From 0b793b6717a631fa2bd7650b670834e5268e8ae6 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Date: Thu, 11 Mar 2021 11:53:13 +0100 Subject: [PATCH 001/262] Create terraform.tf Signed-off-by: Jacob Valdemar Andreasen --- .../techdocs-s3-storage/terraform.tf | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 contrib/terraform/techdocs-s3-storage/terraform.tf diff --git a/contrib/terraform/techdocs-s3-storage/terraform.tf b/contrib/terraform/techdocs-s3-storage/terraform.tf new file mode 100644 index 0000000000..d8d57e9cd6 --- /dev/null +++ b/contrib/terraform/techdocs-s3-storage/terraform.tf @@ -0,0 +1,73 @@ +#========================== +# Variables +#========================== + +variable "backstage" { + default = "backstage" +} + +#========================== +# Bucket +#========================== + +resource "aws_s3_bucket" "backstage" { + bucket = var.backstage + acl = "private" + provider = aws + + lifecycle { + prevent_destroy = true + } + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + } + } + + tags = { + Name = var.backstage + "Managed By Terraform" = var.shared-managed-tag-value + } +} + +resource "aws_s3_bucket_public_access_block" "backstage" { + bucket = aws_s3_bucket.backstage.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + + +#========================== +# IAM +#========================== + +resource "aws_iam_user" "backstage" { + name = var.backstage +} + +resource "aws_iam_user_policy" "backstage" { + name = var.backstage + user = aws_iam_user.backstage.name + policy = data.aws_iam_policy_document.backstage-policy.json +} + +data "aws_iam_policy_document" "backstage-policy" { + statement { + actions = [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucket" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.backstage.arn}", + "${aws_s3_bucket.backstage.arn}/*", + ] + } +} From 602cb4152285c70324e1fdcea01fed3d3565f0a4 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Date: Thu, 11 Mar 2021 11:59:45 +0100 Subject: [PATCH 002/262] Create readme.md Signed-off-by: Jacob Valdemar Andreasen --- contrib/terraform/techdocs-s3-storage/readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 contrib/terraform/techdocs-s3-storage/readme.md diff --git a/contrib/terraform/techdocs-s3-storage/readme.md b/contrib/terraform/techdocs-s3-storage/readme.md new file mode 100644 index 0000000000..9615cc8d13 --- /dev/null +++ b/contrib/terraform/techdocs-s3-storage/readme.md @@ -0,0 +1 @@ +This terraform file should create a S3 bucket and setup IAM with a user with an inline policy which gives the user access to the bucket. After you have created the bucket, user and policy you should go to the user in the AWS console and create an access key. This access key should be used as the env variables in step 3a [here](https://backstage.io/docs/features/techdocs/using-cloud-storage#configuring-aws-s3-bucket-with-techdocs). From 3eb3f81a4d177ad324ac2684637c31a0af8e9dff Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Thu, 11 Mar 2021 12:22:06 +0100 Subject: [PATCH 003/262] Update documentation Signed-off-by: Jacob Valdemar Andreasen --- docs/features/techdocs/using-cloud-storage.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index fd8f320859..2f5828331d 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -120,6 +120,7 @@ techdocs: Create a dedicated AWS S3 bucket for the storage of TechDocs sites. [Refer to the official documentation](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-bucket.html). +[Terraform example](https://github.com/backstage/backstage/blob/master/contrib/terraform/techdocs-s3-storage/terraform.tf). TechDocs will publish documentation to this bucket and will fetch files from here to serve documentation in Backstage. Note that the bucket names are @@ -142,7 +143,9 @@ variables** You should follow the [AWS security best practices guide for authentication](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html). -TechDocs needs access to read files and metadata of the S3 bucket. +TechDocs needs access to read files and metadata of the S3 bucket. So if you are +creating a policy for a user you want to make sure it is granted access to +ListBucket, GetObject and PutObject. If the environment variables From 65a4980f3f1afec0e7431189a6367e9581dd35c9 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Thu, 11 Mar 2021 12:30:01 +0100 Subject: [PATCH 004/262] Fix typo Signed-off-by: Jacob Valdemar Andreasen --- docs/features/techdocs/using-cloud-storage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index 2f5828331d..f10b379757 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -145,7 +145,7 @@ You should follow the TechDocs needs access to read files and metadata of the S3 bucket. So if you are creating a policy for a user you want to make sure it is granted access to -ListBucket, GetObject and PutObject. +ListObjects, GetObject and PutObject. If the environment variables From f22a8edaafcba019cf4dcc3b53e0e56a81f3590c Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Wed, 17 Mar 2021 10:15:48 +0100 Subject: [PATCH 005/262] Add and change terraform variables Signed-off-by: Jacob Valdemar Andreasen --- contrib/terraform/techdocs-s3-storage/terraform.tf | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/contrib/terraform/techdocs-s3-storage/terraform.tf b/contrib/terraform/techdocs-s3-storage/terraform.tf index d8d57e9cd6..6dea091492 100644 --- a/contrib/terraform/techdocs-s3-storage/terraform.tf +++ b/contrib/terraform/techdocs-s3-storage/terraform.tf @@ -3,9 +3,17 @@ #========================== variable "backstage" { + default = "backstage_bucket_for_my_corp" +} + +variable "backstage-iam" { default = "backstage" } +variable "shared-managed-tag-value" { + default = "terraform_for_my_corp" +} + #========================== # Bucket #========================== @@ -48,11 +56,11 @@ resource "aws_s3_bucket_public_access_block" "backstage" { #========================== resource "aws_iam_user" "backstage" { - name = var.backstage + name = var.backstage-iam } resource "aws_iam_user_policy" "backstage" { - name = var.backstage + name = var.backstage-iam user = aws_iam_user.backstage.name policy = data.aws_iam_policy_document.backstage-policy.json } From 69d9259d260be837beeec5a6483223cb5a4419f8 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Date: Thu, 11 Mar 2021 11:53:13 +0100 Subject: [PATCH 006/262] Create terraform.tf Signed-off-by: Jacob Valdemar Andreasen --- .../techdocs-s3-storage/terraform.tf | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 contrib/terraform/techdocs-s3-storage/terraform.tf diff --git a/contrib/terraform/techdocs-s3-storage/terraform.tf b/contrib/terraform/techdocs-s3-storage/terraform.tf new file mode 100644 index 0000000000..d8d57e9cd6 --- /dev/null +++ b/contrib/terraform/techdocs-s3-storage/terraform.tf @@ -0,0 +1,73 @@ +#========================== +# Variables +#========================== + +variable "backstage" { + default = "backstage" +} + +#========================== +# Bucket +#========================== + +resource "aws_s3_bucket" "backstage" { + bucket = var.backstage + acl = "private" + provider = aws + + lifecycle { + prevent_destroy = true + } + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + } + } + + tags = { + Name = var.backstage + "Managed By Terraform" = var.shared-managed-tag-value + } +} + +resource "aws_s3_bucket_public_access_block" "backstage" { + bucket = aws_s3_bucket.backstage.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + + +#========================== +# IAM +#========================== + +resource "aws_iam_user" "backstage" { + name = var.backstage +} + +resource "aws_iam_user_policy" "backstage" { + name = var.backstage + user = aws_iam_user.backstage.name + policy = data.aws_iam_policy_document.backstage-policy.json +} + +data "aws_iam_policy_document" "backstage-policy" { + statement { + actions = [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucket" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.backstage.arn}", + "${aws_s3_bucket.backstage.arn}/*", + ] + } +} From 74748a99a0790fb28431282809a5eda14ba4506d Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Date: Thu, 11 Mar 2021 11:59:45 +0100 Subject: [PATCH 007/262] Create readme.md Signed-off-by: Jacob Valdemar Andreasen --- contrib/terraform/techdocs-s3-storage/readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 contrib/terraform/techdocs-s3-storage/readme.md diff --git a/contrib/terraform/techdocs-s3-storage/readme.md b/contrib/terraform/techdocs-s3-storage/readme.md new file mode 100644 index 0000000000..9615cc8d13 --- /dev/null +++ b/contrib/terraform/techdocs-s3-storage/readme.md @@ -0,0 +1 @@ +This terraform file should create a S3 bucket and setup IAM with a user with an inline policy which gives the user access to the bucket. After you have created the bucket, user and policy you should go to the user in the AWS console and create an access key. This access key should be used as the env variables in step 3a [here](https://backstage.io/docs/features/techdocs/using-cloud-storage#configuring-aws-s3-bucket-with-techdocs). From 26e8254ef289ef16cb0a3ac43e7318869f3833d6 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Thu, 11 Mar 2021 12:22:06 +0100 Subject: [PATCH 008/262] Update documentation Signed-off-by: Jacob Valdemar Andreasen --- docs/features/techdocs/using-cloud-storage.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index fd8f320859..2f5828331d 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -120,6 +120,7 @@ techdocs: Create a dedicated AWS S3 bucket for the storage of TechDocs sites. [Refer to the official documentation](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-bucket.html). +[Terraform example](https://github.com/backstage/backstage/blob/master/contrib/terraform/techdocs-s3-storage/terraform.tf). TechDocs will publish documentation to this bucket and will fetch files from here to serve documentation in Backstage. Note that the bucket names are @@ -142,7 +143,9 @@ variables** You should follow the [AWS security best practices guide for authentication](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html). -TechDocs needs access to read files and metadata of the S3 bucket. +TechDocs needs access to read files and metadata of the S3 bucket. So if you are +creating a policy for a user you want to make sure it is granted access to +ListBucket, GetObject and PutObject. If the environment variables From 5da1459aeae6b196203fba71b0c0473211a083d6 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Thu, 11 Mar 2021 12:30:01 +0100 Subject: [PATCH 009/262] Fix typo Signed-off-by: Jacob Valdemar Andreasen --- docs/features/techdocs/using-cloud-storage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index 2f5828331d..f10b379757 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -145,7 +145,7 @@ You should follow the TechDocs needs access to read files and metadata of the S3 bucket. So if you are creating a policy for a user you want to make sure it is granted access to -ListBucket, GetObject and PutObject. +ListObjects, GetObject and PutObject. If the environment variables From ea0723fd5f4bcc656b3d219cad335341f7fec6d8 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Wed, 17 Mar 2021 10:15:48 +0100 Subject: [PATCH 010/262] Add and change terraform variables Signed-off-by: Jacob Valdemar Andreasen --- contrib/terraform/techdocs-s3-storage/terraform.tf | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/contrib/terraform/techdocs-s3-storage/terraform.tf b/contrib/terraform/techdocs-s3-storage/terraform.tf index d8d57e9cd6..6dea091492 100644 --- a/contrib/terraform/techdocs-s3-storage/terraform.tf +++ b/contrib/terraform/techdocs-s3-storage/terraform.tf @@ -3,9 +3,17 @@ #========================== variable "backstage" { + default = "backstage_bucket_for_my_corp" +} + +variable "backstage-iam" { default = "backstage" } +variable "shared-managed-tag-value" { + default = "terraform_for_my_corp" +} + #========================== # Bucket #========================== @@ -48,11 +56,11 @@ resource "aws_s3_bucket_public_access_block" "backstage" { #========================== resource "aws_iam_user" "backstage" { - name = var.backstage + name = var.backstage-iam } resource "aws_iam_user_policy" "backstage" { - name = var.backstage + name = var.backstage-iam user = aws_iam_user.backstage.name policy = data.aws_iam_policy_document.backstage-policy.json } From c65a85afb691700ddb795f2a4b9d9dc0b2648a13 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Wed, 7 Apr 2021 12:32:43 +0200 Subject: [PATCH 011/262] Change terraform variable and fix typo in docs Signed-off-by: Jacob Valdemar Andreasen --- contrib/terraform/techdocs-s3-storage/terraform.tf | 6 +++--- docs/features/techdocs/using-cloud-storage.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/terraform/techdocs-s3-storage/terraform.tf b/contrib/terraform/techdocs-s3-storage/terraform.tf index 6dea091492..ca267f0f12 100644 --- a/contrib/terraform/techdocs-s3-storage/terraform.tf +++ b/contrib/terraform/techdocs-s3-storage/terraform.tf @@ -2,7 +2,7 @@ # Variables #========================== -variable "backstage" { +variable "backstage-bucket" { default = "backstage_bucket_for_my_corp" } @@ -19,7 +19,7 @@ variable "shared-managed-tag-value" { #========================== resource "aws_s3_bucket" "backstage" { - bucket = var.backstage + bucket = var.backstage-bucket acl = "private" provider = aws @@ -36,7 +36,7 @@ resource "aws_s3_bucket" "backstage" { } tags = { - Name = var.backstage + Name = var.backstage-bucket "Managed By Terraform" = var.shared-managed-tag-value } } diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index f10b379757..2f5828331d 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -145,7 +145,7 @@ You should follow the TechDocs needs access to read files and metadata of the S3 bucket. So if you are creating a policy for a user you want to make sure it is granted access to -ListObjects, GetObject and PutObject. +ListBucket, GetObject and PutObject. If the environment variables From 5d8339cfee72a399a748e80b025f40009d409559 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 9 Apr 2021 14:26:37 +0200 Subject: [PATCH 012/262] some more tests Signed-off-by: blam --- cypress/cypress.json | 2 +- cypress/src/integration/integrations.ts | 45 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 cypress/src/integration/integrations.ts diff --git a/cypress/cypress.json b/cypress/cypress.json index ebbbe59901..59f7516c47 100644 --- a/cypress/cypress.json +++ b/cypress/cypress.json @@ -1,5 +1,5 @@ { - "baseUrl": "http://localhost:7000", + "baseUrl": "http://localhost:3000", "integrationFolder": "./src/integration", "supportFile": "./src/support", "fixturesFolder": "./src/fixures", diff --git a/cypress/src/integration/integrations.ts b/cypress/src/integration/integrations.ts new file mode 100644 index 0000000000..76d0b6b28a --- /dev/null +++ b/cypress/src/integration/integrations.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 'os'; + +describe('Integrations', () => { + describe('ReadTree', () => { + // it('should work for azure', () => { + // cy.loginAsGuest(); + + // cy.visit('/catalog-import'); + + // cy.get('input[name=url]').type( + // 'https://dev.azure.com/backstage-verification/_git/test-repo?path=%2Fnested%2F*', + // ); + + // cy.contains('Analyze').click(); + // }); + + it('should work for github', () => { + cy.loginAsGuest(); + + cy.visit('/catalog-import'); + + cy.get('input[name=url]').type( + 'https://github.com/backstage-verification/test-repo', + ); + + cy.contains('Analyze').click(); + }); + }); +}); From 382531e50195a22cbde71b91e2107a184a40b09c Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 12 Apr 2021 10:21:42 +0200 Subject: [PATCH 013/262] chore: more work towards fixing Signed-off-by: blam --- cypress/src/integration/integrations.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cypress/src/integration/integrations.ts b/cypress/src/integration/integrations.ts index 76d0b6b28a..839159d34e 100644 --- a/cypress/src/integration/integrations.ts +++ b/cypress/src/integration/integrations.ts @@ -38,6 +38,11 @@ describe('Integrations', () => { cy.get('input[name=url]').type( 'https://github.com/backstage-verification/test-repo', ); + cy.request('/api/catalog/locations', { + target: + 'https://github.com/backstage-verification/test-repo/blob/main/**/*', + type: 'url', + }); cy.contains('Analyze').click(); }); From 9afcac5af9d579b7252b3c588e81f81da1b4f7cb Mon Sep 17 00:00:00 2001 From: Ilya Lyamkin Date: Fri, 16 Apr 2021 16:59:26 +0200 Subject: [PATCH 014/262] Pass NavLinkProps to SidebarItem Signed-off-by: Ilya Lyamkin --- .changeset/healthy-phones-press.md | 5 +++++ packages/core/src/layout/Sidebar/Items.tsx | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changeset/healthy-phones-press.md diff --git a/.changeset/healthy-phones-press.md b/.changeset/healthy-phones-press.md new file mode 100644 index 0000000000..c771caefc5 --- /dev/null +++ b/.changeset/healthy-phones-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Allow passing NavLinkProps to SidebarItem component to use in NavLink diff --git a/packages/core/src/layout/Sidebar/Items.tsx b/packages/core/src/layout/Sidebar/Items.tsx index e41a45a225..7c9c0a901f 100644 --- a/packages/core/src/layout/Sidebar/Items.tsx +++ b/packages/core/src/layout/Sidebar/Items.tsx @@ -32,7 +32,7 @@ import React, { useContext, useState, } from 'react'; -import { NavLink } from 'react-router-dom'; +import { NavLink, NavLinkProps } from 'react-router-dom'; import { sidebarConfig, SidebarContext } from './config'; const useStyles = makeStyles(theme => { @@ -138,7 +138,7 @@ type SidebarItemButtonProps = SidebarItemBaseProps & { type SidebarItemLinkProps = SidebarItemBaseProps & { to: string; onClick?: (ev: React.MouseEvent) => void; -}; +} & NavLinkProps; type SidebarItemProps = SidebarItemButtonProps | SidebarItemLinkProps; @@ -156,6 +156,7 @@ export const SidebarItem = forwardRef((props, ref) => { onClick, children, className, + ...navLinkProps } = props; const classes = useStyles(); // XXX (@koroeskohr): unsure this is optimal. But I just really didn't want to have the item component @@ -216,6 +217,7 @@ export const SidebarItem = forwardRef((props, ref) => { activeClassName={classes.selected} to={props.to} ref={ref} + {...navLinkProps} > {content} From 94da2097671c0369278eef8eda4a68bc3c26c702 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 19 Apr 2021 19:39:37 +0200 Subject: [PATCH 015/262] Sort the table filter options by name Signed-off-by: Dominik Henneke --- .changeset/chatty-parents-search.md | 5 +++++ packages/core/src/components/Table/Table.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/chatty-parents-search.md diff --git a/.changeset/chatty-parents-search.md b/.changeset/chatty-parents-search.md new file mode 100644 index 0000000000..d9b1222d8f --- /dev/null +++ b/.changeset/chatty-parents-search.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Sort the table filter options by name. diff --git a/packages/core/src/components/Table/Table.tsx b/packages/core/src/components/Table/Table.tsx index d061be6d60..2251b8304e 100644 --- a/packages/core/src/components/Table/Table.tsx +++ b/packages/core/src/components/Table/Table.tsx @@ -363,7 +363,7 @@ export function Table({ placeholder: 'All results', label: filter.column, multiple: filter.type === 'multiple-select', - items: [...extractDistinctValues(filter.column)].map(value => ({ + items: [...extractDistinctValues(filter.column)].sort().map(value => ({ label: value, value, })), From 9b9a8f39b60ba68aa21b518f012e6878c51a76af Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 19 Apr 2021 20:35:56 -0400 Subject: [PATCH 016/262] Remove WIP Signed-off-by: Adam Harvey --- plugins/catalog/README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/plugins/catalog/README.md b/plugins/catalog/README.md index e9405a41f5..2940fecaa1 100644 --- a/plugins/catalog/README.md +++ b/plugins/catalog/README.md @@ -1,12 +1,25 @@ -# Catalog Frontend - -WORK IN PROGRESS +# Backstage Catalog Frontend This is the frontend part of the default catalog plugin. It will implement the core API for handling your catalog of software, and supply the base views to show and manage them. +## Getting Started + +This frontend plugin can be started in a standalone mode from directly in this package +with `yarn start`. However, it will have limited functionality and that process is +most convenient when developing the catalog frontend plugin itself. + +To evaluate the catalog and have a greater amount of functionality available, from the main +Backstage root folder, instead do: + +```bash +yarn dev +``` + +This will launch both the front and backend in same window, populated some example entities. + ## Links - [Backend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend) From 0604a3a9e71931f82b6377eb74030bfa8e1fc914 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Tue, 20 Apr 2021 08:16:30 +0200 Subject: [PATCH 017/262] Added Austalian Greeting Signed-off-by: Brett Wright --- .../CatalogPage/utils/locales/goodAfternoon.locales.json | 1 + .../CatalogPage/utils/locales/goodEvening.locales.json | 1 + .../CatalogPage/utils/locales/goodMorning.locales.json | 1 + 3 files changed, 3 insertions(+) diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json index 4d48666666..ad3c4e4634 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json @@ -11,6 +11,7 @@ "Armenian": "Բարի կէսօր:", "Assamese": "শুভ আবেলি", "Asturian": "Bones tardes", + "Australian": "G'day mate", "Azerbaijani": "Günortanız xeyir", "Bashkir": "хәйерле көн", "Basque": "Arratsalde on", diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json index 890899fcf3..ed68d0332e 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json @@ -10,6 +10,7 @@ "Asante": "Maadwó", "Asturian": "Bona nuechi", "Ateso": "Akwar najokan", + "Australian": "G'day mate", "Aymara": "Winas tartis", "Azerbaijani": "Axşamınız xeyir", "Basque": "Arratsalde on", diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json index febbc32c49..b906155426 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json @@ -4,6 +4,7 @@ "Albanian": "Mirëmëngjes", "Arabic": "صباح الخير", "Armenian": "Paree looys", + "Australian": "G'day mate", "Azerbaijani": "Sabahınız xeyir", "Bengali": "shuprobhat", "Bulgarian": "Dobro utro", From f8585183748910df996d0104629649e34cf5985a Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Tue, 20 Apr 2021 08:20:23 +0200 Subject: [PATCH 018/262] Added changeset Signed-off-by: Brett Wright --- .changeset/gorgeous-pumas-cover.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/gorgeous-pumas-cover.md diff --git a/.changeset/gorgeous-pumas-cover.md b/.changeset/gorgeous-pumas-cover.md new file mode 100644 index 0000000000..c4c9facac4 --- /dev/null +++ b/.changeset/gorgeous-pumas-cover.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-welcome': patch +--- + +Australian Greeting From 40d1e11cf36f83ee62b5e5e285dd3e629dfabebc Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 19 Apr 2021 19:58:47 +0200 Subject: [PATCH 019/262] Add a FossaPage that shows the license compliance status of all components in the catalog Signed-off-by: Dominik Henneke --- .changeset/unlucky-starfishes-vanish.md | 21 + plugins/fossa/README.md | 48 +++ plugins/fossa/dev/index.tsx | 74 +++- plugins/fossa/docs/fossa-overview.png | Bin 0 -> 375035 bytes plugins/fossa/package.json | 4 + plugins/fossa/src/api/FossaApi.ts | 14 + plugins/fossa/src/api/FossaClient.test.ts | 378 ++++++++++++------ plugins/fossa/src/api/FossaClient.ts | 132 ++++-- .../components/FossaCard/FossaCard.test.tsx | 186 +++++++++ .../src/components/FossaCard/FossaCard.tsx | 208 +++++----- .../components/FossaPage/FossaPage.test.tsx | 134 +++++++ .../src/components/FossaPage/FossaPage.tsx | 228 +++++++++++ .../fossa/src/components/FossaPage/index.ts | 17 + .../src/components/useProjectName.test.ts | 38 ++ .../src/components/useProjectNames.test.ts | 45 +++ .../fossa/src/components/useProjectNames.ts | 33 ++ plugins/fossa/src/extensions.tsx | 13 +- plugins/fossa/src/index.ts | 2 +- plugins/fossa/src/plugin.ts | 4 + plugins/fossa/src/routes.ts | 21 + 20 files changed, 1350 insertions(+), 250 deletions(-) create mode 100644 .changeset/unlucky-starfishes-vanish.md create mode 100644 plugins/fossa/docs/fossa-overview.png create mode 100644 plugins/fossa/src/components/FossaCard/FossaCard.test.tsx create mode 100644 plugins/fossa/src/components/FossaPage/FossaPage.test.tsx create mode 100644 plugins/fossa/src/components/FossaPage/FossaPage.tsx create mode 100644 plugins/fossa/src/components/FossaPage/index.ts create mode 100644 plugins/fossa/src/components/useProjectName.test.ts create mode 100644 plugins/fossa/src/components/useProjectNames.test.ts create mode 100644 plugins/fossa/src/components/useProjectNames.ts create mode 100644 plugins/fossa/src/routes.ts diff --git a/.changeset/unlucky-starfishes-vanish.md b/.changeset/unlucky-starfishes-vanish.md new file mode 100644 index 0000000000..90ee10a81a --- /dev/null +++ b/.changeset/unlucky-starfishes-vanish.md @@ -0,0 +1,21 @@ +--- +'@backstage/plugin-fossa': patch +--- + +Add a `FossaPage` that shows the license compliance status of all components in the catalog. +This is an optional component that can be registered as a route: + +```diff +// packages/app/src/App.tsx + ++ import { FossaPage } from '@backstage/plugin-fossa'; + +// ... + + const routes = ( + + // ... ++ } /> + + ); +``` diff --git a/plugins/fossa/README.md b/plugins/fossa/README.md index 722d8d2cf3..049a1c25cb 100644 --- a/plugins/fossa/README.md +++ b/plugins/fossa/README.md @@ -75,3 +75,51 @@ spec: owner: CNCF lifecycle: experimental ``` + +## Other Components + +### FOSSA Overview Page + +The plugin provides an optional page that can be used to check the license compliance of all components. + +![FOSSA Overview](./docs/fossa-overview.png) + +Add it to your Backstage application: + +1. Install the FOSSA Plugin (see [Getting Started](#getting-started)). + +2. Register the page: + +```tsx +// packages/app/src/App.tsx + +import { FossaPage } from '@backstage/plugin-fossa'; + +// ... + +const routes = ( + + // ... + } /> + +); +``` + +3. (Optional) Add a Sidebar Icon: + +```tsx +// packages/app/src/components/Root/Root.tsx + +// ... + +export const Root = ({ children }: PropsWithChildren<{}>) => ( + + + // ... + + // ... + + {children} + +); +``` diff --git a/plugins/fossa/dev/index.tsx b/plugins/fossa/dev/index.tsx index 06c71c48b7..9625b24dc2 100644 --- a/plugins/fossa/dev/index.tsx +++ b/plugins/fossa/dev/index.tsx @@ -14,14 +14,19 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; +import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; import { Content, Header, Page } from '@backstage/core'; import { createDevApp } from '@backstage/dev-utils'; -import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { + CatalogApi, + catalogApiRef, + EntityProvider, +} from '@backstage/plugin-catalog-react'; import { Grid } from '@material-ui/core'; import React from 'react'; -import { EntityFossaCard } from '../src'; -import { FossaApi, fossaApiRef } from '../src/api'; +import { EntityFossaCard, fossaPlugin } from '../src'; +import { FindingSummary, FossaApi, fossaApiRef } from '../src/api'; +import { FossaPage } from '../src/components/FossaPage'; import { FOSSA_PROJECT_NAME_ANNOTATION } from '../src/components/useProjectName'; const entity = (name?: string) => @@ -34,9 +39,16 @@ const entity = (name?: string) => }, name: name, }, + relations: [ + { + type: RELATION_OWNED_BY, + target: { kind: 'Group', namespace: 'default', name }, + }, + ], } as Entity); createDevApp() + .registerPlugin(fossaPlugin) .registerApi({ api: fossaApiRef, deps: {}, @@ -81,8 +93,58 @@ createDevApp() return undefined; } }, + getFindingSummaries: async () => { + await new Promise(r => setTimeout(r, 1000)); + + return new Map([ + [ + 'zero-deps', + { + timestamp: '2000-01-01T00:00:00Z', + projectUrl: '', + projectDefaultBranch: 'master', + issueCount: 0, + dependencyCount: 0, + }, + ], + [ + 'issues', + { + timestamp: '2001-01-01T00:00:00Z', + projectUrl: '', + projectDefaultBranch: 'develop', + issueCount: 10, + dependencyCount: 15, + }, + ], + [ + 'no-issues', + { + timestamp: '2002-01-01T00:00:00Z', + projectUrl: '', + projectDefaultBranch: 'master', + issueCount: 0, + dependencyCount: 5, + }, + ], + ]); + }, } as FossaApi), }) + .registerApi({ + api: catalogApiRef, + deps: {}, + factory: () => + (({ + getEntities: async () => { + await new Promise(r => setTimeout(r, 1000)); + + return { + items: [entity('zero-deps'), entity('issues'), entity('no-issues')], + }; + }, + } as Partial) as any), + }) .addPage({ title: 'Entity Content', element: ( @@ -130,4 +192,8 @@ createDevApp() ), }) + .addPage({ + title: 'Catalog Overview', + element: , + }) .render(); diff --git a/plugins/fossa/docs/fossa-overview.png b/plugins/fossa/docs/fossa-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..2c6dd972312d50bfc678dc5a2dcf5063e38965cc GIT binary patch literal 375035 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 +P|_a7WOK(M9bA9ykmd7 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%0Adyv^458nhwg2y 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

%XTkq>>*!J-9W`*k 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 literal 0 HcmV?d00001 diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index fd94c6b906..39da3638ec 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -33,12 +33,15 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/core": "^0.7.5", + "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", "cross-fetch": "^3.0.6", + "luxon": "^1.26.0", + "p-limit": "^3.0.2", "react": "^16.13.1", "react-dom": "^16.13.1", "react-use": "^15.3.3" @@ -49,6 +52,7 @@ "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", + "@testing-library/react-hooks": "^3.4.2", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", diff --git a/plugins/fossa/src/api/FossaApi.ts b/plugins/fossa/src/api/FossaApi.ts index 84406e1b1a..15e8b4473e 100644 --- a/plugins/fossa/src/api/FossaApi.ts +++ b/plugins/fossa/src/api/FossaApi.ts @@ -30,5 +30,19 @@ export const fossaApiRef = createApiRef({ }); export type FossaApi = { + /** + * Get the finding summary for a list of projects + * + * @param projectTitles a list of project titles in FOSSA + */ + getFindingSummaries( + projectTitles: Array, + ): Promise>; + + /** + * Get the finding summary of a single project. + * + * @param projectTitle the project title in FOSSA + */ getFindingSummary(projectTitle: string): Promise; }; diff --git a/plugins/fossa/src/api/FossaClient.test.ts b/plugins/fossa/src/api/FossaClient.test.ts index 820210e2b6..24bcad526c 100644 --- a/plugins/fossa/src/api/FossaClient.test.ts +++ b/plugins/fossa/src/api/FossaClient.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { UrlPatternDiscovery, IdentityApi } from '@backstage/core'; +import { IdentityApi, UrlPatternDiscovery } from '@backstage/core'; import { msw } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -52,138 +52,266 @@ describe('FossaClient', () => { }); }); - it('should report finding summary', async () => { - server.use( - rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { - expect(req.url.searchParams.toString()).toBe( - 'count=1&sort=title+&title=our-service&organizationId=8736', - ); - return res( - ctx.json([ + describe('getFindingSummary', () => { + it('should report finding summary', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { + const expectedQuery = + 'count=1000&page=0&sort=title%2B&organizationId=8736&title=our-service'; + if (req.url.searchParams.toString() !== expectedQuery) { + return res( + ctx.status(500), + ctx.body( + `${req.url.searchParams.toString()} !== ${expectedQuery}`, + ), + ); + } + + return res( + ctx.json([ + { + locator: 'custom+8736/our-service', + title: 'our-service', + default_branch: 'develop', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_licensing_issue_count: 5, + unresolved_issue_count: 100, + }, + ], + }, + ]), + ); + }), + ); + + const summary = await client.getFindingSummary('our-service'); + + expect(summary).toEqual({ + timestamp: '2020-01-01T00:00:00Z', + issueCount: 5, + dependencyCount: 160, + projectDefaultBranch: 'develop', + projectUrl: + 'https://app.fossa.com/projects/custom%2B8736%2Four-service', + } as FindingSummary); + }); + + it('should report finding summary without licensing_issue_count', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { + return res( + ctx.json([ + { + locator: 'custom+8736/our-service', + title: 'our-service', + default_branch: 'refs/master', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_issue_count: 100, + }, + ], + }, + ]), + ); + }), + ); + + const summary = await client.getFindingSummary('our-service'); + + expect(summary).toEqual({ + timestamp: '2020-01-01T00:00:00Z', + issueCount: 100, + dependencyCount: 160, + projectDefaultBranch: 'refs/master', + projectUrl: + 'https://app.fossa.com/projects/custom%2B8736%2Four-service', + } as FindingSummary); + }); + + it('should handle empty result', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { + return res(ctx.json([])); + }), + ); + + const summary = await client.getFindingSummary('our-service'); + + expect(summary).toBeUndefined(); + }); + + it('should ignore result with invalid title', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { + return res(ctx.json([{ title: 'our-service-2' }])); + }), + ); + + const summary = await client.getFindingSummary('our-service'); + + expect(summary).toBeUndefined(); + }); + + it('should skip organizationId', async () => { + client = new FossaClient({ discoveryApi, identityApi }); + + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { + const expectedQuery = + 'count=1000&page=0&sort=title%2B&title=our-service'; + if (req.url.searchParams.toString() !== expectedQuery) { + return res( + ctx.status(500), + ctx.body( + `${req.url.searchParams.toString()} !== ${expectedQuery}`, + ), + ); + } + + return res(ctx.json([])); + }), + ); + + const summary = await client.getFindingSummary('our-service'); + + expect(summary).toBeUndefined(); + }); + + it('should handle 404 status', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { + return res(ctx.status(404)); + }), + ); + + await expect(client.getFindingSummary('our-service')).rejects.toThrow(); + }); + }); + + describe('getFindingSummaries', () => { + it('should report finding summary', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { + const expectedQuery = + 'count=1000&page=0&sort=title%2B&organizationId=8736'; + if (req.url.searchParams.toString() !== expectedQuery) { + return res( + ctx.status(500), + ctx.body( + `${req.url.searchParams.toString()} !== ${expectedQuery}`, + ), + ); + } + + return res( + ctx.json([ + { + locator: 'custom+8736/our-service', + title: 'our-service', + default_branch: 'develop', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_licensing_issue_count: 5, + unresolved_issue_count: 100, + }, + ], + }, + { + locator: 'custom+8736/our-service-2', + title: 'our-service-2', + default_branch: 'develop', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_licensing_issue_count: 5, + unresolved_issue_count: 100, + }, + ], + }, + { + locator: 'custom+8736/our-service-3', + title: 'our-service-3', + default_branch: 'develop', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_licensing_issue_count: 5, + unresolved_issue_count: 100, + }, + ], + }, + ]), + ); + }), + ); + + const summary = await client.getFindingSummaries([ + 'our-service', + 'our-service-2', + ]); + + expect(summary).toEqual( + new Map([ + [ + 'our-service', { - locator: 'custom+8736/our-service', - title: 'our-service', - default_branch: 'develop', - revisions: [ - { - updatedAt: '2020-01-01T00:00:00Z', - dependency_count: 160, - unresolved_licensing_issue_count: 5, - unresolved_issue_count: 100, - }, - ], + timestamp: '2020-01-01T00:00:00Z', + issueCount: 5, + dependencyCount: 160, + projectDefaultBranch: 'develop', + projectUrl: + 'https://app.fossa.com/projects/custom%2B8736%2Four-service', }, - ]), - ); - }), - ); - - const summary = await client.getFindingSummary('our-service'); - - expect(summary).toEqual({ - timestamp: '2020-01-01T00:00:00Z', - issueCount: 5, - dependencyCount: 160, - projectDefaultBranch: 'develop', - projectUrl: 'https://app.fossa.com/projects/custom%2B8736%2Four-service', - } as FindingSummary); - }); - - it('should report finding summary without licensing_issue_count', async () => { - server.use( - rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { - expect(req.url.searchParams.toString()).toBe( - 'count=1&sort=title+&title=our-service&organizationId=8736', - ); - return res( - ctx.json([ + ], + [ + 'our-service-2', { - locator: 'custom+8736/our-service', - title: 'our-service', - default_branch: 'refs/master', - revisions: [ - { - updatedAt: '2020-01-01T00:00:00Z', - dependency_count: 160, - unresolved_issue_count: 100, - }, - ], + timestamp: '2020-01-01T00:00:00Z', + issueCount: 5, + dependencyCount: 160, + projectDefaultBranch: 'develop', + projectUrl: + 'https://app.fossa.com/projects/custom%2B8736%2Four-service-2', }, - ]), - ); - }), - ); + ], + ]), + ); + }); - const summary = await client.getFindingSummary('our-service'); + it('should handle empty result', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { + return res(ctx.json([])); + }), + ); - expect(summary).toEqual({ - timestamp: '2020-01-01T00:00:00Z', - issueCount: 100, - dependencyCount: 160, - projectDefaultBranch: 'refs/master', - projectUrl: 'https://app.fossa.com/projects/custom%2B8736%2Four-service', - } as FindingSummary); - }); + const summary = await client.getFindingSummaries([ + 'our-service', + 'our-service-2', + ]); - it('should handle empty result', async () => { - server.use( - rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { - expect(req.url.searchParams.toString()).toBe( - 'count=1&sort=title+&title=our-service&organizationId=8736', - ); - return res(ctx.json([])); - }), - ); + expect(summary).toEqual(new Map()); + }); - const summary = await client.getFindingSummary('our-service'); + it('should handle 404 status', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { + return res(ctx.status(404)); + }), + ); - expect(summary).toBeUndefined(); - }); - - it('should ignore result with invalid title', async () => { - server.use( - rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { - expect(req.url.searchParams.toString()).toBe( - 'count=1&sort=title+&title=our-service&organizationId=8736', - ); - return res(ctx.json([{ title: 'our-service-2' }])); - }), - ); - - const summary = await client.getFindingSummary('our-service'); - - expect(summary).toBeUndefined(); - }); - - it('should skip organizationId', async () => { - client = new FossaClient({ discoveryApi, identityApi }); - - server.use( - rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { - expect(req.url.searchParams.toString()).toBe( - 'count=1&sort=title+&title=our-service', - ); - return res(ctx.status(404)); - }), - ); - - const summary = await client.getFindingSummary('our-service'); - - expect(summary).toBeUndefined(); - }); - - it('should handle 404 status', async () => { - server.use( - rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { - expect(req.url.searchParams.toString()).toBe( - 'count=1&sort=title+&title=our-service&organizationId=8736', - ); - return res(ctx.status(404)); - }), - ); - - const summary = await client.getFindingSummary('our-service'); - - expect(summary).toBeUndefined(); + await expect( + client.getFindingSummaries(['our-service', 'our-service-2']), + ).rejects.toThrow(); + }); }); }); diff --git a/plugins/fossa/src/api/FossaClient.ts b/plugins/fossa/src/api/FossaClient.ts index 5693895901..fb5eb80345 100644 --- a/plugins/fossa/src/api/FossaClient.ts +++ b/plugins/fossa/src/api/FossaClient.ts @@ -15,13 +15,28 @@ */ import { DiscoveryApi, IdentityApi } from '@backstage/core'; +import { ResponseError } from '@backstage/errors'; import fetch from 'cross-fetch'; +import pLimit from 'p-limit'; import { FindingSummary, FossaApi } from './FossaApi'; +type FossaProjectsResponse = { + title: string; + default_branch: string; + locator: string; + revisions: Array<{ + updatedAt: string; + unresolved_licensing_issue_count: number; + unresolved_issue_count: number; + dependency_count: number; + }>; +}; + export class FossaClient implements FossaApi { discoveryApi: DiscoveryApi; identityApi: IdentityApi; organizationId?: string; + private readonly limit = pLimit(5); constructor({ discoveryApi, @@ -37,42 +52,101 @@ export class FossaClient implements FossaApi { this.organizationId = organizationId; } - private async callApi(path: string): Promise { + private async callApi( + path: string, + query: Record, + ): Promise { const apiUrl = `${await this.discoveryApi.getBaseUrl('proxy')}/fossa`; const idToken = await this.identityApi.getIdToken(); - const response = await fetch(`${apiUrl}/${path}`, { - headers: idToken ? { Authorization: `Bearer ${idToken}` } : {}, - }); - if (response.status === 200) { - return await response.json(); + const response = await fetch( + `${apiUrl}/${path}?${new URLSearchParams(query).toString()}`, + { + headers: idToken ? { Authorization: `Bearer ${idToken}` } : {}, + }, + ); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); } - return undefined; + + return (await response.json()) as T; + } + + async *getProject( + projectTitles: Set, + ): AsyncIterable<{ title: string; summary: FindingSummary }> { + let nextPage = 0; + const pageSize = 1000; + + for (;;) { + const projects = await this.limit( + page => + this.callApi('projects', { + count: pageSize, + page, + sort: 'title+', + ...(this.organizationId && { + organizationId: this.organizationId, + }), + ...(projectTitles.size === 1 && { + title: projectTitles.values().next().value, + }), + }), + nextPage++, + ); + + if (!projects) { + break; + } + + for (const project of projects) { + if (projectTitles.has(project.title) && project.revisions.length > 0) { + const revision = project.revisions[0]; + yield { + title: project.title, + summary: { + timestamp: revision.updatedAt, + issueCount: + revision.unresolved_licensing_issue_count || + revision.unresolved_issue_count, + dependencyCount: revision.dependency_count, + projectDefaultBranch: project.default_branch, + projectUrl: `https://app.fossa.com/projects/${encodeURIComponent( + project.locator, + )}`, + }, + }; + } + } + + if (projects.length < pageSize) { + break; + } + } + } + + async getFindingSummaries( + projectTitles: string[], + ): Promise> { + const map = new Map(); + + if (projectTitles.length === 0) { + return map; + } + + for await (const { title, summary } of this.getProject( + new Set(projectTitles), + )) { + map.set(title, summary); + } + + return map; } async getFindingSummary( projectTitle: string, ): Promise { - const project = await this.callApi( - `projects?count=1&sort=title+&title=${projectTitle}${ - this.organizationId ? `&organizationId=${this.organizationId}` : '' - }`, - ); - - if (!project || project.length === 0 || project[0].title !== projectTitle) { - return undefined; - } - - const revision = project[0].revisions[0]; - return { - timestamp: revision.updatedAt, - issueCount: - revision.unresolved_licensing_issue_count || - revision.unresolved_issue_count, - dependencyCount: revision.dependency_count, - projectDefaultBranch: project[0].default_branch, - projectUrl: `https://app.fossa.com/projects/${encodeURIComponent( - project[0].locator, - )}`, - }; + const summaries = await this.getFindingSummaries([projectTitle]); + return summaries.get(projectTitle); } } diff --git a/plugins/fossa/src/components/FossaCard/FossaCard.test.tsx b/plugins/fossa/src/components/FossaCard/FossaCard.test.tsx new file mode 100644 index 0000000000..0761c85da5 --- /dev/null +++ b/plugins/fossa/src/components/FossaCard/FossaCard.test.tsx @@ -0,0 +1,186 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry } from '@backstage/core'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; +import { FossaApi, fossaApiRef } from '../../api'; +import { FossaCard } from './FossaCard'; + +describe('', () => { + const fossaApi: jest.Mocked = { + getFindingSummary: jest.fn(), + getFindingSummaries: jest.fn(), + }; + let Wrapper: React.ComponentType; + + beforeEach(() => { + const apis = ApiRegistry.with(fossaApiRef, fossaApi); + + Wrapper = ({ children }: { children?: React.ReactNode }) => ( + {children} + ); + }); + + afterEach(() => jest.resetAllMocks()); + + it('shows missing annotation', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name', + }, + }; + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect(getByText(/Missing Annotation/i)).toBeInTheDocument(); + expect(getByText('fossa.io/project-name')).toBeInTheDocument(); + }); + + it('shows error', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name', + annotations: { + 'fossa.io/project-name': 'my-name', + }, + }, + }; + + fossaApi.getFindingSummary.mockRejectedValue(new Error('My Error')); + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect(getByText(/Warning: My Error/i)).toBeInTheDocument(); + }); + + it('shows empty', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name', + annotations: { + 'fossa.io/project-name': 'my-name', + }, + }, + }; + + fossaApi.getFindingSummary.mockResolvedValue(undefined); + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect( + getByText(/There is no Fossa project with title 'my-name'./i), + ).toBeInTheDocument(); + }); + + it('shows fossa issues', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name', + annotations: { + 'fossa.io/project-name': 'my-name', + }, + }, + }; + + fossaApi.getFindingSummary.mockResolvedValue({ + timestamp: '2000-01-01T00:00:00Z', + projectDefaultBranch: 'branch/default-branch', + projectUrl: 'http://…', + issueCount: 0, + dependencyCount: 10, + }); + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect(getByText(/Number of issues/i)).toBeInTheDocument(); + expect( + getByText( + (_, node) => + node?.textContent === + 'Based on 10 Dependencies on branch branch/default-branch.', + ), + ).toBeInTheDocument(); + }); + + it('warns about zero dependencies', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name', + annotations: { + 'fossa.io/project-name': 'my-name', + }, + }, + }; + + fossaApi.getFindingSummary.mockResolvedValue({ + timestamp: '2000-01-01T00:00:00Z', + projectDefaultBranch: 'branch/default-branch', + projectUrl: 'http://…', + issueCount: 0, + dependencyCount: 0, + }); + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect(getByText(/No Dependencies/i)).toBeInTheDocument(); + expect( + getByText(/Please check your FOSSA project settings/i), + ).toBeInTheDocument(); + }); +}); diff --git a/plugins/fossa/src/components/FossaCard/FossaCard.tsx b/plugins/fossa/src/components/FossaCard/FossaCard.tsx index 4cc27f5d03..9d2db263c8 100644 --- a/plugins/fossa/src/components/FossaCard/FossaCard.tsx +++ b/plugins/fossa/src/components/FossaCard/FossaCard.tsx @@ -17,14 +17,17 @@ import { EmptyState, InfoCard, + InfoCardVariants, MissingAnnotationEmptyState, Progress, + ResponseErrorPanel, useApi, } from '@backstage/core'; import { useEntity } from '@backstage/plugin-catalog-react'; import { Grid, Tooltip } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; -import React from 'react'; +import { DateTime } from 'luxon'; +import React, { PropsWithChildren } from 'react'; import { useAsync } from 'react-use'; import { fossaApiRef } from '../../api'; import { @@ -65,109 +68,134 @@ const useStyles = makeStyles(theme => ({ }, })); -export const FossaCard = () => { +const Card = ({ + children, + disabled, + projectUrl, + variant = 'gridItem', +}: PropsWithChildren<{ + disabled?: boolean; + projectUrl?: string; + variant?: InfoCardVariants; +}>) => { + const classes = useStyles(); + + return ( + + {children} + + ); +}; +export const FossaCard = ({ variant }: { variant?: InfoCardVariants }) => { const { entity } = useEntity(); const fossaApi = useApi(fossaApiRef); const projectTitle = useProjectName(entity); - - const { value, loading } = useAsync( + const { value, loading, error } = useAsync( async () => projectTitle ? fossaApi.getFindingSummary(projectTitle) : undefined, [fossaApi, projectTitle], ); - const deepLink = value - ? { - title: 'View more', - link: value.projectUrl, - } - : undefined; - const classes = useStyles(); + if (error) { + return ( + + + + ); + } + + if (loading) { + return ( + + + + ); + } + + if (!projectTitle) { + return ( + + + + ); + } + + if (!value) { + return ( + + + + ); + } + return ( - <> - + - {loading && } - - {!loading && !projectTitle && ( - - )} - - {!loading && projectTitle && !value && ( - - )} - - {value && ( - +

0 || value.dependencyCount === 0 + ? classes.numberError + : classes.numberSuccess + } > - -

0 || value.dependencyCount === 0 - ? classes.numberError - : classes.numberSuccess - } - > - {value.issueCount} -

- {value.dependencyCount > 0 && ( -

Number of issues

- )} - {value.dependencyCount === 0 && ( -

- No Dependencies. -
- Please check your FOSSA project settings. -

- )} - + {value.issueCount} +

+ {value.dependencyCount > 0 && ( +

Number of issues

+ )} + {value.dependencyCount === 0 && ( +

+ No Dependencies. +
+ Please check your FOSSA project settings. +

+ )} + - - Last analyzed on{' '} - {new Date(value.timestamp).toLocaleString('en-US', { - timeZone: 'UTC', - day: 'numeric', - month: 'short', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - hour12: false, - })} - - - Based on {value.dependencyCount} Dependencies on branch{' '} - - - {value.projectDefaultBranch} - - - . - - - )} - - + + Last analyzed on{' '} + {DateTime.fromISO(value.timestamp).toLocaleString( + DateTime.DATETIME_MED, + )} + + + Based on {value.dependencyCount} Dependencies on branch{' '} + + {value.projectDefaultBranch} + + . + + + ); }; diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx new file mode 100644 index 0000000000..efab6ab091 --- /dev/null +++ b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx @@ -0,0 +1,134 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry } from '@backstage/core'; +import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; +import { FossaApi, fossaApiRef } from '../../api'; +import { FossaPage } from './FossaPage'; + +describe('', () => { + const catalogApi: jest.Mocked = { + addLocation: jest.fn(), + getEntities: jest.fn(), + getEntityByName: jest.fn(), + getLocationByEntity: jest.fn(), + getLocationById: jest.fn(), + getOriginLocationByEntity: jest.fn(), + removeEntityByUid: jest.fn(), + removeLocationById: jest.fn(), + }; + const fossaApi: jest.Mocked = { + getFindingSummary: jest.fn(), + getFindingSummaries: jest.fn(), + }; + let Wrapper: React.ComponentType; + + beforeEach(() => { + const apis = ApiRegistry.with(fossaApiRef, fossaApi).with( + catalogApiRef, + catalogApi, + ); + + Wrapper = ({ children }: { children?: React.ReactNode }) => ( + {children} + ); + }); + + afterEach(() => jest.resetAllMocks()); + + it('shows fossa issues', async () => { + const entity0: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name-0', + annotations: { + 'fossa.io/project-name': 'my-name-0', + }, + }, + }; + const entity1: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name-1', + annotations: { + 'fossa.io/project-name': 'my-name-1', + }, + }, + }; + const entity2: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name-2', + annotations: { + 'fossa.io/project-name': 'my-name-2', + }, + }, + }; + const entity3: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-name-3', + }, + }; + + catalogApi.getEntities.mockResolvedValue({ + items: [entity0, entity1, entity2, entity3], + }); + + fossaApi.getFindingSummaries.mockResolvedValue( + new Map([ + [ + 'my-name-1', + { + timestamp: '2000-01-01T00:00:00Z', + projectDefaultBranch: 'branch/default-branch', + projectUrl: 'http://…', + issueCount: 0, + dependencyCount: 0, + }, + ], + [ + 'my-name-2', + { + timestamp: '2000-01-01T00:00:00Z', + projectDefaultBranch: 'branch/default-branch', + projectUrl: 'http://…', + issueCount: 10, + dependencyCount: 10, + }, + ], + ]), + ); + + const { getByText, getAllByText } = await renderInTestApp( + + + , + ); + + expect(getAllByText(/Not configured/i)).toHaveLength(2); + expect(getByText(/No dependencies/i)).toBeInTheDocument(); + expect(getByText(/0 Issues/i)).toBeInTheDocument(); + expect(getByText(/10 Issues/i)).toBeInTheDocument(); + }); +}); diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.tsx new file mode 100644 index 0000000000..05e1379378 --- /dev/null +++ b/plugins/fossa/src/components/FossaPage/FossaPage.tsx @@ -0,0 +1,228 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Entity, + EntityName, + RELATION_OWNED_BY, +} from '@backstage/catalog-model'; +import { + Content, + Header, + Page, + StatusError, + StatusOK, + StatusWarning, + Table, + TableColumn, + TableFilter, + useApi, +} from '@backstage/core'; +import { + catalogApiRef, + EntityRefLink, + EntityRefLinks, + formatEntityRefTitle, + getEntityRelations, +} from '@backstage/plugin-catalog-react'; +import { Tooltip } from '@material-ui/core'; +import { Skeleton } from '@material-ui/lab'; +import { DateTime } from 'luxon'; +import * as React from 'react'; +import { useMemo } from 'react'; +import { useAsync } from 'react-use'; +import { FindingSummary, fossaApiRef } from '../../api'; +import { useProjectNames } from '../useProjectNames'; + +type FossaRow = { + entity: Entity; + resolved: { + name: string; + ownedByRelationsTitle?: string; + ownedByRelations: EntityName[]; + loading: boolean; + details?: FindingSummary; + }; +}; + +const columns: TableColumn[] = [ + { + title: 'Name', + field: 'resolved.name', + highlight: true, + render: ({ entity }) => , + }, + { + title: 'Owner', + field: 'resolved.ownedByRelationsTitle', + highlight: true, + render: ({ resolved }) => ( + + ), + }, + { + title: 'Status', + field: 'resolved.details.issueCount', + // We interpret missing values as '0.5' to be sorted at the end of the projects with issues. + customSort: (a, b) => + (b?.resolved?.details?.issueCount ?? 0.5) - + (a?.resolved?.details?.issueCount ?? 0.5), + render: ({ resolved }) => { + if (resolved.loading) { + return ; + } else if (!resolved.details) { + return Not configured; + } else if (resolved.details.dependencyCount === 0) { + return No dependencies; + } else if (resolved.details.issueCount > 0) { + return {resolved.details.issueCount} Issues; + } + + return {resolved.details.issueCount} Issues; + }, + }, + { + title: 'Dependencies', + field: 'resolved.details.dependencyCount', + render: ({ resolved: { loading, details } }) => { + if (loading) { + return ; + } + + return details?.dependencyCount; + }, + }, + { + title: 'Branch', + field: 'resolved.details.projectDefaultBranch', + render: ({ resolved: { loading, details } }) => { + if (loading) { + return ; + } + + return details?.projectDefaultBranch; + }, + }, + { + title: 'Last Updated', + field: 'resolved.details.timestamp', + render: ({ resolved: { loading, details } }) => { + if (loading) { + return ; + } + + return ( + details?.timestamp && ( + + + {DateTime.fromISO(details.timestamp).toRelative({ + locale: 'en', + })} + + + ) + ); + }, + }, +]; + +const filters: TableFilter[] = [ + { column: 'Owner', type: 'multiple-select' }, + { column: 'Branch', type: 'select' }, +]; + +export const FossaPage = () => { + const catalogApi = useApi(catalogApiRef); + const fossaApi = useApi(fossaApiRef); + + // Get a list of all relevant entities + const { value: entities, loading: entitiesLoading } = useAsync(() => { + return catalogApi.getEntities({ + filter: { kind: 'Component' }, + fields: [ + 'kind', + 'metadata.namespace', + 'metadata.name', + 'metadata.annotations', + 'relations', + ], + }); + }); + + // get the project names of all entities. the idx of both lists match. + const projectNames = useProjectNames(entities?.items); + + // get the summary list + const { value: summaries, loading: summariesLoading } = useAsync( + async () => + await fossaApi.getFindingSummaries( + projectNames.filter(n => n !== undefined) as string[], + ), + [projectNames], + ); + + // compose the rows + const rows: FossaRow[] = useMemo( + () => + entities?.items?.map((entity, idx) => { + const projectName = projectNames[idx]; + const summary = projectName ? summaries?.get(projectName) : undefined; + const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY); + + return { + entity, + resolved: { + name: formatEntityRefTitle(entity), + ownedByRelations, + ownedByRelationsTitle: ownedByRelations + .map(r => formatEntityRefTitle(r, { defaultKind: 'group' })) + .join(', '), + loading: summariesLoading, + details: summary, + }, + }; + }) ?? [], + [projectNames, entities?.items, summaries, summariesLoading], + ); + + return ( + +
+ + + columns={columns} + data={rows} + filters={filters} + isLoading={entitiesLoading} + options={{ + pageSize: 20, + actionsColumnIndex: -1, + loadingType: 'linear', + padding: 'dense', + showEmptyDataSourceMessage: !entitiesLoading, + }} + /> + + + ); +}; diff --git a/plugins/fossa/src/components/FossaPage/index.ts b/plugins/fossa/src/components/FossaPage/index.ts new file mode 100644 index 0000000000..7d6481949e --- /dev/null +++ b/plugins/fossa/src/components/FossaPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { FossaPage } from './FossaPage'; diff --git a/plugins/fossa/src/components/useProjectName.test.ts b/plugins/fossa/src/components/useProjectName.test.ts new file mode 100644 index 0000000000..e85b1f427c --- /dev/null +++ b/plugins/fossa/src/components/useProjectName.test.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { renderHook } from '@testing-library/react-hooks'; +import { useProjectName } from './useProjectName'; + +describe('useProjectName', () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', + annotations: { + 'fossa.io/project-name': 'test', + }, + }, + }; + + it('should extract the fossa project name', async () => { + const { result } = renderHook(() => useProjectName(entity)); + + expect(result.current).toBe('test'); + }); +}); diff --git a/plugins/fossa/src/components/useProjectNames.test.ts b/plugins/fossa/src/components/useProjectNames.test.ts new file mode 100644 index 0000000000..ae17fa93d8 --- /dev/null +++ b/plugins/fossa/src/components/useProjectNames.test.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { renderHook } from '@testing-library/react-hooks'; +import { useProjectNames } from './useProjectNames'; + +describe('useProjectNames', () => { + const entity0: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', + annotations: { + 'fossa.io/project-name': 'test', + }, + }, + }; + const entity1: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', + }, + }; + + it('should extract the fossa project name', async () => { + const { result } = renderHook(() => useProjectNames([entity0, entity1])); + + expect(result.current).toEqual(['test', undefined]); + }); +}); diff --git a/plugins/fossa/src/components/useProjectNames.ts b/plugins/fossa/src/components/useProjectNames.ts new file mode 100644 index 0000000000..c0e11a1e87 --- /dev/null +++ b/plugins/fossa/src/components/useProjectNames.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { useMemo } from 'react'; +import { FOSSA_PROJECT_NAME_ANNOTATION } from './useProjectName'; + +export const useProjectNames = ( + entities: Entity[] | undefined, +): Array => { + return useMemo( + () => + entities?.map( + entity => + entity.metadata.annotations?.[FOSSA_PROJECT_NAME_ANNOTATION] ?? + undefined, + ) ?? [], + [entities], + ); +}; diff --git a/plugins/fossa/src/extensions.tsx b/plugins/fossa/src/extensions.tsx index 38573c2d1f..21e53996ba 100644 --- a/plugins/fossa/src/extensions.tsx +++ b/plugins/fossa/src/extensions.tsx @@ -14,8 +14,12 @@ * limitations under the License. */ -import { createComponentExtension } from '@backstage/core'; +import { + createComponentExtension, + createRoutableExtension, +} from '@backstage/core'; import { fossaPlugin } from './plugin'; +import { rootRoute } from './routes'; export const EntityFossaCard = fossaPlugin.provide( createComponentExtension({ @@ -24,3 +28,10 @@ export const EntityFossaCard = fossaPlugin.provide( }, }), ); + +export const FossaPage = fossaPlugin.provide( + createRoutableExtension({ + component: () => import('./components/FossaPage').then(m => m.FossaPage), + mountPoint: rootRoute, + }), +); diff --git a/plugins/fossa/src/index.ts b/plugins/fossa/src/index.ts index f1b645c29b..929983bb6a 100644 --- a/plugins/fossa/src/index.ts +++ b/plugins/fossa/src/index.ts @@ -15,4 +15,4 @@ */ export { fossaPlugin } from './plugin'; -export { EntityFossaCard } from './extensions'; +export { EntityFossaCard, FossaPage } from './extensions'; diff --git a/plugins/fossa/src/plugin.ts b/plugins/fossa/src/plugin.ts index 638be4a0bf..849769d42c 100644 --- a/plugins/fossa/src/plugin.ts +++ b/plugins/fossa/src/plugin.ts @@ -22,6 +22,7 @@ import { identityApiRef, } from '@backstage/core'; import { fossaApiRef, FossaClient } from './api'; +import { rootRoute } from './routes'; export const fossaPlugin = createPlugin({ id: 'fossa', @@ -41,4 +42,7 @@ export const fossaPlugin = createPlugin({ }), }), ], + routes: { + fossaOverview: rootRoute, + }, }); diff --git a/plugins/fossa/src/routes.ts b/plugins/fossa/src/routes.ts new file mode 100644 index 0000000000..6e8ce07b29 --- /dev/null +++ b/plugins/fossa/src/routes.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { createRouteRef } from '@backstage/core'; + +export const rootRoute = createRouteRef({ + id: 'fossa-overview', +}); From 18868f258b5c77a387430d7ebc00417ebce9a018 Mon Sep 17 00:00:00 2001 From: Andrey O <10812297+andreyors@users.noreply.github.com> Date: Mon, 12 Apr 2021 09:38:14 +0200 Subject: [PATCH 020/262] Update Ukrainian and Russian translations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../CatalogPage/utils/locales/goodEvening.locales.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json index 890899fcf3..36d48eaf39 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json @@ -75,7 +75,7 @@ "Quiché": "Xe q’ij", "Romani [Sinte]": "Lashi rachi", "Romanian": "Bunã seara", - "Russian": "Dobry vyecher", + "Russian": "Добрый вечер", "Scottish Gaelic": "Feasgar mhath", "Scots": "Guid eenin", "Sesotho": "Fonane", @@ -91,7 +91,7 @@ "Telugu": "శుభ సాయంత్రం", "Thai": "Sawat-dii torn khum", "Turkish": "İyi akşamlar", - "Ukrainian": "Dobry vechir", + "Ukrainian": "Добрий вечiр", "Uzbek": "Xayrli kech", "Welsh": "Noswaith dda", "Yiddish": "Ah gutn ovnt", From 37f1311d1ebf4dd2153a7723b80ce01b9c39a202 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Tue, 20 Apr 2021 15:11:40 +0200 Subject: [PATCH 021/262] fixed australian greeting Signed-off-by: Brett Wright --- .../CatalogPage/utils/locales/goodAfternoon.locales.json | 2 +- .../CatalogPage/utils/locales/goodEvening.locales.json | 2 +- .../CatalogPage/utils/locales/goodMorning.locales.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json index ad3c4e4634..72e7782882 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json @@ -11,7 +11,7 @@ "Armenian": "Բարի կէսօր:", "Assamese": "শুভ আবেলি", "Asturian": "Bones tardes", - "Australian": "G'day mate", + "Australian": "G'day", "Azerbaijani": "Günortanız xeyir", "Bashkir": "хәйерле көн", "Basque": "Arratsalde on", diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json index ed68d0332e..636f845c36 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json @@ -10,7 +10,7 @@ "Asante": "Maadwó", "Asturian": "Bona nuechi", "Ateso": "Akwar najokan", - "Australian": "G'day mate", + "Australian": "G'day", "Aymara": "Winas tartis", "Azerbaijani": "Axşamınız xeyir", "Basque": "Arratsalde on", diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json index b906155426..c131d2eb04 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json @@ -4,7 +4,7 @@ "Albanian": "Mirëmëngjes", "Arabic": "صباح الخير", "Armenian": "Paree looys", - "Australian": "G'day mate", + "Australian": "G'day", "Azerbaijani": "Sabahınız xeyir", "Bengali": "shuprobhat", "Bulgarian": "Dobro utro", From 772f60f14b3e7f5cfd0827879c13daf311c9575c Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 20 Apr 2021 07:10:08 -0400 Subject: [PATCH 022/262] Update plugins/catalog/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Adam Harvey --- plugins/catalog/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/README.md b/plugins/catalog/README.md index 2940fecaa1..611d2989e8 100644 --- a/plugins/catalog/README.md +++ b/plugins/catalog/README.md @@ -18,7 +18,7 @@ Backstage root folder, instead do: yarn dev ``` -This will launch both the front and backend in same window, populated some example entities. +This will launch both frontend and backend in the same window, populated with some example entities. ## Links From bc30288405c70f10bfa2eb08ba34e9174aaa2933 Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Tue, 23 Mar 2021 14:46:03 -0600 Subject: [PATCH 023/262] Change #0A6EBE to #EFE5B1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- packages/theme/src/themes.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index 0cdd41508c..0e592cb521 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -124,8 +124,8 @@ export const darkTheme = createTheme({ errorText: '#CA001B', infoText: '#004e8a', warningText: '#000000', - linkHover: '#2196F3', - link: '#0A6EBE', + linkHover: '#EFE5A1', + link: '#EFE5B1', gold: yellow.A700, navigation: { background: '#424242', From 343913573fa4fcf864991c50f3d6d93579629aee Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Wed, 24 Mar 2021 08:23:52 -0600 Subject: [PATCH 024/262] banner link color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- packages/theme/src/themes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index 0e592cb521..3d9e7f139e 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -46,7 +46,7 @@ export const lightTheme = createTheme({ info: '#2E77D0', error: '#E22134', text: '#FFFFFF', - link: '#000000', + link: '#0A6EBE', }, border: '#E6E6E6', textContrast: '#000000', From 931b21a127aa69eb2851eb68ea10b5d40816285a Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Wed, 24 Mar 2021 08:29:49 -0600 Subject: [PATCH 025/262] Add Changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- .changeset/light-horses-hammer.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/light-horses-hammer.md diff --git a/.changeset/light-horses-hammer.md b/.changeset/light-horses-hammer.md new file mode 100644 index 0000000000..4e3159cc1d --- /dev/null +++ b/.changeset/light-horses-hammer.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +I've changed the link color in dark theme to #EFE5B1 instead dark blue From f9b206cece589334946e9fe82c72e5767125b97b Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Wed, 24 Mar 2021 08:33:48 -0600 Subject: [PATCH 026/262] Revert "Change #0A6EBE to #EFE5B1" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 30d3886ef7cba00ac55c8db9aca7f20eda8a5d2f. Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- packages/theme/src/themes.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index 3d9e7f139e..26b58389b9 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -124,8 +124,8 @@ export const darkTheme = createTheme({ errorText: '#CA001B', infoText: '#004e8a', warningText: '#000000', - linkHover: '#EFE5A1', - link: '#EFE5B1', + linkHover: '#2196F3', + link: '#0A6EBE', gold: yellow.A700, navigation: { background: '#424242', From 08b25805d1501ec4e555e9689efe1ffb72d13026 Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Wed, 24 Mar 2021 08:38:12 -0600 Subject: [PATCH 027/262] Fixing typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- packages/theme/src/themes.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index 26b58389b9..f67360f176 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -46,7 +46,7 @@ export const lightTheme = createTheme({ info: '#2E77D0', error: '#E22134', text: '#FFFFFF', - link: '#0A6EBE', + link: '#000000', }, border: '#E6E6E6', textContrast: '#000000', @@ -111,7 +111,7 @@ export const darkTheme = createTheme({ info: '#2E77D0', error: '#E22134', text: '#FFFFFF', - link: '#000000', + link: '#0A6EBE', }, border: '#E6E6E6', textContrast: '#FFFFFF', @@ -124,8 +124,8 @@ export const darkTheme = createTheme({ errorText: '#CA001B', infoText: '#004e8a', warningText: '#000000', - linkHover: '#2196F3', - link: '#0A6EBE', + linkHover: '#EFE5A1', + link: '#EFE5B1', gold: yellow.A700, navigation: { background: '#424242', From 9c9df47f4f3f3bd597039eef5e54fef806b4318f Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Wed, 24 Mar 2021 13:01:40 -0600 Subject: [PATCH 028/262] Replace color proposed by one Backstage color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- packages/theme/src/themes.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index f67360f176..b6810d9a84 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -111,7 +111,7 @@ export const darkTheme = createTheme({ info: '#2E77D0', error: '#E22134', text: '#FFFFFF', - link: '#0A6EBE', + link: '#FDFB9F', }, border: '#E6E6E6', textContrast: '#FFFFFF', @@ -124,8 +124,8 @@ export const darkTheme = createTheme({ errorText: '#CA001B', infoText: '#004e8a', warningText: '#000000', - linkHover: '#EFE5A1', - link: '#EFE5B1', + linkHover: '#FFED51', + link: '#FDFB9F', gold: yellow.A700, navigation: { background: '#424242', From 7923c2a94606dfb8c9070cf92da76496da8e491e Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Wed, 24 Mar 2021 13:06:13 -0600 Subject: [PATCH 029/262] Fix Changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- .changeset/light-horses-hammer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/light-horses-hammer.md b/.changeset/light-horses-hammer.md index 4e3159cc1d..06abf339f1 100644 --- a/.changeset/light-horses-hammer.md +++ b/.changeset/light-horses-hammer.md @@ -2,4 +2,4 @@ '@backstage/theme': patch --- -I've changed the link color in dark theme to #EFE5B1 instead dark blue +Replace the link color in dark theme to #FDFB9F instead dark blue From 8546ef9f0c223ffff1d47be20e1f9dab8bdf8273 Mon Sep 17 00:00:00 2001 From: Victor Perera Date: Wed, 24 Mar 2021 13:39:28 -0600 Subject: [PATCH 030/262] Fix Changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Victor Perera Signed-off-by: Fredrik Adelöw --- .changeset/light-horses-hammer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/light-horses-hammer.md b/.changeset/light-horses-hammer.md index 06abf339f1..0d421c7056 100644 --- a/.changeset/light-horses-hammer.md +++ b/.changeset/light-horses-hammer.md @@ -2,4 +2,4 @@ '@backstage/theme': patch --- -Replace the link color in dark theme to #FDFB9F instead dark blue +Replace the link color in dark theme From 091b3f7363d795ac5a9e8f449d847d67ef933c20 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Tue, 20 Apr 2021 17:04:25 +0200 Subject: [PATCH 031/262] Fix review comments Signed-off-by: Dominik Henneke --- plugins/fossa/dev/index.tsx | 2 +- plugins/fossa/src/api/FossaClient.test.ts | 64 +++++++++++++++++++ plugins/fossa/src/api/FossaClient.ts | 33 ++++------ .../src/components/FossaCard/FossaCard.tsx | 6 +- .../src/components/FossaPage/FossaPage.tsx | 11 +++- ...ectName.test.ts => getProjectName.test.ts} | 42 ++++++++---- .../{useProjectName.ts => getProjectName.ts} | 2 +- .../src/components/useProjectNames.test.ts | 45 ------------- .../fossa/src/components/useProjectNames.ts | 33 ---------- 9 files changed, 118 insertions(+), 120 deletions(-) rename plugins/fossa/src/components/{useProjectName.test.ts => getProjectName.test.ts} (56%) rename plugins/fossa/src/components/{useProjectName.ts => getProjectName.ts} (92%) delete mode 100644 plugins/fossa/src/components/useProjectNames.test.ts delete mode 100644 plugins/fossa/src/components/useProjectNames.ts diff --git a/plugins/fossa/dev/index.tsx b/plugins/fossa/dev/index.tsx index 9625b24dc2..1c2e96807f 100644 --- a/plugins/fossa/dev/index.tsx +++ b/plugins/fossa/dev/index.tsx @@ -27,7 +27,7 @@ import React from 'react'; import { EntityFossaCard, fossaPlugin } from '../src'; import { FindingSummary, FossaApi, fossaApiRef } from '../src/api'; import { FossaPage } from '../src/components/FossaPage'; -import { FOSSA_PROJECT_NAME_ANNOTATION } from '../src/components/useProjectName'; +import { FOSSA_PROJECT_NAME_ANNOTATION } from '../src/components/getProjectName'; const entity = (name?: string) => ({ diff --git a/plugins/fossa/src/api/FossaClient.test.ts b/plugins/fossa/src/api/FossaClient.test.ts index 24bcad526c..29e5b50fcd 100644 --- a/plugins/fossa/src/api/FossaClient.test.ts +++ b/plugins/fossa/src/api/FossaClient.test.ts @@ -287,6 +287,70 @@ describe('FossaClient', () => { ); }); + it('should handle multiple pages', async () => { + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { + const page = req.url.searchParams.get('page'); + + if (page === '0') { + return res( + ctx.json( + [...Array(1000)].map(() => ({ + locator: 'custom+8736/our-service', + title: 'our-service-2', + default_branch: 'develop', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_licensing_issue_count: 5, + unresolved_issue_count: 100, + }, + ], + })), + ), + ); + } + + return res( + ctx.json([ + { + locator: 'custom+8736/our-service', + title: 'our-service', + default_branch: 'develop', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_licensing_issue_count: 5, + unresolved_issue_count: 100, + }, + ], + }, + ]), + ); + }), + ); + + const summary = await client.getFindingSummaries(['our-service']); + + expect(summary).toEqual( + new Map([ + [ + 'our-service', + { + timestamp: '2020-01-01T00:00:00Z', + issueCount: 5, + dependencyCount: 160, + projectDefaultBranch: 'develop', + projectUrl: + 'https://app.fossa.com/projects/custom%2B8736%2Four-service', + }, + ], + ]), + ); + }); + it('should handle empty result', async () => { server.use( rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { diff --git a/plugins/fossa/src/api/FossaClient.ts b/plugins/fossa/src/api/FossaClient.ts index fb5eb80345..e8f3ecb7cd 100644 --- a/plugins/fossa/src/api/FossaClient.ts +++ b/plugins/fossa/src/api/FossaClient.ts @@ -55,7 +55,7 @@ export class FossaClient implements FossaApi { private async callApi( path: string, query: Record, - ): Promise { + ): Promise { const apiUrl = `${await this.discoveryApi.getBaseUrl('proxy')}/fossa`; const idToken = await this.identityApi.getIdToken(); const response = await fetch( @@ -75,30 +75,23 @@ export class FossaClient implements FossaApi { async *getProject( projectTitles: Set, ): AsyncIterable<{ title: string; summary: FindingSummary }> { - let nextPage = 0; const pageSize = 1000; - for (;;) { - const projects = await this.limit( - page => - this.callApi('projects', { - count: pageSize, - page, - sort: 'title+', - ...(this.organizationId && { - organizationId: this.organizationId, - }), - ...(projectTitles.size === 1 && { - title: projectTitles.values().next().value, - }), + for (let page = 0; ; page++) { + const projects = await this.limit(() => + this.callApi('projects', { + count: pageSize, + page, + sort: 'title+', + ...(this.organizationId && { + organizationId: this.organizationId, }), - nextPage++, + ...(projectTitles.size === 1 && { + title: projectTitles.values().next().value, + }), + }), ); - if (!projects) { - break; - } - for (const project of projects) { if (projectTitles.has(project.title) && project.revisions.length > 0) { const revision = project.revisions[0]; diff --git a/plugins/fossa/src/components/FossaCard/FossaCard.tsx b/plugins/fossa/src/components/FossaCard/FossaCard.tsx index 9d2db263c8..034ba57dfc 100644 --- a/plugins/fossa/src/components/FossaCard/FossaCard.tsx +++ b/plugins/fossa/src/components/FossaCard/FossaCard.tsx @@ -32,8 +32,8 @@ import { useAsync } from 'react-use'; import { fossaApiRef } from '../../api'; import { FOSSA_PROJECT_NAME_ANNOTATION, - useProjectName, -} from '../useProjectName'; + getProjectName, +} from '../getProjectName'; const useStyles = makeStyles(theme => ({ numberError: { @@ -102,7 +102,7 @@ export const FossaCard = ({ variant }: { variant?: InfoCardVariants }) => { const { entity } = useEntity(); const fossaApi = useApi(fossaApiRef); - const projectTitle = useProjectName(entity); + const projectTitle = getProjectName(entity); const { value, loading, error } = useAsync( async () => projectTitle ? fossaApi.getFindingSummary(projectTitle) : undefined, diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.tsx index 05e1379378..cfc6e8af97 100644 --- a/plugins/fossa/src/components/FossaPage/FossaPage.tsx +++ b/plugins/fossa/src/components/FossaPage/FossaPage.tsx @@ -45,7 +45,7 @@ import * as React from 'react'; import { useMemo } from 'react'; import { useAsync } from 'react-use'; import { FindingSummary, fossaApiRef } from '../../api'; -import { useProjectNames } from '../useProjectNames'; +import { getProjectName } from '../getProjectName'; type FossaRow = { entity: Entity; @@ -63,7 +63,9 @@ const columns: TableColumn[] = [ title: 'Name', field: 'resolved.name', highlight: true, - render: ({ entity }) => , + render: ({ entity }) => ( + + ), }, { title: 'Owner', @@ -170,7 +172,10 @@ export const FossaPage = () => { }); // get the project names of all entities. the idx of both lists match. - const projectNames = useProjectNames(entities?.items); + const projectNames = useMemo( + () => entities?.items?.map(getProjectName) ?? [], + [entities?.items], + ); // get the summary list const { value: summaries, loading: summariesLoading } = useAsync( diff --git a/plugins/fossa/src/components/useProjectName.test.ts b/plugins/fossa/src/components/getProjectName.test.ts similarity index 56% rename from plugins/fossa/src/components/useProjectName.test.ts rename to plugins/fossa/src/components/getProjectName.test.ts index e85b1f427c..461cb18ed7 100644 --- a/plugins/fossa/src/components/useProjectName.test.ts +++ b/plugins/fossa/src/components/getProjectName.test.ts @@ -16,23 +16,37 @@ import { Entity } from '@backstage/catalog-model'; import { renderHook } from '@testing-library/react-hooks'; -import { useProjectName } from './useProjectName'; - -describe('useProjectName', () => { - const entity: Entity = { - apiVersion: 'v1', - kind: 'Component', - metadata: { - name: 'test', - annotations: { - 'fossa.io/project-name': 'test', - }, - }, - }; +import { getProjectName } from './getProjectName'; +describe('getProjectName', () => { it('should extract the fossa project name', async () => { - const { result } = renderHook(() => useProjectName(entity)); + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', + annotations: { + 'fossa.io/project-name': 'test', + }, + }, + }; + + const { result } = renderHook(() => getProjectName(entity)); expect(result.current).toBe('test'); }); + + it('should return undefined', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', + }, + }; + + const { result } = renderHook(() => getProjectName(entity)); + + expect(result.current).toBeUndefined(); + }); }); diff --git a/plugins/fossa/src/components/useProjectName.ts b/plugins/fossa/src/components/getProjectName.ts similarity index 92% rename from plugins/fossa/src/components/useProjectName.ts rename to plugins/fossa/src/components/getProjectName.ts index 88379ca3fa..3f117dbbda 100644 --- a/plugins/fossa/src/components/useProjectName.ts +++ b/plugins/fossa/src/components/getProjectName.ts @@ -18,7 +18,7 @@ import { Entity } from '@backstage/catalog-model'; export const FOSSA_PROJECT_NAME_ANNOTATION = 'fossa.io/project-name'; -export const useProjectName = (entity: Entity): string | undefined => { +export const getProjectName = (entity: Entity): string | undefined => { return ( entity?.metadata.annotations?.[FOSSA_PROJECT_NAME_ANNOTATION] ?? undefined ); diff --git a/plugins/fossa/src/components/useProjectNames.test.ts b/plugins/fossa/src/components/useProjectNames.test.ts deleted file mode 100644 index ae17fa93d8..0000000000 --- a/plugins/fossa/src/components/useProjectNames.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; -import { useProjectNames } from './useProjectNames'; - -describe('useProjectNames', () => { - const entity0: Entity = { - apiVersion: 'v1', - kind: 'Component', - metadata: { - name: 'test', - annotations: { - 'fossa.io/project-name': 'test', - }, - }, - }; - const entity1: Entity = { - apiVersion: 'v1', - kind: 'Component', - metadata: { - name: 'test', - }, - }; - - it('should extract the fossa project name', async () => { - const { result } = renderHook(() => useProjectNames([entity0, entity1])); - - expect(result.current).toEqual(['test', undefined]); - }); -}); diff --git a/plugins/fossa/src/components/useProjectNames.ts b/plugins/fossa/src/components/useProjectNames.ts deleted file mode 100644 index c0e11a1e87..0000000000 --- a/plugins/fossa/src/components/useProjectNames.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity } from '@backstage/catalog-model'; -import { useMemo } from 'react'; -import { FOSSA_PROJECT_NAME_ANNOTATION } from './useProjectName'; - -export const useProjectNames = ( - entities: Entity[] | undefined, -): Array => { - return useMemo( - () => - entities?.map( - entity => - entity.metadata.annotations?.[FOSSA_PROJECT_NAME_ANNOTATION] ?? - undefined, - ) ?? [], - [entities], - ); -}; From 54c455cfa44bb801da3e5ca4af8a65d5d8eae8bb Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Tue, 20 Apr 2021 17:09:05 +0200 Subject: [PATCH 032/262] Add a link to the fossa details Signed-off-by: Dominik Henneke --- plugins/fossa/dev/index.tsx | 7 ++++++- plugins/fossa/docs/fossa-overview.png | Bin 375035 -> 337907 bytes .../src/components/FossaPage/FossaPage.tsx | 13 ++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/fossa/dev/index.tsx b/plugins/fossa/dev/index.tsx index 1c2e96807f..563c63faf5 100644 --- a/plugins/fossa/dev/index.tsx +++ b/plugins/fossa/dev/index.tsx @@ -140,7 +140,12 @@ createDevApp() await new Promise(r => setTimeout(r, 1000)); return { - items: [entity('zero-deps'), entity('issues'), entity('no-issues')], + items: [ + entity('no-fossa'), + entity('zero-deps'), + entity('issues'), + entity('no-issues'), + ], }; }, } as Partial) as any), diff --git a/plugins/fossa/docs/fossa-overview.png b/plugins/fossa/docs/fossa-overview.png index 2c6dd972312d50bfc678dc5a2dcf5063e38965cc..6298fb95573dea5f3121ade63e2e8814f84d2b98 100644 GIT binary patch literal 337907 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 $D0XxbkZ~+sqYp9>XISC961nseel%I@hs*Kd{4y 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

_8v1 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%0AZuyp*Z+WiWZ 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%0Dt|9TTkZlAek&#?-tqAU#E&{inlAFF9a7&NI;;| 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 VZXV%{;0EBw(#+;K!Suql{{jc5CQ<+Z literal 375035 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%0Adyv^458nhwg2y zY_?P8F3^-;eJy-UcnPC`_<RH*v?Hw3qYx=0=(d>ieLh}<Vy4w9%94CzcT{>uWHt7j z;76?qzovTQ9IvZ{kpeD__hu$P_4)0u(HC%`a4Dp3t`-b)P@BX@tu>ME(#;;H{U;?Z zk^<|foAXmG7Y!e?uS|meiXgX+=7a@Z$v1lbjh8}pzHMYUYGz*IHMcmo?14YJs1C2` zA@GQOEFpI^N01GJ!=d4-pP0OaN+dxh+9vI%1ti-!W9CQrP@+_(nctBDM4|WY)8V`U zuke}aGAcC?BpXrD(QmUBoX%d6CXSLme?6kqgk83hcb`AH!g_g(^GJiWOeNQ%Uj)I& z?UOXK8a^7S#&xv!$0wbcb`kXZ!o#Bx0XzB|2`hwk+bp(`H`87MgSzT+{rjw^T;>m# zt@CVK{gTWG0zcEh4m^2`cRI4eRm}*$Un+6v<8?|eo;#$hOpgjgFH|4^lV_uA0Lfmf zb7|)L#LaLr6n(irOSGorhXDD?b@84pv4aQLx*Xs^nej1`yCxy_m^-e$8Umf|)wPVd znPD0M`<c?&%gIUV0;#4V=v-HK1Az9x5FhFjiphN$IeF*1z9XxPNP{$(z-Qvz*z8{t ze;mxYok6>pI~S2*3Q7RVV{X{TeWhFYZJ>Pe<oJX!2(;=RX^hm?90H_}F$+T;Fxok= zofEA{RhrcDjn++r6Z>ZQre`y52bWeDb)v-W;CDAJitE8;%HO*D{)Lv980l3D@9m$O zR0|-5-}D1CFmUz^l%@yRc7y(c&6XCshjp!CTD*T0nvMq>>?UiS<N9xA)q++*P6|0M z+pf}ciApH&DreYdb{e3%WE=1Fa7p48DMj0Fx8l9Z#NWXh=D%aBz{Y{un)vs?RHxl& z2dKq9i!GuxxRVqrU}qrO{KRsu)xewFii$v?xGTXML~^gb>S`WS#=3GMWpc6yKN#&+ ze{C&F(sV=EPzAaz5ELt>qHnu{yy=Pl2$l6Do2D-4o8L{pMB$1{*E)oboGKX$TI@8G z<_X@+={~r-AYwfc-G7V{7TJR2@0sNS3*IvZ84r|yM>($dF*9<6L-2tBp^8B=wA0*; zhpy%E=C+I=cdBR4yG!1i^jJpDfhjz=;DD3=Yz@TVuuoZ$PdU>}O~340{Z=E3@aV5S zr|E~MKcy9{x<p=<8Z~RwtLhcxrGq|hu72V=?1wtRS=V#Wn%}@#NdJL(44`^U_QHen ze<kHe#_Q18gzndX_cAZnnUs&RL;;Bdf2^c3OH0ZGN5?zhQl(cIhilA9g=l=Yn0pL_ zsFmzyN4W1V`jOnx6B9+lxE<Ffu7R}~wm_crh^&LlxCXB&SG>T$N+kVP_Vj0e=q1;O zd!5;i&w67w|Di~jTMQTa4t(BuDdy+p|8p8Vavc-F36@ObAurMR)0a8`o@pn1SB=Xm zx9EQ5_vOv9BEV-s?G?n?Kfp-k+*Aj;jmdeT$4p45Oa%sGaN_sl>cf|6U24A;+zQ;J zaGiuNxdi|*_f>_3ATlW&)0s*E!Q9(Tp?OjkuB=@Mx~f+J3$P$LDQG<%kW<~oiBmxx zj&^_I_T2B&vumv3iws^+uw7ll;kDAuN9gpM;(Q4G4|1WzM=@bnRt#=O4FZEtoJfmI z=!?~9K8e_fNkKLDcmODCF+zf8)b0_kn$mX}oDc0}=C!;n#Xx2kR|1o(S?3!a#wZeg zSMJsq)Q`zwY&3Fj<=1W~PRy{ndHTWp9v`fc-8q^6yhXOyI_e!x>EXWoB=hLS%?J^! z(q;J!tK`qVB`l2OOOELs;kR!RJGTEIHVzNJL8>*{VUj0klEsn>8XzCwDud#z>ezW! z>P&e%+e2<|-Cvh%BV!g(h9nt*04R`;k)%AT><?x9s#b-Fg+Cf760U^Au<aCH8pcU} zZYVs4@3o9#o4mm`k|}31j!cVs?=DwihwVN2CWRiD_>{WTweM}UzWC41jrw*8ASl2D zEFWaL>c#J(EcWD53tZnugXM!NzWzjtdz`ioyHF@ppEE%V<OC>f7g>a~RJIzpxx*)Z z3D(560-O`}s_{MXy0=C^B>m$fl-5z*0@h(c7R&v}-kx(DO)-#Cn+q<8psE`obt&^5 zT#h|r_dzn#US9Ma2tx=+=oaW6`e&b{5OLG_%@`a-Vpf4LDuB=(wXh|r+!pEXtPB4_ zPui;f!>G?B=n(3Qt8@@brFBoAts~0}6f)dq-4`ZtDf3r&_V5y=$~oO93YW!%hm*aM zt)P=szoK5%Sw-gCsCy#{Cq-Ge+~z6432-j{h)sR}${p){Ur=_{NtFIY0yMM+=C@nU z=_^c_B%1Q}$K$lrf&|e`YWG94uK<N`{g62^jwZcqm^5cGm)RyK+KnkiQe><Gwr>)M zid%k@CZ*MVB?D(<t5Z<fVugdwKHmf5Y60Lw-ItupbUp)c^w_Li!c`Y%)?dq9kk_1W zeQ<u}eer(DAv>BJbLA4`wQ|$(7GEqo8IC<yn~y6P`^l0{=2GP%h(j7vU2Oy+RiH^c z#F7A$=sPb5C>_P&dY_~gK(dF-=3JJJ%xuft(*J}2a$8fH=vJ+lbu2F(ER<w!6nDJp zHw0$_-#3GeiRsxo*mumj{v66H%58(-xV4!8I?&#Kxb*d_8;OC(DkysD@xC$2al{yi z9X2`Yk0sN({t4>-v&G;a6N0-oi?EJS(plL>JXSbN__~37a>)Y_Hakte(OQUUlWKhu zfI7mrK{=hU1n7Q^tGP;vY3q|)D8#_n29S7t!UImlOOq*)zhfMCVN^xzq|**lD{#** zbW(H?o$?HcJWbPiGiPKjTc`5?R|20fR?x&W-;cMZx3NPBf!c~XfXomNXOeDy5J0zJ zQAtQwHsnLMVNPr@#xbdzoo1>Rxyo{&5DTQvz+*-)klRUEbs-UaIM6)<vepTeZL*oJ zPntcBG_(?l5<6D(9y>ZC*pvMmd($8F{M1z8j^j1}d6Aum#T7>{942+ZJ1PxCyn~qA zDXZGWoi2X}k8~Z@P}HVz+)su?7xs#@THydEI*9(GrdLl}fwwNnPJ6igd^Y1#fVx~~ z+>CXV^5C+PTX^9}5)^0|@|bqeL42R9X?G}C+uBP(A`)M>^o94?Yzxku<Q$hwzOwDA zUa>Ex-||Arm~dJ)H2}49iLowQ8c%vy0~cAYIO!#I0nNz%PkRqRT^=Es?r9zy#}V_G zZu54W699l{(|{^3?bT^E7t1brNg4%>4_e;^3z(1u11cP*wWxcuLcrW@9B<<?I-d+* zd`TdvW$&eE>K*16L=2c^&>$SI`DCc4{W#ghvq(JlWsy)xtXd9aZi=jxRUvIs-9Zj- zOJ&*)KF%ni*o?dC(geUUsGxQOmNIov6~U{QEj#}W%i)7<z&3O6Q4!(_5DQ{Vu67L7 z8VYjIYKd-r;gk%)K`HeQTk?Q$odL#ZNwP)ob+|(KEsf79dpTOzoF;|&kZ$0wh+7;X zr|P80gdIbXfMy%J+r=u_N{-!K)!c=?=Odl?s{SFl$ljmOtuK*8Tw=yQw?Q?UWD%$o zmD{q%NU`G#PH>=ccSvOp$89}*uSR;XqPkA2QW3FSMJ^-YZtq5UrC=@-<nZbj`s*NP z1^@<W{;tDw<I2$VA63ZhT+1jlB*!@?-57|-T18Gx%Jk_&?m4nNCJ)~!+~Ve*#8C1f zOgE2;o&Dzh@5P@I$APpW{+=W_?<|+}9#Dg7B9P$uQBI(Q++of<EC!mbJ|SJ&&F!jJ zFK69$9jBj*%PlCnn}?c;Js#!=??8xIK2u!dzPa$*RbI=beGh;z8vVhhMv%Vx^G6fj z!L>>8g&si0i4L|z`s4vb9QOdrgLvzbB-}uOjT3f4G2<_&9asN=*XpeTDV6xdnCFO0 z`Ctr(g!r=_*((fGi3O>*17DlO#(OgyZL{d+SYt#W@ar>I#5(0AuSRBnHA2jsT4#W) z|M8mtc_Y1a22p=9u*?(xxF%g@Rr!a~8~Df{U+7ffw|ani&WknN@6_IBtV3Q*!%Z!L zei;#AWI+sa;dG}#Xf`%#`|lBa5rRj|c$<LDN#}tpo-7D)@0B(#v5{^%Oe)}tck_!_ zIhYNipn3ljs6QYhP*_v}4j>V(lP?q4anStPuZ5s=&|C2h(dYZ|dXH2S|G12(-{dhX zkn<LG(NYK^X&rU5dn$$F<?SVTKQO*7IRNOkTT)+e%;_&0T-@O=<@$Sl=Q`q23chKA z#f?cUz9(JjZ)A!~qgjB{vQc(3mFkSjr5apH+)iFcz2v@va9FUrsF*6d2d(B8djewO z1*S><0v6UQHwKcyX&WD7#TYw~s5bA+wM%fX_N6^t%p>!HZzk_>wP0qINe1_4N)3l= zHLcM{dpjwq3LJEWLr?O;|8QfB>C9f&wo`5#L7aEm{zwBLG0LqTV$MJht<(?>C6zSL zXEHAZrLoy|ubwe_Y>U_GC>7f`o9Vo~On6L8B{YCT>T73SI8SFIFG-?zf?anHnh%-^ z62j;PlPpp->gcI+#6L!Kok1m(YvLRaXT2W*0-nN1*L3d2mZ%~Mq?4~}gS5uB`@Hve zN1I|V)r%C~)C^H;NEbL3ty^VcN#`+MjQ_xsq=9?U+vot;s+EO=(fdpb7EHv?7D@~S zhpsD!Y2me;AFl@5sQO-5%z0OW8cJQ`1o~j%Zr@+4e%D`j{1h5mwau5N1&<FB_^m}F zy~0Udi4=pEF2AG79Ke&cW1PD6bx@SWR2Gj2hZ-B{!Me2`4Ibh|gS7)!_$LZ;XU88E zG;|w1M0IvkS4#W7`H&S4rj{UOxG^f$Q?sevLT?A3+>(r8haoBNWS*5@q+%=}!nkH< zY)KQKK5!Bo@6d;mdxaMyM|vO}jneIZUA`Skxt(@0G}9-s`Aq!qhQXqUSda=|1*oyy z(5)r^)5vy4mh|2(tXdpQz5oS8ER()FecCCkKNbEY&MdwjfCR1@&~+^0Pl9CRFGlSQ z=>DY9rpoBDN#N?$(P7>u>r!<wvPX2Zta=@fqQ|;x5rHHwWW#>80h=)mzoVv=N2$Ri zAKEP3Bp<T#IY+8kWqX-T7P{V@%!;g5PR0)YDK)Nl^~8L`%2gG2C=P1p)JWUDmBSzH zWnPc?Y-NChoD~dS1`2=>>jfAV^S}WlB>Q}ST2a3+BPOPFm;!LOLWPg)6^4T0$a#sG z(og>JEZ?4sVY8$P!!RAYWZpG6RJdRK{a)p~D&Tuv23J3t$qZJqf!M%`>-Qrdnknqh zmVv6OF^Xc=GCqTAnVWimJG@N%2fYI@9mJ`ep(GTi%Ogp=r{|M?2U8Utp$6Hii5xRw z(U26|&isRuYTNEyP}2Qae5@T<zx>|P*V`?1_7RDC_NGV1&4A;*ce{>L+SuaQ%K<{w zBb{Y=yI7K-4d80|b_qi1Y`Zt^A7I|C>}WO92z^U1e#qK4<eCA5(c<zw^Ez)WkLynG zJ)c;FEe;W%p$6iCI5<59s!$f1IgpjnBZ7!Ee%P}P9#b5)2iQ%maD~G}Elo`lh0B&0 z%OZ}!gyM(g4D4iFzce(&Rymll`54XeM)rF&h&z)q7t2XvZ!T}nuvN%A0QoR3LP+c( z)kx@d)1etOKeLKY`#<IB*NZib3hk)hniKR4z0kf>R^t#I=1v=2@fwG5Uj>z~y0rkn zot%vK$>+{nymz+9AqPFs`c$`Bufje6#XA#~zByqdb4B5Dc(4YZC#Y_(zjl;wdbM@i zFg%(DBai695}P_(rS|LP<RS4_XC+MS@9~ZDgMksn__%7F5haXOGk$oo`gdW|8SDPO zz3P#bCOmfw;as=j<G^N}4sVK=(S_lnJ%aTV+zsgl2c1^Zn=WabU|qOIMF^!_12F^< zQ=RGy4mhDm4%UsUF@dN~=~3=8=O4sJSkrBv_BKiH^IR={zTeka`(yK&M1Ei=$L@_` zvy;?$EkV@Lq5_i*G@)XCDdYGJK&~o=H*OaFUV5}XqPHvi)&%?FCzqVlo0PcIVSR}^ z^G&`V0x6+zNJ}?S-8c;XMK712j#z<mI@Agjz>?zVqWSZ4Pk@Lei5DK)?ly50BWAaL znPRnhzp6wib-zS4F?9MXmd!N0v9o@ani0WoVKH$l%`uC&V%-4EJnjQ3T@zqyInFkq zY@FM{%;G0E9RlF6P(!A~Ia0I7x`KX=*tps+Ah}tDOKu9rQvS)>YFwT)i(U;N7irbY zAxs4`QAW0yJ}}d=_78l}w2y`B(A(tMf&{G8uN{`0gYE<%+x9d9W=tT$MV{f=_Uf!p zHP9?=#uiRJi#2RB<2GN{p9$jBb<5{gIz?fG250n(jAme8xu$xN77vn>cRA=LOu@0d z+i*)Fk-~9E|2M7}Ob(i^mDN&Xc~}5K3wn0CK0xFSTZEY13;#~_DuSfHfH;v_t!4Zl z<6(u)=zb9=G?0|8s3C|sluY)Zq8G4MokDo}Mq)Ox6{aThN1MxonF3E0Y%bb){WXLp zbR>-t?h;HNGy6sjJb-lTVE_B)$H3e7iND6NhkLZUwT64A^7f^ttU^n`F?r=FWz^sw z<f8%LwKia+E<zwV>3V9MQ-M3c>~EEM1Odlt9~~&iMh%=+>oQlSA}_UxznAag;;jX5 zz#;r$R|wb9hP=OIC77TP?1V2}Z83NGp7a2&rRKZS1;l(D<A$(>y`7H|jt^rg-4y_g zW`@hSnoJ$S*G|tLhtbE{q<cMZN>?Rq(tP~f1@=2oFX;*I-5>f`r~Ytn7r>gK_D^-? z#mwp{MBbt9h$>0Xl{zyMz`Z82+sJp>*;;RnY6DgcX9`|Myytx4fPI0m>NN&xrI;yb zK|vyLRUmVK$Hh^^7a@YnM+#S6#SAKBYb1v5Tumb#dZHNoNK0ce_noRwM0v9U8urq& zn3^CU$)dpa=_9HBO<M(?SM_Lb)(>S|U-2Ans}<Q2@Wg+$ky<UJrh>h+!QIIQB^y#k z&dK`l&m2ln_cW8`9)mkyOD<8}`SS$;3Ud`chKW5=0hU$FIhdjGoyOF6tG*@B5Y!J> z!GL0j*@-Y~)Zy%G_c02(CI8-Dip==P{?3eKv!kkRzbDY8NT9Jtkz*(JYC%TMq9vJA z&i)ngQ!Kb9kC~eAND(06ShYMCP3Rch9+HH*sk3Q*MgGLi*zgL&u%(h>7g8fne<-ax z)M)&}DBdwQSWfJaR1s?++;ojF^M-%>AsXXqJJFgAbS3vcsVm2;CH+6h-ClHEjM@k) zZqO2UjIO-?H+#%<e7DItkcMZ~-!Jc@n7fDzShi_etO9m3nc`NMJ6y0{QTsAKjLMu$ zmQwq!(aCGIRNOJo1U2p=q^F}|zjF2%i<oKAvqv=j?{Ep~<h|@jRY&zS`;i)yt80^^ zagq;Vam{3a(`KtQ(S9dwu@=4`Jp3RjjS*C|GuDas<Bf{p_R@o||Lat|z~Y-`dDb~! zt+J?K<hRRSeGR6u8-G3RE^ZeLSWSV#q<l|kGwX&bQrSU9hkrqojOAUOcmAJC(brX9 ze+j-y#;^B>cm4Fm=({TwMIixh1<cXCZDQxQKXDf>yZqB7h|ls}C~_7JvRFw%+x*Gm z3>P`cb_IcYXJ3liR+qn&)@y=<4fExVw8yzFFsoQvys}e-<1p6pjqs)&j?E%VJzK-t z|MB<E-E<1)$oV5;t(FUEFxOEk^wGuqA#Vhg-SYk291FSj;&IL^7MC@+a(|#ezUZvX zH8kxel_WLkzQ<@qS}4igrUN?WteAz1WA)T2R2OUl_KECBqGYT|-NOc~qJC@7{iMy) z^w+0FT5}{3nB{=_>e)z)E!P9a6T{3a(Q&LV`U!|#Mk??XJS{n8qB*P6i^wh$P|95T z*MEHR#v`aJz;qN=U%w1+x1E8nME>e?mjb<cWTFexnPlpj(k{ssFQ2{^!XsvWbLn6I zA>#lpw!I^!YFG<=<=*c1LFnIIs~P=G=FX}Jh8G^WcDSovY9IQ$Z@h#j#0oCf+DPAC z@;Y;;_H%Nosi%MOaKMjLJL4Y9;brTCZd&Hfc5#A#{Yd}$#mtPjn{3ngLgD@Zd^KVj z#rLnD%s&tBjp7?-TE`F~ZtyW#CVvmczx&1y^x#6BUD=kEjEN~13P|0nKmNtL!2QT9 z?#6t+$&yko*bRhaq$&RUld)AW3;Oq3fd6Ns_^t4US$FadiI^rWcrhza(x7+$#uC7{ z9}*I~Y^B={fREAb&e>qD|BcaJ3akaMky<3=ZRBt;FuwX1HYtB=3I5<QH9n-P1Ro>v zJ4AW?o#`>daIdrP>lapc7VutphEWgx_H~+q*SY!e{|B%0zhB{hyuueVK}KF)Uhb_O z!hdIQmkBJmqT}POu~_UVnERxnu3nv$bx%b}iTEf(IRDr0vip^eGtKuH#T7DELV#%< zJEtz+|2qpQg@c7RF&f2pqFXHEN8#eWGW?M>{4dvTDH$=BaeZv45&FCHE7}5fV4KNK zjo1FpWymn+fMsXV-POI4g1csqpUb>|dCgD~aLvL|oIcvmz<P>%XTkq>>*!J-9W`*k znT<sf(_rPdpIrYI@OLX$rj3%hbA&Haz~{Cs&Ows>?H9fVpQENw43rv90yim^Y18(1 zUw8?R5$7rx{@YdjpHKR~z5Rc=I^X=axBvI(;eXq1{(HmzuS4ViGXDDCp5T9S>HpuY z!g-@vBqYV*M}j?GlZ5x!lCbYgyz{hueaL@l=Ku45$n1f@NV`8m7s?9ulIj@zE||k- zyw3sSW(Q3bcS{{v4;-y%83wIWCUreX{?k4D-`pW^xmW(f<sLl-u_-m?%7+b>e;rT$ zd<lY3RZ)F?KX6RYo{7A5235j^l|zHprhl=^gE*A&pE%U+;!l9|!(ZomsWt+-3#g&0 z;L&=>CwIG%PIBznu*Yh;hIxp8Vu~e_W)YPdcU1if8tC4sT9&@92|ZDVR0qsFh>w2Z zL7lP_x&~*ez<<7LJJz|6MgF8ILe!MlER6G#R*&a2-bH_Pt>4>>hvC;a(&_2+`$>!c z@=r~$%<uX*ny(#7Hr*7wJ}lbQ``+Z#&Um)0H>b;^x46&YyukOwZNmD*@>y{{6WS&l z6{&x_+H|HPJ|<aj;~d7#QP!X1Sgy~x4c*w5FwCeJsjqrgVFE6#CjEA`TyAA)$;HBf zTD6Ou`E1?XiM80p*<1<z`dF}`!|1kzJ(8=vzDlL4&C|ioPwbs(RKr_S+NB9cFh`~X z{I+VI8E+4z8itA?hcOs-v`NiwT<TqgUIV1i@AyO^rJfDs*?Vdba80-k`lUEbhP21w z6O~@SxU`kwe*E1NsB^L3IVR`(e1m6S>DjTM^Ldl~!L`+dxTQoMy_=J|k~PL5FICi) zOW*#m@Y!o1qi)V^B)xWfU@|$2@I=!%NE>CiK0hN&qywKXKJeU+hwra=qV{{<-s$P$ zEHAThzlt((kMfH1_!RsXZ~M0<Fcu?58Zm7{U?X-a6ApgrF;hEBBqtWue2Mcj$Hi&L z^^SRQJ&aC7x0^#>4qVu}TlpmF;rP6%txV0e1`pdSJ>9BTz3jX^zA_wqpZsna<Y^BJ zSs(8$_V>zPq^3$hjXF0}mD-0?)`ZNMLU;peq_~FuG(B41wnPU@)bv9I;I(-_y&N#= zSdZ!J(6!KKDh?_pDCn+TiuHv^`Db^B>l3=3!2w)-6+Y8?<`p`N!BhTEzM($)yqfR| zsj2SB|Js_V@{70H5wl2Oaxf><v>rK@fF5%dPSDp?c6n>;>?Tex_C-DkL-on~uxUit z%I=Ua_Sgw^9SS{c=I&`6b#z`Wjr15iY_E3nlTETR6j7`8dGA@C))4!CUY()g`_j{K z$Ak6+#zBO_S_WjM4^gJ_fQwuo)1bTe2<~bLi(&BZU*l-%nyGEH>EzEZZgmWEfes6h z;-jVJ-{^QawLI`R`k7q~+Zp{n&t!x|KcY`yY_W~}fBA|Oz2!Z=rtK{}F<iY``gFoY zr$=FbSJW7uo%`f-0e#x>PhWIxcHR&2Tw&!(n|`cC6Z%S_>QRu<L`Qc-uug52pc{4Z z`XG1Pd5xJ$9r~o@dfJ-I^F1EN*ZKMipBAZU3}ww1ps$40t8EnA`S*UIn~z*8jE}m9 zWY~%t)!BB1=Ne)0(`<TEJxmKLWBh$NyrfLT$a?Ljl?W9d1N2f?pjy7maME+0ax3$< zy65Mql{PuXqHHdCaN`OpP7Zed;H|q=j8M(>Y|;jC>XF~~JE<cAr90hE-_Y#0XQZfU zcQy8rxybwUa-O!C{e`0pti`#;gOCs8qgf!XO&%sIKFJB-t%%AY%uUh~Dge-vO2&1~ zb<C0I{(e77*wNj8mQZnHcoHU^FE=|g)>tX{DzvG2eaPWwGdJ8bL_s(}`)kvFn;2Nf zBBiI1X+vvCgHw1&uHzshgBNjm@7LoXXARclr`m-3KSb=IS}@xeT>R{<3LEGlkF{7> z&nWdog(>{1{?eEA<O#oAHxh?2`UMxJ$(H9g=^G76SEG|0TDW_w9!i_uyrD#2sY2R- zeYYRz?$E_sJ!gqQ7p%>?1zvHS8BWS6^9!R&X@1<Feqsmh+$nEd?yL@UKMXSReqvtC z;#28VAbnQPHfD0_krwxwBsfi=v?@ZZ(%p=~v!!fu`uP51hQ+zFWK`K%ihf1-s}tXj z2R@E=9!h+x88#kelHLTl9oKBWy5FfazNw<DTpHz%zU87?W$wukHcF${I(p+|_dsob z66}S3bi*yd5r_84oug`>;PUfXE}Sk9yY?+pqTGhvW;89Fy)-KK%FJi)VrRQ=P0soh z_URgQwqYILnHGjl`pC!&KI#8jiYUsf{dw*V6S0p?rQG8$No#pk{q}!upa0drz4(mt zN}37oznX9_SNbUlS;W37|JYagP)U(`L#1{&igVjxVV)E(4U(Mxipdz+bK~aCHMD-p z`p`!eync5`nq7b7ibda05b`QVX(r?(hll)q9qiUnE79ikq?d6m^H`i>O~vQ^u4_dH zZKfg<eI>l4m+OA#RSWkDKxb(K9I6XV$@k?)N=+KF6laCb|9pC4bdWLB_36e<ydGQA zi}T?hGI@&TWn(-W=4t22<l7lcCDpXe2K0L89~e?l>kr+py&Ky7Sxy%0(NRknD3dtK zk3EHr!qp0P!~&uV?NeU*Y&F8vU-v;NT3Wgv_|abzWhnR4YOr|<Ve1R%JvA5L-Z}Yg zB#yz(4hNp>J2+6J4T^pX&Z%get2KLElJ#?K^LcO0ZO*rsn+qc$HV-!#Bp&=n*nx;S zsVNVOw7uyP-koB=Kh$8TU8W#e!S*UyQTx8n@-P>=LU%s#7O*LU{7B^ekg77-29cTv zkk$i7u1K%Gi~ALX|L39SKZh!T$uuC&K>jF_E(S;0k<+=`Cxdn=f86;J-L~eS>%;g4 z@u)xVct=sc$y#6ZF9)IZR;|1C#}x~q-!OZ+OlXAqIOnZ>XWiY!a5ayStn9!&??P|j zunIoxqTKzsScM)le9dt@MdQ0ZIo=zr@+<OEa7s!&y(_*@j0&`(>OI<zZw?GN2{KB) z>w@9ITJ7&G=_a5<TCNlt8;j>Pkxf+uS4`^9)4Wp+dW`+CF`5a5$n>BYkIdqlc4y2e zSC3oQ(?SjH&Y8!u6)P*QpM)fz2?m6vU7UXV&f(dmT$8Kd>3)88_^WW;G@TC>M(b8% zvfjPlIy0uri#0bkh*Q6bt$BUUH02PY-iqa^>aECtm*q-P=u94;T!ybrwgt(;LA!o6 zP26~n#B&J0fPG91)eYaB`uyK0!hY^@>G%+JA+Me-hO`13SlB4DQS|C3)(I4Q^E_pt z<#~&jp@W?ILcSupN~t<cEWwX=^z`8+!@p1m^NPTV=~gbA6vn9`OBAakygXIB)-V!> z<!sV=!+yT6Uz8;4eh1&*-%ITa%r&jc^ZBwJdmwZkt({Q~5uW=2L)<-QPAGWW<mJ^L ztp-DImdkCDzpot9y1BkXe;kV)ovt~*o%rcRVCg1oil;POq;Z(-ert0*`>pNm;^n4% z`t|Cr))iA&HoJB{-Rm)~9$q%G2UQNA95zj-IJx>n0$|lWrX)I7=$k!rjQv%`ZS(`8 zSI<9JILwl(JsGVqb8jXKaPXfkONVOxvsqj;Tl~Ip;;l1agnabiK0%>Z9j`%k8Q&}K zcE#tL4nAkvgWXIE+abRzBSrit%?{MB>P(73`c)fTUSOs2v>$Y8$9a}MG1XNwvbab~ zxw&1wLjkq4x#mE<tyf8O&a7*v{MMC=K9`8o84^?`wuF(a==3+KynpxCb#dVu@%MzB z-?ZB!to|aTvID}k?)u}3xW_n&XXnb&PsJtF?<&GTvS8BP*s-vA##H+r5h@~@qr>`X z79@wasn2X$D`jlX^_S7gN2~$SDq3XcC*Ot!KA~UcV`m$z3D2j#Ie+qdt+x5d7`<7Y zlp_;u;3Zq^WX|ttRgmu1dT1uZ<!K<Nmh^bHwJs344^6P<HF`m(uu~%)zl55}xTdaH zryJF=znqk<MGv;I=jl@;9_w@l5nV0Zj?q1iCMeI3H3e}Zor|6>V+R|&D325R9{j=* zEb~~}XWjAGeEKIIn4g!q*9uyycq_sN>43j5G2QI2aPPh9qP=h2?eZ^`B$-nnl!eY% z%Jtg;)k?RIHRF*-bDuGF>Z7eRP9Oag>#n%zKS@#jz>#tI`#C#*T=zNYm8mM~?daNX z70MndTDjXv%}$(ie(Jeo-LTefCdBPYrxc)Fih$Fh>=Sm0?e}`#a(isJw(^bRHodeq zaj_n7t8+Q8xp+GlMP@2|ELF%6e7Cp88AO-`UL5t%FKj=T#TI`N2G7I4yd(YO(c_5B zW2XTRwe|GR;szELC_Br4?i9b?YJ9w+KDI1ug#TfuHa3ci=3nPbe(Qj{oMfaE)1k+0 zU?xW(B&mtYvAQC>`*WsY95yA;?QkfK6hSlfxZp=opfZE4ta8TJKPR9Yw1P^QJauSS zXW(nA2}Qh>HyKHEDz=Giz!S)3INCj)9=*ry#vv(rzEZOa?LFbdKk-I<9~E917)7*P z?0+{hj59U}R7Gz2`5H5+sPWJXdLLjM8qWI6gbH0LV3q;WwQk<uZG((znyM$KPq=N* zx8<kcJ}JW-P5QstJNK5N=+_wgsUjz0jLV1C2U|R=D`Wp$t+FLMl`Z!37OW1rC`eoi z32*10(R|@RBA{T`_3Y~PgDT}K@xj;guHdmUra1155#fJ#G#N!sh&<1~BAFXT%uLCP zcQrVL+Y5n?FI`Yk(L0c?n3Ps-h;I&xtDJ08E+?;qHxU^=Q(hh(DO<V7jFPgOPxpOP zT2IPb`yByF!(4O&K&BjJ=-9H(<vQ>^a39bCe-()H8~1~e%#M!Dd+`+rq(Y?NUW$%T zAecRkEN+=2!pQrb?3RH+n3;B*ACTE#%!>`Z*90Uxzzzc02cXGz$aAbt5uvcdxEUC| zRNt2@)U$+0vj_jIm~QexzqyRR28xEm_LlUR{#QA87(cK*j28Vc!`DK<y0=u+bxCh^ z6b@I6V)Otra?t?#sF^K!OWMCtEm^P&u=5<~0g5@!q~`}%B{IfWK~jp-tC}8{AhJ8> zQ$4gui#T)BHj|S(ur(heCr|6<DJdO)FY$Oxc!5f^2V(G(q6BLdq4jyKy<`-X$&_&6 z-L!PnKQ>X@uXCkZz;{!%;WW_$(Xz_X>E8Ec-{Ul$yPG-6+vV$7wcss-hWU4q9zS{d zQWtpw%s=`G*tpILd8Utdk<ZjYlH84UPc2T&{ncl;PSg?QK^|;PiMOD@AuvLubGW-I z@^`8UqSj6N(kydyZps$VU#Tp$_eC-n&ltT5;JRvHhxXaEyF=XKw}Y{6*pAEAIURFL z^lnxuRM_v$;~AA;b+M|oB`dhG5ZcaPas=YNH!^3}A7clPs%_QyI`>AYL58e<Ff*5U zxJjmamzK+Ug~2*FtY=eI*@km^?*ZqUr+2UT85qht4o1o0twM+MV$_lzwb#3`8%`mO zmqDjaRn0kx64{-{d<%R0n`Ts;FP&6m?^Pky#rvq%zG<t;v~rKZK|11ce*ygddAyF3 zJpfIq{~8(^S_31$KDMY2WhRpP9%FMo04fAs@4ot@*f7HeR5~S8*=c(tZ~S}i_%12i ztpL#4FHR}}W;w<uC0(Tj_V9w2@WJzR2V5V;;?jGQ6KBsQaIKYKzFk|gFt^WoZ%bQy zdpm;cZchSl4H$bi2_~*<^QtWi;t>l<07ac_GqK_qPFfeb@X%{=E+nHD@2_5<7N=KH z5^TU^se^Ol(9I$c=bVfstge}w!pYn^44Z7HmhRH;k4vCq4e7Rr1pR6#)^FW_9h<`< zjYT2(i?p#YIoZ;W821WTfObqlA+s)W_nyz|S2pM}R|B(|^mDfe$sKv8&=wuFPta{E zNxYFy{)wM0X`3h;o$@fh(orbyN-~|FbQebkK0j_6Xz@XQ6HejJWdnafqL{Y8KPDIx zl{Sq!b|c>S6>e4MG1wAM5ZSX~EU>m!5kyOCd40iq{uh}?N$#ikoMd0ySMk`38k)Go z0#!c|@n1Yil-^(WrV73FS97{@zMzigX$hxk#fZ0ky<h6C#_IdKr~fB=0Xt|wB(<bG z^E82GbM3?pjI=>EjM}qhoaD;1Y4+I5%2Mgh>_sq;&D00<!m>64;GcW}8nFWct~5*3 zz`?8iHI%U1@|Moa%8?-?ave;ft3E$FK_?5@t6nYvz_t#S2{03G9q`j(%SLO`|F+Pn zNqqN4bcMZlZEZx)Y6`{%K-3#}{NN9Ox{0yy2x-sK3ED>Euqin*ZJ=Sy8n~9+oyqHp zcg*Re*-M~P^&>D)X!kwB5tul-A@Ka}Kq&}~h1TY0W)IRqaL`Ej;G(p3!^cLxv*Wl@ zts;_JYYknO!rj96_`XqQEP>B<Q87@d%xss}Gs@SCYu+M>#U46AHQ~Aqf+;OxGfPE? zicdq=5|9cE!yO3Gd#``Nj0x+8X$kwQ9TV&r9?_$Av+JsT<*=0>VGV1Y)gIga+;WUN z&sTH5YqpR>MsvKB$K4Ne3&Vvwvk`}KFG*(i`nyX#`n1*#z~^2W%PM93N*_cK?K<3f z%|#<yoU!Cswv%D{a!HK?8AbuMXWj4T66tjRMbEjGW-9y=tLFbRvTr@ooFR4WspX3} z=7ehMb^eke^>RKubS(%&p{JKBe29mmW!#?_!E`McmPlw9hN?lwkR@)WrXFq)>~?%; z8-W$d7JvG5gOiQzEFva4+N|KIBD$Io)X$r1<*HW!^zC@d`5rGCjEuw+2gfzg#%~Eo zSx$^TVA^vU`%ByZD-NO5$K{&I2`KY6@lu4LE_epX{(hj6t_t*Wab&INXlTS}eLV*3 zIuDP%K}Du2KzEWTMHe(@V<*N+OdSg}4*}=s@r4IHNCuvhf4v|U<iai3)z=j@9aB#= z|GgGK3jAf&PCOeszt3))wlKEAoh6X-Vw9Su-bzVPygmRc7z9JE{_?NvHaV?69kV}b zZ4jy{yi(;^;8F+Yd22M0@U@|)v`bon{07-XcCfK{ma&rQ2xg7jaD9JFXM8N3ou-W; ze>j$)VY#&0V@T?&RXJE-1>O7&`{Vl_lWzvt?}7i;tg1GTLevPQRL7&vRHAHk<v>r6 z$FI^z#Qrz_JiBPl2}=|4fG!8Zz++s>-v7=+?~gJPS05wU&-J`9-tLB5Z*nb!`z*4U z6LM&Lz<9(qbq4Tr^@_#kO)x_;mys4$*{ICx17=w{A{yccldkKZRCw4c>Khv+!~vr+ z4MIyHw#@AF`{ToJsCy;y|D-+4Qh+E^)yHJvK^X`&F$0JV+%P@Sll+-x06;KK@*8yv zD=;XYAqBPU^*E|(pp`Ie(iYSb>OOr4>P$`zKQKHsOSu7li5i2tM@|9QEDJbjrnX6H zBu=N5Q_3FAgoeG<uB{wB^ARcAiL|wBnjp-j+;xN=f0FQ7Xo?f|^GX+}N=H*AuOJ`v z@rV_uDQUAE9Mu!M<l7C`)a+J0GcBpHX)(B&`1XaL-56K9`gB8fT6uu&rJj}+Ce<n1 z=Vvw%+{R1>XUf_=`)d>9JoLk(<p%LhT9P!fJT<&6D~U}FL+3`?`-$tQrm{2-85MAp zF1?X(Qm;o)S6NJ0xU*hHp^HA)aVc`L|C2bT5Y0&!R6tZW3DrJGR6I!NDx6oFoyw?y z%Bf@B%HtqD2M`CzHeU}O6GO9^zV5Q5o*gKnTf%-uqTOR96?Rsih2}9H;$}(oBy(5- zkpSVjcm<@Kp~7AOv$KyoYlUG`97a0e9!FoQM_UXPl*R<x*DK|{gl(*vx%Car7#?Y* zN<nAX`}Q}{_tvU8DjetHyJie5O#8+iknsx>yYh9TMb4krCq<{oQDyl8dv<_mF|u`p z6Um3P^qmizlMqy`n-}GSNeJx`5^Zixt(BG9P6<uJ%Ifb@$L^mY1rvKIH3sK8Y8T0` z(hRc4uZs&+7&ln|9ER6VH<AZJjhVkXRRHu?K*f)N{N%#M8TK@|**LGxr=hHF-o2LZ z^b2+~%}vxaG!qk5*~n=7l`>rQU9T_){X#baQ5_|9+-Z$Sg@BODX%rr)akdFq()>`~ z<Q!QfsG9CNKb)sX5phh{f+%WbGk`{k(FRXPn>Tx4rnsB1GXM#QdJes}2Zh>jK<|7G z5bQ0YEaX!k8$fH5cu-YeiU{w{jVZ_pfU5U<`6d{9I1|ADw%Nx<`8HfGF8z3K)duYB znKv0B6P0es2TE!@pc$iV$KZ@tR1}3e2XkYsL61b#j$;6liejZOd0$rx<qNhY#IDl{ zkk>-pS4aEalhH5j@@pa)I&k5p>p^LxmW9Q)JuLDUfWO}o2LR&KR)>F!Se{=T@1_s# zx`9h*P|J{-5_4OgU26josRI~q&QWo6dg`0Y@hN$K6Z8Z<k_0<nMp9(R9jXVz&R~MJ zK#yNZUh)uN#9SY*CQ9F(UYV#Ww48@GE_l3Z52X%lD41Fg5hz&kuUj2pZrPWA&=b!s zaK>#LP+nfX24>NwxEg6+4c8IJo5pH_I#;>Xp=_0LGJ9oe?v&(YJL%Iu_;C|<m_Mb| zKpO%pU9ZWz%2hqv16+kT=8~A>@X;8!KRf6|r8D9LjB;e_>E&W*84>LSK^NAS37h<+ z!DBsj$0!XA37u7fjuz=7s^huzEedtuF3mk|<mKQcp<)ynA$`fg(*tY8iaqsOAK*rH zL!u=*E#!c^lY1PF;GPn;>ZUSm_O0v7kd}6W<+0Pyi@?^_&|s2wx7+g*fX_euC2ETF zYCwnppY<GLRA$vPfMVUXNE=)6eKCV_89Yh{UE6z`VBSi}pF2J&0hVP!;Gk0V9qbFR z&kxjGI@l)ru}++lpsOsce+{&IvA$^6?SZ1o+mE<c9g#U|o;hwMuxOQe{NwNun}TMM zU2#cG9}qXBg_<3om8@7y=ajt%v%G&Et&P-vlp5PZ74nBGwS1f$)7?9HHTX?_AM^%4 zo}tBo(bGn3?<k!i4-%Unf&ui780X;mU9aNJ$7d$$%E~Us)qvTI2E%=AxDDRXxa4&Q z7TdKnt&S%C1oPW}pFST+-D4<ljsX1$<F`!*`Xa+<c|AJ97j6|pGIpnm{l*SjIy3~e zb2}0Q)t|^Qr{fAvb_TyX3gIdjJ3h9-WN7DTi#STDQG}yFSat7JEqefY7Pk?OCrLU+ zGd|>=U9ve^A0wpv(f9XDEVW{tS=OIV9OB%1pB+`ks0}jqA*0n^C{pP~r~ymhQ6UM` z523R<R3GCGOS1U*vC1b#_Lsw8vaew^tk6pMnM))H|FqG7fkk}}6>I2FXBfsUDLQB% zs9v!5Mh;5%vyDG$>GjscGJ*O91}~-VQOOWzotNzu@#=s-->RitP0lyPd`>GybY_$4 zM;m^ydfLH6u0b91(^rDMr%yzyU31+|T4MA)Mt<JkM-NSY@7ZLS?jqmN^}cLGz0;wp z54kvU)%tl(z8nvZTkB@}NilM2aZ@Pwl(4mlg!u6imA7Zkrf5OQu5-ty4;uht4}pn8 zPuG95QToC`#}x2le}?v;bk)Sf&Q+JN2D9Ej)h0HPo({2@!gTmoPCW26rtAJNeC(-S z!=G!VjXfzVkK_UgWZA&j+r0X}53H^n6<EG(9COvFJ!2p7f^^z9%JLY$7z|D*EUxd? zf55^&_yEk1NMe3r_138Vv3nbt$YXrnxnv%4tQXmkb}oCZD?pY`fbg}uQG%bpi>Gek zcXXJ_+*>0O^dx{_?}O&j;PtmZWa^c&WJMgcvKiI#zvRejlPymHvX_qLT2jDS39YTu zE@<>|<<SYYukZ8#Ky<OWTqiaBcJHPDX4lSWmYmDVLS*4~Uv!Z&hbct<LLXKbwKjL? zZZ(4rkW|?zC$*7}Zd(Yl9eENL_Sf!<ak@lrt<K%MOwfa~Md(IPp4{wg(K$FU+WtCQ zj3dd&BnYvsh_b6vbG{FpXl#Zksg1;eR>{jfoy0_K)RXk0E?GM_pr-g$=Q?R;Lt<`5 zf=ckP@R;Nu?znm8w9Kp|?fW0mu!cTB(y@A&czZ)~38qGS6U>^o!(?nW9i+Q&PD@rZ zm_z>w0Le6EFa{)M`B>{WI55vq`j$u<QzL*I<b>IZ1(1633|2!8A39}|PEY4JHRIve zf4r-SBz&cvv1Qt*`{4-8BPjd*`;W*GHuW{=Ef~$$dT29JptLg|CH;O%Ra3KEErrG# zmVYT8F-9f$M}+&Lla)eTo4;ut44}AJ10)C6f>$ezhL~~^%LX+JWYB2YG1~E|2i;|Y zZsJsMQc&-FDPo58^vueke@E4;!M2}dlb-)Vvj^KzxI$FtRuR`BKAaAIPUcc~i+S)X z3JIq#J4f&ti4D()c;ucf)bxye475((X#msHyCt-zHgBFi(A~2<+Zf%1?ipq*lKd`! ztUZ$z2u|Jg(YM5#OMYu6MuUHayl6mFXC}xXsw4h<D=Oe|phy5x3R@dRFM_yAZ9l16 zJ)Lt_hs{a3>rcV?4!)J!8gxY$(xP`OaDoaP!crz2I5%*$pHnRPV+;kV)CJy6L2jTX z*G`^!f_d!Uv}FZyojUQd!naRYD^xGD)c_5@Z|HNk>JGRq9V^Ewt&BuR`kI$Ul3Z09 z-z0t1X;-JD;1lnY-|p@{q?rg^`|)9Qpt7E%eu<WVcM|CNgNHz9B&mF#az3*Dr9fcX z@7r6)RuV~Gzou!%BevHp`XGl<sb0lR*j_!UwXU){exGwHoo=dX!n%?2G64sT?e11x ze5spnJE@Mv$4}}u2CZ}R9A&SL!f?M<2pg$sd`APBmS3;8KsNW1YC$uu2yF4JrRIc% z9^>Xdx!n;PMPtTaVMuunk;fXSv?DMkVjWPquGNiag&C|A`nzJ)UkGV4ITeP1J0)>W za~palY=gLCqpxi>v`W1@&@SxxLW70rHv7PWuw%3e?GHD_9HNKrF)D%Fgju_Z=t^?! zjG?LQ=^PThm9ZSP?3qlGntbnAU#c}tE8Z$Znm8Ktgs+~qpn;3nQw#c7aGK3w_UJ_% zfuokKEeO;pB(lzMz+ttx{K*^+lKMA!VGb46eI6Uk`*iO~UBI|`dRQYrr3KP?z{OxQ zwayhks<3_xz)kR}Bf+nnS}Y*BS#a+`n@N+msAmgox>0mMWIcuFb-{Kb+RZ`eOEJj} zI}$j%Tdpz<-Q!WIdNq73*v?+f`Wb0}^TA2n=g;#-PHra~$t!2smMhInBfQ$v1HoDb zeWbQBCIPI+CqwcvN@|{{RhW+u+3>2LoZLT$17?HE;AxB~QE`m6J7_;0Y&X~5ddX(0 zrfu)em}PgLRUzC70o|P`$osbWNGLen&14Z;FKe;A(1kdPM)2=SYkwHA-xJfmu7MP$ zUUEs{Y2;Kban(<2BV!O7zUqKAQaDR}w8(%-HH<Tv_B$}n<p@V`YHO>=3LJ<8AvoQO zOJ=SWIAN=C+b$y59&U=spK#P>OB44jb`=PQ*}X_yoeN<iQ4J~@^9Fe_6WK>XX}X-Y zl3=7oF5WGiCiFo;rUktxnr{~z!|{IA%g<x=z{~0v?>90RNXju8d?w-82*)>R+sHBW z(#wdbPg1ueu_JNBdPa<9&Md=5T>N0G;=ka0#brzvYNms}8MU&-pdDh2r}@w#mzRzL zgll2>$4Sj9FRe6AvhBhP@Jje&fB&`sN7-b7{j4&)^(g<(_D9{-EBl74V<$3k-&G2O z?xVrD?DcSsWzR-`)|HdzmjxoCY(YjvMI^CnoFQcJM1EedT$fLE#&bjO%@YR@;p$s? zhAmR&Y2!|@-F+Ru)qrH($PjZp#RR$$P7Vis2!6}Y?rn~tC;F_~H0pxe_qPvLdsNj< z#<6MmTB&y42*U@wq-)*#>sru-%W$}T3e^c@gT}{ZMImK9f8Tu{sM5y+vxIt^n8YU< z)9h-7LTc5!u}>QoI)y!E_tn;u6XGW@>B>fa=xo#nKSP5}@`zN9w<Tw#h#Vdg9mGVL zR<fi(y<t@$Hsa)UmE?tXX=vOJ^NU;K6CUg7bE=Mq*v*u+z6_CA(eP<z-AXBttr8y1 zR4a&>Y{}kRj|Lkw&3KmM=tMYmD~WM3-oXs5XH8ZM2Yb2@EKto<$D75Fr8ohx36q?N zSLbZBp4U0~<r<dCPB(?CaTv{&+rxL-+HTHaBK}z@v%=|<xTqecb}-~wc{-PkJdsEK zAgrU|F<Mr=SRyK>s&rAAw>MlQtaGEy%z+M4;oEUAT@1)k5au{*<a-<UI_F9Zf0+jG zi=}sY97wn8O8B2(g!he4k1^60w_QRCi1^%X^68_8ywAYGoXfW}w5!kC1?}TRZ#5@2 z0p0ail7*~VkYoMpC3W_BGSG)a_GlWwAX%t0si=mgnqbVTRtHo01XE`(GbS&;)P8`R zN`Z~AX+P4+<{_giz<x`JjKjGR$((#j_d!)puWqH)Ca@#oqnUt`<tp0?6?-sEVj|X2 zP&`YtPxZcG_AM!%tVk0A<nY}BlkF4{Vv%DeJ`q}r-D!_rcuv^;86`8oMp}s60~Z6C z@{TzE(yArY^jr|w#)KAr3&~7fUmB6zg--BQ201n7*=7@3fvRwH<%P=&PTo%HK7Z`p zB5^agR6fPD-F1IY$<2~Ooun50`26HIJe134dHt-xcUgsuW2HbNd0Or-fR;JjEPzI2 z|6BTvnEDS<-OH{0i;b3+Ue9ntYK4;F2tpFZ2I|t?M8xJx$whFCD{(b}Uus0VnN%G} zojktmZG2}`-Xg#?mtxeb5OH(LRqEhJO%Cj(5HI0clN!cS>_AtGS}#omY}u0=)w?s( z-<#qG<?W42b=g!gNn&F=(|5kT3B)5v4mH4(8iddzT!M@k#62n(Id$|fMO>IuBihlV z^yC&kpgO5t4$h-u)YfuRmPLgcRLb(eXW$$~{p~op@oLX;iuht?#}%q{mlj@i(M76< zR7E5+bi7;Yg@v0pBM2oxXCY#nF4rmdYWUL0Pk3jx^UW!v?0)}<%eD^B0@;K%Jwppv zRv+*<BGsHpo?>&j{G{KdR6k1f6FeI|-aX4Yx0O(^ls}$YhLUiv`b;$G_cATGv{>%Z zZPtb~koz&&`6|w|(1|BKT7<3+W-7`%vZgD38O5dU#YE}D9|Cu<<tDfiU<&@?!m^W* znX&{=zWu((RF;($2Q)$|uPV(?2|{V_Y7&!n*y(FSr&GlP*Mk1=GUo0R*mHo%mYuB! z)>X6D2(sna89AB`A|KJksXt#myW`3oiK?qJc6v&0KgIPpZKb9{7@d6+U^*({Hj3{2 z+J9U??NOPrpnsW~@ttd~Q+!!LWYdz5$zEACRn$<SqeGVTVE&~;qw@iq77d;h>Rnmx zlH08S$<ea<L}!(#&SGw!!llYF-D3V?urJAF6k0BMk|ba4<j&XYj^1Ke&ofR*QYD&} z6sPP^QF~U(uDe^kbh{NB*pgm{GC6-xOYw`Wv$D;DBdz<>`%8Fbv`P#m{W0apO>IY& zkMRN45Iv4$8lKMVJxFPP6VjAc$L-3ux9oOc%}<8O8WekOPOC?^GgR*EBjM4Rzlg5g znpI`hO3De-fsHHn6n1~AF^F#<*Jk(=Uw;6sms^=Oj*4dJOWwX3ZAoJv)2$tKtyu~e z_C#SYHSW>W7;{?ns_^Eee4bcim#+H=Eii!Q^G&)PlmEfqdqy?cZEM4Vf{KC-L_q{p zlp@&Z0V#?F2tD*7BAw8SfB``f6)7r3flvej1PC<*LWzJB=@5Ddy|<t=A(U@L_dfgV zv-dggbH@0_c>lbA7)VTV-|Jp;u34_@nth$)v2PW2bTpLNcZNRS<h$NC4cx(nL^N#k zTDh&Xg4e*opdk0FT}8tj?PNT56=F=hV`q2QpGZz+iYRRYk;+h&GS?|+;*1l%FJmoh zmc^O@x$3uku#`1H)46VV0xjrhHw5Rm@oc_PFAb~dVr~6#ta#3ap^0@sYvomc;}KV- zLNgyZ{QfahH!lL~Nu3eZdU>cq31BCuH~X!~J1`7pYKY1PqiSAvxqD%UR_yTl#^g*h z3zBaSSXR(D8D;>U2!We{)C~`LPb1}Fku*`DiF2JMx>3rk+j>N)XpzV)#O~&_8cdiW ze)VaIz(Mkn1w&H_{u16B<m}`|BlJxwNS-4PKeT<D6C#3dkn+-eB+phesH+LO=MMz8 z(}oYAv&ZCmyM5f%GVDyHDQgK%WeOs~Dc56s11c&B>@%R!-*t^{=M{mnOGPGS?@eX= zT)zZrd$8_K${Depx-Mq7A(RU<;<EjM;<x~Zo~9c?oprlYKUjiw0a4+XJ`cGg5oEi- zGe9{-*?3oXZRnFsf9cs~(qKL-!c5@XeAo@|n2r{8bZgp;BM2M}rL-cO;Svrs&j&Ma zXU2`X-!Uqg;)1L&mX=$bGF91=F5(KMWE7CVU7ah*&$~&jzj>%D8kEilK3G9q0D?nE z<d{muA}bKf@|~HHq<6XIOd$y^gzg3D#&L8KN=@X7R_QATHr!kn#@GXi_e?xgArKcz zr@~z)--VQJ@gMV#EVJeh;&3$J*y$e!OV=sHZ|Bc^hK)*NZWkkwd3ybDgp|cc6ER!c zk+r|!<BHnc^rlGLu&PGw-O$uaam<62qF*PDg)I(=)tr|rQ~B(dLjt`(-$!9^VZp;P z(|<ETlczRD5cs2}n>$bE{W%wwa4)nixQ22+lcma2q9Q+WdF(lmB2HzOppFkVAa23s zbL)EYm6Qhw?6W-dq*!?bldG+>?ea(!YR=ehNWd8EI9vHfBqq0<=cU9%D&(a9=H&EE zg;eKyGp}kqk!gnI9<%BzdyeKVp3jh$F960+acHW-t($N@hr}%DeMfbOCq^XF_G>5i z7uVi2h&g%AeCXuX5?7+(5|G1UI@-QP9WmWU93Mi^P8FmATf;V#y?oFX1dXaYI>g8@ zM|q`nK)$#A%oA58;&i<YoQbS~v9StJI$@~qDa@>73FRW0>;ohZfNaog*dr*{s1sg4 zb3AQ|OL9YPIJ5CM{sE}Plwk-c>n^H(PC1XBD0Q+TDRa?g*n>SECElrXw+Mg2dCydk z$#r(6x<dYo{4ki2ry;>*mGwKLB}G1$0QiSznCnqSbQ?fQUEmfUPJZx6_Z9_|+6F$4 zJ%pMIF;G0rWd@}(TSLSaOO4<?zC);pK%-iv>0tDkF+vq@XH^D&L)wZ6R6EUM?sC|J z7TMu0(TM>sF@OQ#TpmCTomn_af9PAzbJQ-8;vS^Y%_`W*%o~O56a!`f*JI0Mv(tK{ zB0=&dfken@W7yySGtUyBK2Ph&=Vox^8*!<y73us?A;hF?-u}T@dVwLfe6$FtLe(C= zGLLgD5{~sN8-B6H67_=f!}`X<abpgO7TErxL3u_GjV&Hb!UkNkvIU-`yD$l=-t(RC zMr70KRECjj-9q3<TAOpOMOc%WBpmO<W?#|#$X%i3?P+`Xpmo+A-9rD|%bt4;Y5}ub zs}rfYy`&oMDARJ-d?)%n_JI&ps)(1+cRJ^=ZiqAukh?nykM9LJpheq^!+sxek-{T- z<$2#K6AGo4e+jXB;2hzN(I0yvgM$afAbG}r2SX7Oe>YESV_(bU#9ku#>cvF6`K^)G z#HV&fDtE?5#65ee()OqBdJgn4h}*+vyMpW-BZN+asI<2*r3~QHEz@O<6HILCWv@%L z2m5gm7fRh!Hb~s5E9(Rg;*<GdzMAz}avw`y<--R-g|9Va0`}2s9`1_CWFsS2O*J|# zI3&CF{qEA-?*|ekNQh$hE~s)!!ah}t38w@=yte9a!+xYvBf^&{mS?t7Fb0kOtp`xH zT%Aqj7S6!VT0yVaJ5b)^wsr@i2wwXYW5@2Dw*zsrQunv>V0xsrw^)#myH{qc5$}V& zoDi$`@j9W(Uf<D~J|BD1r@#?YJ^1EIg8r*2-~2X!ozWE{>M$}rQ?iSdRtz`|wvY;} zdT^GVm621{N9UVI2L1)rs1IrN)$IK|=&rdlChb7Ab;G#jhP?YYC$t{4=Zxu^p1G!# zeu1I%3;7x>tG!FXk?n>Tm4mgHYN9Q-1Pb43Y~q0?Y&+QcCGQ=CDky?y`mGPTwJ90@ z7zC*-(P^$C{kqVf9({lfI8rbVrpx7af2FvwB%c=G*#p9ojP#no_6h!I$2B0y5sNyS zAZ8zJOCFj(IkaZaM4QZa#0$jP+2}7zQa^#fB->5C7%y57Ursnu1WtmtT~=)gi_g@B zct+JAOJEJo8BdRif~t3t_<>b}tVdzKFJe)QT~15R+MM_1)UyMPIl|jpOwe{YZ3v2W zGUw0El6p`N;+$#BGp|t{hA^=T@Nj14m=SI}7sjBy<_qOwDW|~Fji2Tq9O`wy7)!71 zs9l=}rah6)#&l4y&M-XMXE5uh?2PV&uB2hzq*&;lP2&S#uUv&0s*+8dTUts5KPx%2 z@NHMa<*(ApGm7s$x{PS{vfkd|Lc3ChL*-PrV)E|P&j<vJ-)6zUgr3NYS09q{4uXE> zFvMovd_V*2OPtd)<O7iIt&ur^Nn^y%Lzb#&9c1%IYuskNkjFDKUjabRPhqymQsDdH z^=>Fam^ax@L1ZuT&5+>ZT}1g)044D=RU0t}j_L?EK=Oq)`M%2elJ@oyl`MX%{UC#{ zTq#EMX!6zCkBQmE4~KJc<pkquuJm_BcOe@|J%DRdz(x>sGd5rZrJF15GvjW;=C-!{ zd;_|jv#LUpGCx_(qfGo$fi?8{3f&iQNEO&-MRk(n?1q>mhRTH4mNtPTL?d%n#?Mfr z8(HN6w<(n+lY48QP-<QK3{$6=>AV4O8mhG4eb>Xz9|fh7OG_r1T?J;67w_5uAL_&7 zPz(;|PrErN`EW>usbzSSNNQ>FWv2)st;xa%3L=zMe<n6r&^tO&mUMjxjD?`cP?%kJ zfS82m&+k|Cisu6+Ma9B<rjNNQaeRBnI`LDjWtO`Hqx!cU4mWyHH@5+FW#(1ej$_sq z`iY-!KlGO?ie-0B@9V0i3p#ZX3pVdXjUbi8&?V6jvEe(#zo|ZX!biI9f#Oj#EMKSF zV!M||CryRd)eCRyub~=c%^Kh7ZoK8>M3h>lJGelJCv5Jg`?G)1t_~g|s9n4Qrl_b$ z-lH3x9ZUl+2B4W{B+!0FS+P-upzVV^9_6oG)0i!xtAG(UDwd4OTH70%d+EqG>daOQ zlWpEJFx5;HyPT9yhn@3Fd<x23S7&{%7!#oge7>3mr(=*4#g)TLL(C1fhE~pUB#0qW z>eN`DXeZ^APlcI-CExPvDtV|R@!hrp41ldbf<d&cm)&2y540COF!m4>9Avndx3uPI zSSVyX^KY`ej@C$7zm#XKii#rYaI;;1LxNPgeV=ob+(Hq8s?+2UZ#>$w<<Xkw#v+j8 z2p%EdrC5Y-lc(BD<8bS<XO%7bC$i_(TB9nmp@jt`K@pLBgj1p|Uz(Iix*WH$wxMN~ zAX};FFIVKw%12m$qp{BuBhGxYU(bm%>8A&BRb2NsfhE(YRUWUI^^x&7VWT$=Dt`G~ z&w8`vxeY-DV*?{dcEVXY33!J5sJQlbECA}=wz+B8PWdC12iIH62AS_j_l=NCiP&n1 zn@4ywpnt3WTf<hmldlO4%}WUl?nY+x!a%qR%M81{Wuu*TK@7V2B}usiwBglU(lNvW zynf{S_b2kh1=n)R<hw;*rzdGCLA4JFs-ir>Ou#-cdG*W>KJ@McV><ACVEAma4xcg< z_Mw{W&Ec2^hLKj-4uC?N&>-u<p<W*$!%V||FozYHP7W~H!Bt=2xP-}=b%aWkoQ8ss zxrf#}Xq^&7^P|uwdX3#e3$sBSm17(k8R>8ZsZ)GGzhtN5MlZ6ogR%5?naVIImXjr` zp^f@16_j46ljK)RBRveQ+<w2RGTSF#ohDm~&fIn!JY}99ncY~K=TJ+(G<^>guvESJ z?%Sb{rq3pJ(Q5hAD*?ZAg6Hx@^kQ5So!(LO>nqc3xR>AVk`Op@{M=<S$n>_=5g8d{ zF(7)9>I7$;Jpcq2LXpy98nSxRzUneRo;G-^06^?yQw${PS+`EhJ@yhIqI+vXLc)2_ z@PC|DnP^MH-a(m~Ki{g?5m2tWfCx*t`S|7RD_)o`MlA#up+eI2xXzGLK7M$q#em71 z*7M^v>7p$1sYFXkgqLd5=@uR1sPAaG2dZ^6E4T-<iZz9W>oB+?HZm@x6jQ`uXNfm5 zR6|h1dZylKw#s)yaWjmCKVvyR&|)0ZFCd5il_9U^z4%f6woBc$E*&_$p35t{c`5%W zJ(i}7(UZ}yAwvVnCZ_!S4(eKUy(%jAvY3~K2Ql1QhP=N+9#PSN&rLrUxxxJG!EM4x z4XYl23qCbAH;C5M5A*VCEQSm*=~D2X8or!(>kz>XV1I8O9$sG*M$}a9u77V@Bxm*q zOxGd1Yqz|FIFITVRJN-<<(I4-dG2^tP3#7CJBLrVM6ASrmsvo*M-uC9*PxybFPPt3 z+zeaRIk8fy){P0<BuM>cGS&P&xcQ`Au<(2_Hu6Sn;e|Fe#50AFA7uQKzEjhY$b?2} zwIwIh;=G)A|1YPW{sCy!?gk~^ar~Y~PN&Ngb5JTNmscFMvR|d_0_dO6-WO*TlzVZY zIYIxSa(~-PG^XSWPfX9W@E&IQ;cz8F)vG_tTgY{`RT)<Py-5h^s>>?~OJ?fbRyc2R z$c~Kn2qOFc8V!cNh_=J?yMqe({b!*l(=H``T8IlFkDj%TA5~>DhyvjZ%)K|wi{m~t zIRo;ndyq+C%gL*;5xvSA%M-(>4C_~gzR2Qu653TxIR?&W?Z-=a`#t$u0cbxl_2J}j zIIsdyr8LMRS@#(Y8iJr^DG)X1lK#!1<4e#=f@TQo#9L27Bjgp6r|t8nKrX!1q}7h& zPy&$Tg0aXp>E8KD^%HRNLFHT2OZ$i0O+pP|p(4vCX;g~<#;Y1ckcGbMU@(WyuL78B zT;R&C?&nO-o!ky)cF>nD$lu#ek78vvnr=nzCq~=%{|q$VGD&I=K<Rfe9{?iJxt)-& zplXy^<-U8DR&lpembc&p(&^FgzPu{YmPEAB{EATQ=_Z~SBQgE%Dz*b!BM+jg){OMV zFYdlIXOb7tNqehHn{N~4dGU9Ak|j+@V`5^8Z}VL<kYGg%oJo7GqeKhm33OtJwCX4C zQSHV613;S~q^1W_`<=?(k~d-Db%{C;Z)*7habx=WRI~*@+u3Cq`h1!S!4ah%O($A( z-<GT$G5<>M1^a9;e}fpn?ropr^#QaXEMJ~GB01E@Cpl;B<$EnozJYPTS>h_Zu($lF z_)=S|pWvDE(%ELW%Iu%k-z1wBx?~})i#?TS@gs?`=tQBxSjs<O*@Hq)n8_&sSyi$S zUNS9bW<P%0h-;>1x#AXJ9}d7iyY9|CgKXw+2K1(-Umk$ytrlIjO;fmr+i@B?UG`}E zOGN!3kKWa10Q&r(F5JI-V0R5Rd(0R+?rCq{%hfyNXA)^&;6`evYk?=;PG;|C#|Y#B zEY^{$r!cX4QFPvP^oJsaB5v+5sBF8q>nPXmPbjGNOTUk0*{G#uii*vzPh3>hM*fPE zXh@q@lN>!jluwBj=_`p!+|H%J8R5;JZnV|_JhGc|vmVM@=x*jfjN*gQr4KNrK-zG) zE?Vwp-xw)?61dpSs@BOW%Hh5uLFPgWSarFNHdgEd$K!1211~K!I$-I!NugC}Aq$M2 z$Vz7ih6a7C0BUco{z6@}9`j2w0)_-)WSXrN*V&;FO-8&5oU{TA63x7;tE2M-Ob7fV z@O;9sl&Cs09EIf2)@ICj8%Iruumsgj*h{zlPkr`m+9d~{XEIK}V2V&m3kY?Ho0JC% z7@LiG&}%LXI>IhZ(r|7=CRE!C)quHtt=_L^1FI_+Eq0ScE|qjIu+B-(Wu#O))-d~f zE)IxkV6ROf&4d0lbk&kj!0Dp1V&CnR%XDrAL$F^QE1%Lpf3;y?AOh$NFIJ!DbW$1w z71qld4~xrrVsu3v`mPfz^+ef9TWdWk<D#M_b-rm{Z0H`@RqZoBFn3p;;JpU0HOcsg zD%!g+l%b~*GSo7nX-7EA<#eb(hEGqD!V6Ui!OVd?^ef-EIs?(6FB-9e9GCfm!mP`h z1l?1AM1A{qcX}hUM;o+Ya|*#2n>7_!oBJK@RNI9LiIdSAq?WR_j#Z=Xfl2gbNa)2N zdq*}=Sz5IY0%NNY@~KGBTT?|0!`$zfC{eC~8Y~I~@ZFJD=W}S-@UiLZC%|D~p`Z?e z_@x5{I0vj-f`LOw&w+H|F4o{<@$r__pv>)w#Y{{{B6UF#&=n<fM&R{cMJb-})A|ko zCtT(VdPbGmMK@LM8GeD5%A9!(EJJ1f>>v2>ME3peGDq%#4whjl{h_VkQYp{L)U;?b z4MPthKB=n93B4_NtN?_~-16HFFIu)tqL`|__+&QpBr+zqama33me3HLEp*5L$vN>h zD4cLiTD<q%DZ@=wBA@9_qm~f=Rc67AP&r%{eE0@g*J;r1MP2h@nMxWDWqH;h`qP=C zLd}K=*6Fe*j!tkDnP`_$BGsaJAD;#7HASAukSt-B-IQ*_J1!d`InIwJ1a)90wg3@f zI1P^Q#b4v<hjbpf;>HP&Qb&j|J(EcpGEk#Q_lcIfBx>Jt6#_6&`-y^f?ejF<U7cQ! zs)yPPC8HT1)ug{44zXSCfE!MMsmsR>JY6jTrq{TSiFY<k8A}5gl(tX64TA+`O9`W_ z99nB4VxWTtYtRAkn(;c``SzfEfLI*xR(<gW?^_Hf6}J+^4$+{G(h9d^(>3%GZzB{< zbE}>Ng}Ym$2PVFM+)tFhcWR;&FDg7~orsvq#+ecPP<c@xFP+NqL)BNXm99E5yJn4j zie;=23r+Rs8n_nJ(<RD-89}Z~4DjfwsfD>6B||)5=BnBkp2qo37f?Upej0#a$7WrH z!Uz4Hj%r6Pm8=CHsMuc-+oN3{rCUh9#W?`J%mIY=tqjcM*+l|z0P;Ln;0Za;x@G+x z_988>5IqnO%i_8SveQ=4nW4E{Q$577xmO3ssY$3K)Yt+LvF?M0V{F;UNu_(AG8$v5 z=a`bR0$-z}GeA&*e@;o5#^-uDCA5oLel+u!b<j}NRu_s$LT3!w5)ZqIy(Ao6KM{au ze+r-_3t-k1|BA2dKtio_!{n>D)iNVGeuT*VtwGcBr}^5UDiYD;r{kfhIM_C{P2fou z=LjgBKLW$G0}CIB4qu@;O5b}D;<H|Pf}nqqtOm;$^-DpG6AAu%Ovmnv?nKuD2=Aim z{mdJm-<-M<U232)45JB(KH9G0oamfilSOgjY4Ex2o-Wp^-6<{*8NTB<mBM@6iDqSs zuiFz1X*{j0!AZw=v;*h}?Evz)viye!RW*A;i1-np<rgcme5FEKO+GuNhZ{XI3JK)> zavM&}_AS#f!ix-}uC*1OY;$;Jear!#a*SCm4%QDq&}-}J{hl$_g7;-<ZOJve7%Oy= zn6<}D@gLZBD$LSTVBw}VkQR_j5YEXM6^Bg>RM@|ooM7*#sJICapGt6zad}~!zYOZN zgK!&s(;~!%aHMfz<7*`p`SmlY_1WWq7JXBWRBi3O@WtUlL-B_N3|U7OYMpvXbD=>2 z)49?pB(lWI3QK;<OMghmG)dYVqaR$-MQUU$Ey_mS&{@0ebi`|#;58s0<jMM0<C99& zVUz6+lTY}*RMea*N4wTcRsl4C7gzAXH0AaTiz>9@CSuDyU9krYSU6oE4Pqnpr&$+f zhw&w8a|W?Pnh2eYnw*#2XqXUaXm8N-@&WV7?R}08G-Xn<-A4h$o&r!flmq2}R!0Dz zkGNg>;**aCdmXElHoq#A$c>(h6v@sMV7(-PQv!9O>*@+(xW@)<39`tlPNdgRzvzR^ zUHim}7C`i4(YKR=X|_K{9o4B-iOLg|oL9rn<~%qJ2f@7dzDA?(s$Q+=&JRP{_(x~~ zQF2}aFc{8_YKuR%qafzQuetvh+74A^oulU^Yu|1{^vuYddx<t~w=<PDS0Q)gppKB4 z&Y;nWvAaEN{3ckts9QF<ZI||HXJRS5e;Am3x(s&G4QX!ew7h52ln7--yN?yy5>fpC z)NBbb>&!B!_Dzwpg|TfCGECV#%N|oXAa!M3SE`#~P32leSLxG5Iqq(}M_88U&RQ>I zT1L9pj))3f`P6y~HmgE+6Iz9662?i=9YAi(m(KtIr3;F|E&YquvdZ*FJHT=1CNQoa z3HWug-8vGb+tu=TiTT0gnuZ0(Zd^>YF!wx9jN=1MtTj0jH7vxT-tjbG&+0nv+SZ^R z&%?yUl>4DK$-gFaZ}x_I_^6Fvw!_mw6)t0KD%Ax~O=vZIub@*Qd|x%vx47=8{rYbB z?8av~8RH?BH>hF5T-+G0j%AgkVQ~vE2Ipxwd_aN1>E;+p6V6sBh*X$Ld>43^-BaP~ zW$n|7^c?uUiL1MFS@qK+FoH3IjScP**yZY6e|c>FTHuhVJE&JN?{Kw$-ADumSWZU^ z4D*w&fKHJYefMG4-;~ikwh65^xowXWGIfcG^kMp;Lr{O3g{PyV1lREGR1O_jpfTE6 zY&`|GK8BlDtTrEAWu){BV$OFBWj3-wsT;WY#j0a^_XdYN7qxQ?d<u51%U#Jk3({jl zP^(hWR#w~OgItoFCKI@%Q~P()tpFu4&8r?Q+$K`Al4#`6)Dx`Ba%9?-Msp}Wbtha? z)UW(B4P)etGKlvHHW(fI$*wl*P+K;{S~$yE!I`BTq4MGtzL1EtQ=dN!$PUPN;Ng{? zLJ8#B?o+9H%jMaZ{P=3yN&Iq3BWSj~95o%xx42J(055>*zDvUT!BThgS%5_Itd@2B zBrxbB`XEa|0<;6caTW3i;GBy~-KOsi9%SApSWYbWUWu^m$u*-yF6Y`9K4eI#3+JX7 z?{hPvb)N6D{}BBu)aDFj?-!NNRMrJN=a}=_&PxEqe}j2F668+B0I@!3k)bg2Gj>qS zGJGk_!|0EV<TA5AJ=!Z5#JN^^$P4EfwacSlqD3DouH+><A6OJCa@2-Nse*m&Gin3i zm_LwxDY9zUBmb7pXCI&$209l%vyea(?82<vBO51$v~RU)uN@0YS#?4V+xc8U2G7ap zb{o2z5AXQtd{WNsa36GB(>Afu>((Mmj*2rJW&z9sYosFpPy?e1B+%)Y>ndE|Fg6&* z%7R+8qpq`AdQz2KeVB(M+8K~F^ed?P$3SP`WJ6mUj_fsDbGTQh7$yqKE=$lqSXyK% z@ic3%=Zu2)IPcaoU6>1w31^zp_zmrs!SjLCDm|YqujC<nx@F@b2s8#>ZM+gkTzO*Y z;aaEcUicCHCUf@3LGEW?GpkKLpN101Ygx*h`;W<-$xzI_&B`9r%JPMhd9d!COS1=& z3>1s^6K~*i^~9Efx&1CJ`*q$H=#z08+WzXZ%7wm>_kgavaY3kw=bzOL24wH9=uVP0 z3XA)kLU4VJ3ySk3ftD>G5>w-4XO*Z%dLmKIQQmhw)!(hm&&K)D@S?4z%NxX+b=Xd+ zXs?w>Q(>sLQctcMelZfv`SVc6=|W$yH<5d7@HyfBq%(c}i$Jgjw{#X|OQ=L5E&Q*x zV!I;mk~HUM<E?x*93LM(QNXxqq_RM`<+jjtHqHU&nVbXo>2(5cT0OC?7d;)VggJr} z$MK%neh$z)y&phhIt*_Oa;~&0Qyu-(9@*XLO;MTGfml*hf$B}j%|s8_Vb{|6xXMdy z=e?cMv=^I<4yzJb)@?spv2%6TF|Hm(4hY6tq+}ie9GSW)%wgT_&f@jip}wUvLmdFA zYf0Hl;OcuR2NXiW<r>y#A}5dR-;g(_T#YJu^_5hjs#*Gz-<Y^KKvYx?s|io-nEGs% zd8{vWf%c;I*8VP%PQOEgW6NSH;->KTTZ@lH9e>;GwFr%p{twgT@WU#VMK3+}ZZ++s ztk%v#^dC0KW?!0@Ck@!=MWr6NBNJujTdShW*N}$wrigYCY8XmaOB7Fy*M+(TYB62) zj$1m=y)R?w+v?B{GZ&{jF&fx(kkG$6&{XuzlLVhW@I*(`j+VfMY%7R(LCySku-ar5 zc6>RMJ^9tqvkN+Uu0s1u+I)dBi+@nEd;KIB2F8AKEfsxXrd5}@<Q`fQb;Oa$)|TlW z;iE{wY^xUZ^9Zv`CU^cJS6f*;5!QXeswDx=S6ih~j8cdMXaP0IS%6OPu!+4BG&ZrQ zJM5an8Yu;^@5u2*<nB$-!}H=a^V>`-MC{$@dNhBy9{30u9hjI?7Jmbbywf@VHY8+` z#)(3~j<PQk_u)~^T}h?>J_PhGbKbM=1FNN}1PR!5r*AvlCwG-(e$YBr*Mv3sk08}? z6<Ro%nTr<BT6yeLV%mLM=fqu@IZU>PlfIpGI95#+YA$T@RoCM*&JI(yx3rlpVpvAJ z;R9bK$rDA;U$O!XfM1I4-b@ZOK>wOk3tz(AfmO09x(U534L>#Ub`lcd!TVfZk`5+# z4$N1Ma-O>h%9DW^Z7YqdCgV3^#a(`U;NvB1z{Hf<Qr%M${C#Rby;=v*+lHUa#q6e2 zSe&$<&OP71?uEuvu)U@*Y4PqwoYzIb`Qofyt;mT(Z~*pzPH&GFO3`vj@?EtJNBR#5 zt`r(9uXMBpBHoEHfmjQU1CX{LFkr!eyzBJcpp*e)7BwwcqzTPdSY!&6Ectr{u{koU zZA?1u(9}OFE8_ZcoFdh<zX0F})&?Fx-rRDfdOURO3zLAV7f{ugCJvy>7ja6Z;&Y!z zf|72r*jRp^{l30@U#JE%o#)pQFDSMfLK)a)7-xsjVE}B}%JDYl#i^Muv}N}YPC^@~ z^sq^4uct{U7p;F5=*d)4{+4Gay3;*Pt;RAGyPE`f*t~yCHk2s1XRfH);ZQ>zXz^AO zx3Enp3>{k37EaOZ|Ei-zLZj7z5K5~_C$fcKM#5ex!J|<%-x01QWO?-#S0bR64NR3k zzH%sg&cr}iNDgVBL~U51Ra7PEpib$tOzs=$in>e%-wI~OJ~B3o?#m2;ef|tfyr9dT zBT61=j1oeQL^FzC1REFtT=Gz;N3R)Q6c!dDLoD%4Hw7|(N|?;F>O*By8m*b+Gml}} zRy%@lpczurlVdck^I#>oSJ17T^--sMwxD#z@W4Tn<rT&f!NP<&krWGlIVrm`Q29He z%B@NEnDgi+Ukh4wzn{-oy(-cEMd^rknk3X>miuZr%D=qWhaMjR+_22F>=y#oMlr2> zo-SAM4<@yk9xsV;I|eJ$Vi1PyE~}GMBTCWvbH?5N31~MD*l1_1J#x>63%$hFw4#Z$ zZ%vRTl^V#;W13kl^I?x^xO4d(Rt-LW==+SeC*)?Gs5bS`8#d*45*N2}7Lcvi<L?!L zT;@a%#S$@WbM#&}ug6MM-CJ~l+3w=Ef?@P=RAtHd*#d1CJQOlhr{Kg!>kVc9+_%-z zU*<)z3)O_xMOYqxjRk-Z{g8r6A3jhq_GIZ*0W7xr7ha+U&-1^;3P|WjeFGgl4|9x( zsJYAM#+$pc8WD3SUao}(lRyPQpf&^g%+p`Iy>ra!MSbmb^i<RYg<I0TeqFAg3NBY; zA0&xA%-@{<nUi$=jE1)5r(m`31&FOK)u>kkQg#juG%=>H*ECEcjtKv*RN_y)W}QHn zozJ(V{gd|UfBXP(u};M@0L&LFykL}qvDoIHXoteJQK~MwsJHWrB;2vG$4(wT!nyLI z%mHu!Jnb#^yxX5BNF&Fe)We=`9V+O4bz8K}_2&y>-~urvpZRQrtwGKQcwOf+-=z>S zUTrPgJD{~I7#+X+jXn-1Jv@8ou~s0m)J%w!1+>5W3>~=D$WOT2`pz8k7E^;3;Y295 zOu?C(FN~MM-u0!YapeKkBQ@1LCo4D*>oKtBt8$c%!iJG^N()O+Kk@EkAD&lrK*VrH zY6~Me#vMA3bNvZJ=eKzzW7ZT%Vpyu$8@S~QJFb1EFKLLT<F`Nrdn4tE5^Wo((h8fA zAEW+7sZahu0MH8Pi{Py{aB+EG0jAv3XgwBe7wKS(+Rs&BMd|<ySOyUIjoAjUUNLft zV2i!r2nZXc?ipE&9r_jn9{w-s^Q)+68dgu{7wDtrPgfeB>T5TZ<siLCw`34BnSC?a zALKbOe&mAgMC@{{G$+;e`lU%`{Zb*n(I$`eHub<JV`qIM$j;a3R^n)&F*{dJ&%NEX z@-m>A0;CEn3oo?yiU3Is8Vusww*xDb`q_g;1xHw%PU#nylzema^C*Qk2;{6r#eT4{ zxMu~kv&)H<V{)LQJ$;_jAfbMo+#pRWWA_0u-?tS4_WvT45ug<Sj>7KGZ^f@%sRtwB zY*eDJ=7UmX69`(5X})7P?=!>eJC~Urj|HfN4$sbqSESf*tRt}i`)qsE2C$}DSFTn5 z`m$I|a=fubmvx8dHm&Vl?~=ssaS0g3)M%TZYXH<Jmc6h24^FU+zi>2o$mqB5+;R!- zLhs)ieaLB1<mf@Y4Utn30}<L!UU0`-Z2Ci8GG<Q=SD=d`QF0C4mxR9$RiFWx<<hIw zJLcKE$65+u{XqfsW|bLb9!?+UbO!Nz<fwpp7@I0W=2^N`v9@lk*w37-Da(F(8j)Nc z4pspTcPXYRNb0D8cIRZg{=cd}qD7X$G@?GBWWoK^9PrBE0P7wd6$M+1`tjD4K__aS zmIu(gy{9#77hiEY=2?VEF+vX%8-QI$T1d967rY4W{HAh;uv?#O;r^)NlP6ntecjB` ztD^{r-FmCCsmYP9AjgO-AQm-JW^J%!rhN+~rd)Izu2th{w;sFw)zxq$D{f1YPRKvP zo?r@Hs3O)R8k5(iTz#q23tzXmrNx@o7fIiApRh|4Ay!TTf`yBb69-6@Cb5e{7i-o@ zm^VP9QC3>iH1xMQ#Lyctz0JwUxYUk&*L7EgX$5&Y2AQr6R^+Sr)g)VHz~h`<Fb6C^ zhj2ivd$kd5@`oAlAN~VupaE75B@CE>+yy!h*#KK9Zr8;>-=2I2?wMQ#SLt15OQHf8 z5`3~T3bky!u|!7hA)Tua12SPDqjfcl#D5UBX(VkiYII+`-jiSe{meVz6m@kk+8<Qz zQxXl%Jndt46((ue+~JNl$_cCVR#KmDmq}BNn0G2G&f^Ss;`T(UBk*+zI~OF`CSdhN zg{L-J-J_9MnYJZ_eGt^_boTYrj(lYxM(0$YdBkOus*^Qbe(0Zk;Xl0MKmW#&0POjd zS98BbIQS(N0m+E%q4R1ks?JI4R?&gZhj3C~l4t$^`c5BAaC>1K=Nh64s~C)aA8k|S zi8ijy658!)Eie=Z>H6QBA$dDb|DgS_0n-@n!J$_R9T%ST+lH(xfS&sL%Jw-b!T`gz zErv|-N(QLi#UQsbL!XrPSx$T1_&<fg|6ZT<kMgKIf>tdv3qQ9L_6A({r|Z#WA5Mg~ z;JmX|_BWNl3bwDsZr3oDQIKo_!DNtXo{_P_<P7T1$i(zZ_TMf+=|xE|B^tU=*E7X; zx0lR&T^3W*))UXh(YNiaG>a794}bTXr2SxVn!#v+rhV{nmh(<Dr|&&$&h|o=sIA6o zu!(4U?0^2zejT_-vF7ns(>>ZrIW^2AQCZM@d;LIs>-oNcd)x!~=2v?^nrTIIiDgg% z_Sih4vJfW~x4*68nYq{ekT|wk`ZluodvvZ4^D{9u^`hkc%0jl_^zgYlC@ns9x<B7y z>ZML!tgF&Bdy-6lU3p=xczoaAu>hTb?BvlC)4|{2D4V%3*egN658mFEg|z27cbD6l z#tZ)+uKw=}P2*j0hjSppXoB6JH18R|m%AJFA^y<@^ZXMky!X;_>|wL)!u&)GlR>aV z!&=SYxw09vDqD6cARqePdtzYq@zS(dZ7tvWE|4}|mxw;tb7L#1$8()GEg;`n0RuD- z7vA5JKG^eKPv4=pqNr;ZB5@@zEC3NVu#@iTx{LS&FohqIkyy$W0i<%9G)$J6v7K4- zQQehTXH$uJB5%&r`#-MkU!KWc+YsXUeHaRU&i^FOr2~qGD>g1%;1PsYg$1%z(Ffu^ zw--zl7W(uS-d=cYz~HXQYGC4Pa^wp?*KEZppTol*iO#@Fs9yd^f6IKA;;}gSA%4r( zx>dEcba?uY#=t+EMbbCmW(9wkG#qAC0zOuA^^4iYoF03>`br?3Ku&+T4_YiE`Y|!u zv5;@xb7J5VsG*p#oGt9Sy?IO0!@RWXiM`&Hmd3Q`g2ZWfF|(29!D3C`oX84a_{A)J zOwmfAGiYg+J17@mv*N5QRj%|qg%lh1^o)qFQZ@BN^K`Mqc=$63i;v{xp0TgDi}u`D zavctKL$M}hEw}fCgi?R%r>$zO|7d{<OGyd%@JIj4k@)Z2MZim7W>I-2ZEsXSbhPWu zWusheG-UjQ7~^!TtS0qIp&LXu-+w1heAyTHZ1NP@lTwn#%T`zoSLMZ|Gxij|m^&b3 z4t8vgU7DeC<|Qh^#aZw^rTBviUw^19+9**i>W=4)pCMxFW9(T!l~k_9IjEay3>)^Q zap+a*U;UrW>+i3I?E?cN4;=;*I_&p6_M*A^*MGf?TJO%zj%d_lG9`N|L+wq=ve&qF zy+)pcBzS|JdmCSM&ks8goilvabvd>m|Ni`2@gyTld;J`T1`24iwuTas0;hs22-U#+ zIy{#K#;@ke8;qkZ7x5pnNGG73HDk}#t)nY82p&N3R=CtJQS0*eF#FHuJ7L+)k#DJ# zwAzIK6o>w^$Nf()Nb-QFf$KQA;UOzcsmpwli7=EPYjs4|3CCyeX;{Nynd6yuGg{|$ z|3L{j3GSx1l(!b=Wzh0gKsR04Rw&U>a3LV*h^wr(xvaH8P>Geuu%l5irC1lM4XrA$ z8Hmj`DR!t4F)DP4i4p(<kdsxvS-iH2yZYi^%;evBvNyEZH7?YITh?~9FTI)XGP&{{ zrN8p_FTK|VJPaXBS?~)|FTKvhKyUSrd;}nLbR0X!@PG80w8uID-XEfOUlCZ8^1G!g z4N+%ynhpNS5EG3Lz~x3w42}1NTm>$-;U(YW{Rc{w?@G8t{JVSnuYbEl8$|MQ$xjW) z<2){B^t7hr3zG`>Uok@Ke27wcsP^vT^wqzhy$5=wcR@BTc!K;*VTpztrYc7-{*}w8 z-8<`DuoV=F^w*yQ;cSnu9s*Z>NB4i<?f><X|KY_WAAoP-D<DbEi~-3KnDGaPga6K^ z|IOc$_(9D4_DemU&lG(38;YXZKit~?_}jm1VEtqN=Hvg}M<hvt2gR0tnIz}}zFXNi z#^vjOe`o)=M-aQw0UE;m^95ZsK|^rA9m@IV{?e8L@2mtz8TOh-zvmz=Eue~w?fXm5 za$mqpP-BTYPHuiU1<vu1UdF%ph4M0B6TA&J9XazDV5@|zRu|6v#nt(G5qwX~o!|R^ zW@&ojFJ9-LIXos+0pAqCbG+Ksf8{S;>F+@axo=(q3Du}}a@+Uc&DsCF>i^#AUBG1u zIpPENzoE_j(a$JU|Ig|7f9v+Z3j~_aK1K7{Ldj)`AOB;>(SLG||K{y~ME2bo4xT&$ z9(}%sb>d&!GyCZM!2d75e9{msi=vm@mGFOmKmYa9zJ-F@Dw$<sx%4NgY`y*09t7Qi zZLq1ILjS{^{I8})5!uc?_=BQGBL1q=_&vBO_JIw!&BNrKc$vTU+>c9u%N#=qNk-_? zc509`^)E#QU=uF`3mOx9-%igb+t3Y!@m?;;sr|*9l+-w|yGwOaQBf(3jARuu!52jd z!Wut(_@KC(?$+G~hWB)58@Q><oIg{qa}%78QSbc5`2X6v2kbWiVM@SIO}yD%+5?yW zpSROLULB*!fy%7X*Z-}CVqO1Vx59sC3^eJy@^k-hWBs#1{r|AB4wRn6Q>Fe_1Hqtr z&OCpReID!ot8r`g7m~qg#OJ=@_Vcejclkk@y~JTg<R1eyGojOS3#b07XTL@}LGJ!P z&;HNu{r`FP|1Q4!zvkKhFB#xr9_O|aCGp)}Y``tV#NaDWMbg{D&QtM^AD;ds>5U{y zd76)~Zh1BrL0U76KB&L3pv4Z#k@D-Pmg4aj;SNm_a((NWw;Xy4#9DvEV4`d-Nkv7j z_dSXui9QCdo2xsXra%M`35}QR=pP1BX4#fa(VI)Ypr}a`E$V-H_>{wsvD#=P5)Q=D zu;*oc`o0G27ruD$;xPOd`%?fXT8K7sWZwP-v{apoAJQs@Z|}(W<^ZW)NL;L_t=2av z#t_?hFZ?``;%HQ4V@?BsRW{}S%|DJF0Ax>T>T*r^Lc_(f0U#5me6^FN;roKoWb)je z69HPx#3mTo=QjHFggnoU13=or2JZ=t6K|Pn{%iru(#6(=avJ5DR%9cn>kNu#fMij{ zk2+48c+vnMG3zCH7|>$O*HN^1?0eyG2@UAXPX4OEb6j_XI4seZWtM$(dnuA7DtlP7 zn<>>}<5MkI>-gYYyYN-}M^}n-bdunpt4K8(Nipl~M_L3bVBDlF2Ntb=Mm+Q1*iXH) zFW?(%pZJ!r(aNuo=n5B=yU!=yxkh`BPex1U4c`tPD6|fDOK}BP+geFe%%mx6e%o;b zTBJ0wAS$3(SBs>_B~mJ>jsZ0QNC_76u)|7LZsmmrY?~R~0{Hk7XCR*0WYD~h{_x>3 zF<m|U>Db<8o4-SQlEUWLD&Q<7_-)NTi?R5d$E`kW3=|vJfm(`TFUBN=>3DtCmkl>J zfJX+g4K_tm<iK&~17Ovxflvi*cIaLSjVVO}RJbqrXj=^<P_%{5cBcIn-(}M?4!8+I zCyfiVxZ}0s7|#Z6ArX8{o+tS6U;DUw`u2~r9~5^t-<b0>X)|OPxUPVqcgc5-ryU0$ z!$z)y{=?`2@xhzl#KS_3>FUBibZlJ8`qhA-Hq(d!o<KB<#;$9+){r*R3lO80KKkRu zK#<Q6Tme!u+mTq4p=XBZR*n*6Tl)bT&arP9PRJ)cr~i0G-Sb{UE}-n8d3u*eYZf!p z6AFM3seZZ|^5>utV6<cdg<%F6j?;f4X&&0t(%b_e8h^CMlrgsipi$!sI>T$~kVR3* zOwx;Z<#CI;cZZMulAKNbxBztfLZ3Q=LbxmA+imLbo@eyM2CP5zLj~w{cYu{(YYE4y z&;(RZ4h5Xsr4!aTr+_IHD(*)!L-wmd?NJ8Z?>Y|_abD5;$*>yRZQl#;7K+NR>(*A; zedEFi4pjMbM_4a^n@mu1c~#0<?K6$^asX&@n)qQqjYk9VVk9)#ByKX4vbN&EByePn zkT&X_w$#Y$i($^YvL16f^S!x=wp%x`_L$N-Z%H=z#Rj$<)+TUue)RUe7_3srX{lpR zL@nP|r!TFE#J)AAkzWdjm?Z{BUh2^}H^BH7Xc+@lG3xgy)KLbS#^6j!xF@66IiHzi zl)#A!?W(1r3R33D+kV?mt@pRdZp5$6bX?540UPezC%%*O1MJ)ZfV??=Gbt1-t;~Vr z{10h~tCo{Xb}dc8uJ2(#4}I-r+S)vZoDu(f&VDfaIZ7Mo$|fpF6YMsO&8`x!&Y_;H zOtoA*ui~eG0s7zM-R%{1YtB(et=)OEy#gS31tH|><t8A&^mWZdhyo@fQy&OP{X9_u zjK-lWL(@Fw?d68FgECBk727|XXaWf%zZ)LUzupFOSh4E*{rq4LAJ>(y$~k!c>DNsp z3JV8VNX(?@b?A$3(Zw+(b`#bTLNbE{5IY53&^GND9`<Yh?v7T-BgbwPF0?5bIZSot z6x*z^WJPNZ%;^f-*W)s6g2e<9DO+-_tp##Gn76+P*Z-xPl;au2YHxU}+pt%q&@o5Q zP)lnG>M&4Ds@o|MUk<SnYclMOJ}d4tDNfzWy-Ho9K%=qn7%V2yk&7dpbR$QIF&eqO zVMTS+jo!HlX=;pAE5Luw^t7rM>?u|#HHL8PObRv)QHgeJ%0{^?QAo6O;!b`QN@Vb{ zfe|*`)$_rQJEQ={pmL4Vn<LJoY@^SAukX>VXgF3%1vfANEz2=)Dd_ofFV@4xaEJvH zbGm0<PP>OxuvXQ`Jk1U3Hdq?}KJV}|utnVMhj^B0evugZvz;tUrj79Y#BFxUEB`oL z|0-ctrFh_j7$n;uN5`I+6wfsvDcdHfFnSf>%PkXkD_bwO4L=U)UC7&lxos_Ft9{l@ zdzPo%LzT<HdKh_<xQ~dFritPQSSIscxi-zlu|PX>pcSssSPxu_8CLdNG7KpyWFj~n zv`l^%D(>sOyg@#OeiZsFDzwLG2%fl`KeQ|1`!VPHfH^15(rD5(E!(h`6@v13<>7=h z2ZiBatVlDSaIJ6bDLx00vYMBh?jo0+4<(WHBKxIGZVC(YZMa-Dt{_(?zPG#us?q&T z#riGE0$_ddT!TsRSf@|t*JVeSe5>Xb*As_(NM-;97MqPMM#LC&Gx?~a`o6=3;=+Un zeFcXl1dp&jl<y67LRm8ucYM)BdpK(HK8YiFS(0$X!i6S+_`uIK2p|EN=wciSU|AY< zrO^ppl?5=hWB#E6&3K_+O3@qbo`Ye@x@k9iQcTi}r#BZ@L&dF?mSw%%=b3u)443R4 zmlbaG=@AR!dxx59@wb<Xdzc#yjHacHZ$F+auP&#&?c&V_16mIj{SE=L?bVxxK4~YT z^Ms{R;=8vTzwpJVUt72wzxI}6!Z81FkjLymw?o@`8kld`FYeq;9~ia0iynaJv2c<r zT22k9<pWv6)7>uj0b;(TtL-+m`S#ALwh`Vv^VSFPTepaZLj|6o1h_u_{1te^ciqAI z+XB#FH3zbx1rrlbvJ47Qw@z*>6t)$kVQ!VZK5-~r4Tf7-8c)Ws$mYHMXNDuE`)CZv z#PsxZ5(q775^~q~K+}~JDWL5zRPNnVV5tHDivQUvF(SGIza5!S-CR>RH)8d@wgRos z7zPjJ5R2CslA4Y`g>}+FepNhlj)&go!Fc60vUVrclnwtAh^~!7<L<DyU_5A{jvF%R z4+=oz3>{*9hMHLEuLgMRTH4w<cY;|wdkm}%z}b`%Yp6NQOW2%>`|72S@airiY&jVk z&g>XLDcEP5u0m#&<;-WU^R(UR+1T0`@@?DP5lD|8dls`Uj@aw=a^%9H+h!nn>!2rf zKT9i38MBD~ISIHc@rm<g7+iH|*)nL|A{Ea2@2th#x_&nbE{g02DkBbnSm{-HpBjgr z22$mmt>I!j28#n&<lE0Q&Dla^fn}4lzi*L!Z|kNSvUiv+Xcp3=urFZ0`Ur@l3TPu1 z4m%4pMClQC=wO4=K(mO39b>tQBAlw;smQfYTf(sd^p$-EJsbWN5P`64t$14=i_Xrv zpr3LtRFx>_6DN3lo+ER-!=u<|ZLSq-v}X^(jBhMRDL2$?!aK&onOlnfw`R|O*Sya) zxsd+2cEk+|w;8PtYDF-?><AMdRN~?4AUgZexx<3E?7lSEzgaps<iCdi$LOv#4O9SB zYmKmW-SPGtKw!}}N=Q#+H6$mgev$nCb_`JNUs%QNX0@@dl`ic7s!+R>95TJy_vX=F zzwICQr-5KBhAM_{BjP>mr-veM7up>9RtV1Fr%PO6@I+988JPYSz?DrZYFgsL^;Ld4 ze{|~ChM&!jdl@y}N0(sNZ+sASygkqVT5+39)%iU|F3uQS6=L3?LQsI0V2Jk%UOOi) zyIgon`iWsU&`RHum?9N(RVBSE`)Y7sC%>v<zTe_hbYI+X4ogT^t_rMda#fm_09g%_ zyXw1fe%d;?OUSx6-na?FDLc%1X$5B`*17OKgu@Wom|Q<6ve7%1<4O6XB<@z*lSfro z7M~~GAYx=Qqtnt~y%NK4{J<e3uAHIY9K*bT&ybER&Kq#L!Bs|!jMQ^15Ym=YTgWhK z{;}x(UuJIS-)+W)jZP(Cb3oAQy3^|P;}L<;v-ULs{$rrMJxVt_TC?svgka9o+_mw> zKpYaj;_2nC-Dc?Nw=uWA(|nav^d}`^XK$mmC*XJk+2VBYxxI@!9DQ%#FGfFJ+Z}j> zE60BITxy)fIp^2~-CVEc16$*!j}c(kZEh<2&dD{=$Kg@;g{k%V-ENCpslh1HPY(#a z+}^VX^ATT3pkw3YSJ;@a_2lzn-`U+?Y;}0*0^a<Ejk=n#RZ6Ad=V|YG_F(Y`xKVbo z0w&w{cY;qyR9`!Cb-5#Vexdcok^S>Xq5#oRuF!F0m}$gBe9Xxx|Mst~Wy)R3B6X_^ z_i-TjRSr`bhW<6Xj07Yv4g(eHD~u6u^>Dm1Z19Al&cbNTJwMzYCU<Ey`~lYs%tP(d zLC2s^B84o~<A<+1l;H9xW%OS3LLd;UKIGtQ|1Jl=((zbo*zVY%L*`Da$j{<co(9q? z1q9*J%P9}oO5N`)0p)r3=ur3ZLjS#8RGfhwL+Sg^W<bSnM)ZQN1RD@jszS|jR~!o$ zO-sE;o}2a-BR_ZsIIoNEZnYjVNVRTDK<%Jqe>Plfy(8gI1th1%PL*pOe%a5v0q-Kw z{%nvk4PY}p<%ntPzG)ec5PCi3gfD$Ygi1`t(i6)Dfv|xS2-hW!Vcu>pJ=%W||NQ*G z%qY}PK?EvGN>}I3(#ibbracVDcjU%VX;K&<4f}FJ<BYy`sQpL)VYcuA%)x(a_R1C2 zq=S{Q1%sqjuJu}Wv!W{rPcJNZJwQ-&#EdC5n?Q)a@zpWzC5L;-0{-$%<jTsG`LawP zRQk$wGH|~OHlflVV}ujwb%_BL$^^u^0c7;$DMh~+uoC9i4N8Wyb~t-n!0ABjK|$jp z%w_}pagOBpL>i?Ll@tq^{Or#OzVVAJPzC3mJ_(frEbBv;!k#N?F=fvA`~b@`?L7vr z0ez}j^R+;(AYmwqZCA4d&9fm_J|E5n=>dd7@#*_axp+GMJvzGxz3Enys}Nrt8R*!0 z0?jIh)0$6}VdvRgnR`VD+pg9F5B!O;OeTq9hpy$K<n2;VQT~nv_^=!OlSQ6rT?-ar z!PpIC4R*QZKi|qqI()iy<{mVWjp_NUlaMgZ{LU|H9EdA{CSPl041;ZutfLn<li_?x zwfAiN>SsV`YwH6Eisk5n4ssC$@NGnBV(#3<Jy}#>{KcjVdAXpBwrFo&%-suO<8}3o z4C$`Twq{Sk-HF~gt7vR5#=-70TOeDkZuYS4^wC7idE7#ylLwGNEAG$}$4+5iBy$3M zpsAICQKk9)Z_BMGLYqkH{!VX82v-h@7p2H{mz9sEDNibsqLF1QNBeAQ(28pVNhs9# zkK$Yu++ESik^gF^0{`lIE4Jm1pcrU8!{?$4GecG|H<RaJr<`mpL27b%L7B~IOYT-v zbao4be@x_==d^0s_`639cjYz=b#nFVHXTdsEQWT5Q+?2(WywL>JGTBHH&HG9RV#&R zw06wW=Bw3Gxk4Jw!u6k5ugi7yvGtvfouW(ml5J$HfSJGF5`N~Ld)q_0?^pIZ+HZCS zQZjo9hPL7AM_+wsZM4@CZV_MX<2resC_d0FWSz2m4KK*GS*c*aBNzY_K46%+oo~$% z8y`&*#RMbs3B3+SN~bc+5=)cbYX@lL@Xw#t1G1$vm~)$6eaCay?<*AfwxX?Nk1>a> z3p7$i1fQN(1Pv=zec#EoV((5|t?Sb46)sy?!nFa`&{3AVDWVm0U%=M{g_`=z@>$<v zlA0MF9RS&I{A@#)&W$;6CckUs(TcDKDM~9p6&mMSdB^@+rJ|9~r&LZSeDbU~OiF`K z7&n{T4m1SL{=x~qv|UA?Kicx?#>M4FSEWiLL(gr#bt~+F*PfWbuk{$g0r6ZaPF1;} zE|fz`Lf*P1c2bAUEzU7vt}crtYKS%4+YR7M_R&v&%Yar*@*`&G;!HfcVV-~ve0Q>0 z@z5o-JRp!r6rm6D`<z(;Ih%CvS#owREGt?&>aN6!*d){6#CM$O!4Qr-PREiC?>@|< zJjMN6VQ5N`Pe#tcDTvo%0Y`Th<OM5G%cK=xh@M?Ot23iAeQga5&gVa6T?nZ>f*yEV zZHzwm1*I%_-(Gn{*7pJ<lh4M|q7Jrmzg1A;;FRje+fQB>Rw}}L4&_Ef1?n?t+ETZ6 zbAn0IS8y~5YJODJ8MI&)g#^f%u@=bztOf1E`_OY){zCf6%KVN%fx$h@XQ;Ep#lre5 z7@$XhVb^I?D&3BaXI$w7t+TmWz>&$*qcN$1!)TExy>1f|BahI5e2ZXhTV-?PwxK2f z>8A_cp1q~`qF(g%RbyX3)<P;6qn9$M4Cu-X6anT=QJO|k8S!Q*Ohf4QUmynQ_1oRF zww7X+ciV5Vw7!2s=);GFJQl8ax85}~l9oQu{pfOkw&mLhAL8i+LF(y@#*F!AHLsZC zsq%P7Zm&U?R`1N%6vmxdCjr=#F6+-rB>s`K70nET4cjkp;2t(SlIUEv-gQ{V3TopM zRkmb0taItD(7Tv6S-@ygu!g;Hr%cbR7$}JLXI)#BnixvK1HtI{HVY2=AN-(ne%?38 zVt~ehTtBu3cM>Uj=zrk;p-hhMuS?z84_gYvy_c-08*TRRrN;P7lP(=48-2n^7oSAA zxEz?58ZAc5_Q%=veDOrL80C}eo)HH8OpeE+F>rGH$Qy`72$;%);J@T-8iVdh*2K3M zRgz6NebP?3E*DQ|J@l;7?9PT(xEtZE;wn~wQz_vqY0f_gE4m`muzAtAh11m4zo)|T z71Hl1svBcG;Fn0KP1vKnjgTL(<wEyWSRYiea2moy)MZB~L+WuDn{@XK2Qg6kkYjhm zo-o54-P~ayqx;t?0{P^Do+?*Ul}Bf`SAD#|QU5qX|2_XQ!AlwLn=WFDji>Anv`!|t zgv9%~7=?>REfm!V8r}1;rEa$|ua8c6@G5+W5rIFxFUqVIdbU-Oq_Ldi?)m{CV`=gr z(N69ncqv#y*a_WJXrWh(xM}$!^w$ObmeJKaS$&&iHxx0`khk`;IEJ6Cbek=cG0{Lm z<Fms`F<FhFbWfEztf6cza=>$FXwE{(04Et}eCkSWA!O*Vu7h-ju2k9bCp(aY8Bo1j zFUKv<OULEQ=(j8uSlIU^ov)g`$0!3-ESI$VtOq@Wvmb`W&r)>ZeYWfslD(&M59_LH z>*obsIalhBIrpY42KXE(yH9u43caK(Nw4@|YbM2*!m8Z0w*3Csi(~N>y_vv$o&)}` z65{nM`|Fx%Z(m3m%nKFT<?A=*G{5*UbACT>u50FZ@!4YCfa8xfhrHfU?Z%oxnN%*o z@_vFtS@g@?ud&1U-QgIFcDEgZ>Y||6<h2=ipwzua{i0I0sOt~F0X|fQ2rbu{+=t!1 zhxd^<F3>QEkWB4JioMWb<Y%UEBy`L@&avDUeHshATmNBb=Ipt_IfE^n^6>nIW7<oA zB_GOsHd6eBvDEL^=s_a0qS*h(-g`zh-DYjyN)Z78F9lJNVnskerGs<<1w#+L3DQDS zdPhJ+K@gQ9T|oi_LWj^o5s@aH5JCvOLqLUu4)2+3X5M>d-Pf#V)_OiYYt08)afKBA z$+^#c?tSdvL8#V`prIWYyP*ZO>1z=Pnhd`8EX$(>O3VmYqu007#!%NR-^fl;&4g_t zO$8sYoFv8lI0$Os>;<X7CrW6Oz0|LK26Da3uG<7Z!x=GCd;Plcgj`S>9qT)|+(QLB z%?qH=`M~$M?7sZ`N1HUdMFxgN5tXT{ZiC_0vgf@U!-2tIO03QlZ;*W8{8DcEdcin6 zKTHgr1m89&F*<$=wIq|(zz&1)2HBHQpxBLjcd@#}{;l4#Szr|Ad9L3xis6Cd<O?$L zXV_L<PS}ZylAri`*y43xHKjA(DF)if;exW56IzRVh%l2wo(it{E~QZMi0>6avI>SE zrfs^_@ZX0=9*)BsWjD=@AuL-^uSm-H9jodj;7>E^PwDnOIG*{p=ye!(S$P$S8h0-$ zV6ccNpjp-2$y++fmZ7UhQav!!qh6Nuly8w?$_g%aD&`o)Ox#}+4ZWD>zWA9lt<gvS z^{-BW;vZg!wF%YQHCU(WmPa$d82BRtI4?d0?poTsJcU+8DO8YA@Z$#q-al38+U^_e zJ}kiUz4z0JHN|7>li~jQbAkl50s9hEerK(m8W{QApsT6hg3Zokb{b{oUUbe4)-Q1x z`0^I{@WYKA^qXy2sy#|qIhfZz@)yu{J56kTkKaipeqC6g@zyVQk3#!F%j2R<%M)EI z%Oe-=RqG5^m{>A9x^#3roM+(@%}az8v%st`%!Oehs)#?T6on65KCqu?F;nhE*xPgI zwBjtl(2Gm%aH+@JAM~_fIN;81vP5-uNXX%WYTXpc>bVl8M6SBV){5g#*Ix$z1a(b@ zTiG7Oqt#UfvD>s4<f`*?Fa#OS*`IHda0L`UWSOP7H0@Ll^}&~kh4{w@nJJtnUpR8C zTVTg7LVI_paon>oBU#LM3;Y;;aSgGQUV|9pW=MM&6u6>J9%)LGsy+ysXGwLu5R#Xz zQO-afyWY&f70d{+&*wWFgEN>PMD|uWc7;J1T;-9m>4Rb;yfz_5HY{%}FBvU-UBeJ- zGb)uVDpcs*4`ynl#Bpbj1(LI@=B^O$C(N!5Z+ZtXdRMx}xnk4e&%WgEtW^R0v!}kh zHX_bMcp8J3zgE46i-?Bc*|emfm00JMJI*FNzIj_iU+^qt?tC5aEsdnlAt(475(Gau zXO8uE^81hLS!zu<xCL_t2Bl&6M4qU3#%WG+w+ey9O&a?$M}E&c>D%9rA&!0sUyoj0 zmG#~;Wpp{1Ps2v;8V=elU(}8FioV)D7ebuC=VqjP`}TN^x@5~)I%@gDxzI&wf^|>V zhq6`tCfEXaOBHEOOIp#K6O;OSOJ<!fk<l}&<Dr4unij3e^^^$4GoWH55Hqi@7jbMo z{>^xhqse)~i0)v_eJJWR9Ha=K4DS)j@s`1%217qaTpOzy1bZvTa~Oi_Q&T(_m!sc- z1w=xOZTPpi>`jke4G9f4ZH>`A+M1hy#(kTJDKNBRxBwLybkGkOWHRzGp^KsM%5CXy zk%Dw&!y_FT0{v1|&(<aMZhFLQ>bJ*$ML0zZaPa8>+#Ra3LaDT<R&WDT0ZkPlD09E^ zX-Mm5_>$cbuwhV${j)!%pwNW;n8odY$ghV->$Vz1#0~+FPEe%&E6c$rq!ny0EB{F> z>ms%#KrAT9OCZ@7RlwJT))R&qLnMlpGW4bHV+zL<${MH(29i#&<=s`UK2C*5%UT~u zQTic+G_(Nxx~+ip$R1v^RLN)7lWvUb_60x&%k!~;V^7&^jV$V`6n?W}43u?RSflHC zLF=Q5>Z)371)$N+)1>M@Tgp6oQ^fE8jHX63AzKLoV<_CEu4kb0f&TRF<>LK`0ktQ4 zV_I(tNRM}$)WMr+M5z5-j;}tsc0ju>OBbXnNlgIxPf}(G^MzXrMO)xBB$?1LB-;I{ zE(pAjOy29)@sZq`C5eLJy&{B-r>8!=U&XsMJVS8orLN5^HpHJgT0c4zM#u?tJ`?yc zhBWobwTAO&72Nf&o@Y7<W+)l7S42$0SLzcFUGhwl){btDA&+V?#B6EBb4ph7V6JFX zt8ev&9Oaa>7yQdmyJl*3RQ%^6tj4>LZXXEC1df^eDM1PhO5f~Y8)r79y}gsHM%oB{ zNg*yJE2_OL&RA0nz$5C?X1T4)jSO_nzexnviZKigzIa1r)5sU5`Z@V4ee%@NHx<No znw6=J$dO4F978`w#cw99n6Z^@Z*N&elr`HARm!D{q|fz)z!DE?t{FXCB5;Hyyszi* z-*3qw?@Ba(>NZEONVB1afEYH_f4FR;&X7eaHgmzXOv5sTW7~LdcWxC^;66asf|$5o zl~sIKij@H6pKv{Bt$<&F^pgGh#Mr<^{qE!&18%?OG2KWnLZ3_h&klxwsq(o{o9gY4 z7rja2pW=hh1MC~ytNnx_{+uLcnu#^8@{#XHwKq!Ms_lxMq<Qb^7Ze)w+rDHv@vA0v zodGJF8DZ7!loRn{VL#mnEZd8-yN~S>Ma0ta`^P1>77n+12%u<nfwMqz(2Of!!m`TM ztxv5>;FNd24rcY|{2WqqF5axzIJhK)79c<MpRF`+CA~0<?73GMl|EGUzB1oZ=vv=` z{PLfvND*UZvWwoixfc?E3AdnZvf!VI#Mk3BFN$|pt^Y{ISD2_?*xT$$g9(D*K%C%u z;s!d0?`fDTc#^)}XOPX$7p)Ido=Oq9-ZkE*gRgQS0-|O#0uNr;v!#zCQM*Z9;*wa7 zdNAhcSiVh~Q%EID^CV<&&{x2J&g(gdo_r2Dh~u!@$N6-&Qz?kBeAdPkRj0$v!J{;r zK~Dx(uiG*1m~K7U!oi9+pagQW`p;zI$#A$0;Uo5>yTr)Snhr}T+u8s`OZL%l%f?fd z>kPp!3IWgcB+pZxlX+RMx!?j;#p@-0L53IwYT9c3nihameVL?>CIQQU?hh)L?;KTV zrF>O~7K=7rHj7|GWkn-msuk}NKbfLjdln{QB*xEwydp3bOIRwbpV-&{*x<`GN{>^h zbSEONLf>MxJRnnfjy-BI7w1+-ou-OkP0NeB<taRtc4Hf(p7LsyqG&SD_Ic@r_j_t7 zL9p6PDeeW#^QeVsFkH-yu*>0(I8>hkbwK-(lE*y<$7qws8g*Q2=FTltw?O(=WL;6x ziEDy+y800eY-zXOBf_0b`S@xw@i&bM`Ayg2qiTB)?pY~YDXE5^Iyf{zr!d{7FhEkp zMMcUrf&`3zLSIdZab})P!<*)J?d{B<CvtjsA0$+b@jEf#96MExCK6P<tb%Bw_(6Lw zFRaiq>(6z&Ru?=JxM#ilvMKhv`NUYtOM2QluWQ))yS)t=m3MxwgiMTF(e~@Ci<N(Z z0i7nahjLFm?;)_;?Bo;wRb_CwPXGL3US0TQWJOsAxdrXw&S|iR4`F%qFi&B`t!4B? z;;)xUx}Dc>T3d9=7UN7i%7CNDN9!y-AtrVkX=JxEK*q%lKXz<Lsp>BZ5;Wp0w8SF3 zyBxjJY!4KRcu$Cy*|7AS#P!rC;8%aN*`Ej=uAr1LN+UMboh;MsExS*qIGLzI)izMJ z9NsS<6>sm$UzE}NLK#Xt)J{vhur+hB?r5Sp%5=fI2!=|3=fMo?r>XfJK&!^!-tn^* zyAbi{&XQ|!AdFAui-pw6Kw-U?n_kB<5&3ccumMyj#M(*U4F!m$ue+#n$4g+wT@M&v zo*`H|k0iP<8qnt6I%vBiM#a{;e_6OVJ4}R97A+FwAL&PmC?O{17P{A?)j;(@BVoEH z2$tybljheL8nJ9qVB+ZQJIFAMgsK+tIO+@w!s0ZrC?VzC(P5(0apX|^6Q>3rX|2Z5 z)dW0M*OHI?_{4YmJhr(Y!+WwV2B#G!6<8(v0Gi~cmXH6rh-%h(2CV47Paqla4$gsz z*Xo>u09f8=Lr|Sa!sL465m#CMn>VKhnVLb*LWU)1Q=#Li<cD90CkEQn4n;YBb11ii zq|dQs4b-MEH%&yHnboaUme?QiEZ4j0zX79I$Ed;(LHobjG_TXpHjCPZ$;`!q`t4O| zd%~?mx0aX9OC#CO>@LupfdbbeLs2;jFPOAGF=4Eam7%TsyMO3|ru1Q%6u$4m)ss}b zle0m`)<Yz@T>S+NO;%v)N+FdjKBG6GYCE7JLdBVVoW{J?(+kmEJt0NXfTWJh$0?_+ zcY)=knLa72A5z?tCN-F!k@Y+rj??WDXwO-1^!Ft)+0T*q`>hzE1WW^=`6^|Sb(0^E zKfvlv*HhFZjt8tW1!`^}D5B6S^ouD4>dzV0^3s9&Leq+Wpc31No@Q{*=g&f1g~5~{ zmIVyqt{%!3wGB?Aa;T+@(4tlb)+ISb3rGSh)La9y<t2Jh)aaPJG?**%dDOVvPO9zG za-1u8H*8D0fm0Fe($F&mc$7sgUG_>P6{=MSTF=u))QmQ&gh3bfuZR(Z2RvIql>+$7 zE$ZXn+(^q=-t>3LU-A$fuoqa@rTK>vPs9~S7KnRAlEnTCz;&Tyz@S<|>r3|HP9Hew z3oV4c-gqos;g!++UQ;>j@=e-{tX~G+2!OGF_{B?&5*4$qJ{x4hFsaB2RN1T>ss*;# zb6VE6Tl8tw1$E;D%#3~zuv#ACINPgXn36F^Ca(->OH^fHvYne{=2_r%-+0cg@=%K| zH+yxgB1|^Kv1jNdKySATq>O%!8BiAgymTSJj|_l#JKfnq3HP3Q2d!W}mz9IzFW`EQ zl9)>J5`VJ#wP}9KCr(4=us5DW-u{+T<*wYLFE^DEd$dVT_6}GdHK_7@y8HEOk?9am zl6=}Zmm}X?)R4%4{bBjo_`WNYNAkR@3_}Hzbi+%M48IQ>+F`59ot7QUNe>L$-NIRK zHP%Uf@wco-UmCtmSd&FHEcwq?{q5O~b`4G^yhfqQMibn7K7+<V*y>vV?Byw?8Mg34 zyJWC7Fz6{>AJCE>K-}XtH$Dn;uH(@YfJw9Zc-B*$@>e)h<fqZMVwVlS98F1h9fJsI zgY6wGavvw-n^~}6d=>^29|1*t&YQ<H*ow{xGoLs>udJx%BhEUA7O28&kvA2K*e!gU zlh;Z=K_vD(uNpyE8a%Ug^cH3@tn&li%@3|BGWwso^|mSWrgoa5P>iPhEcmL^O&}6; zSD629l}(>F+75>HA%jNw?;n1F_rASj^Zf-)4HZU-p(#Id%k}yNB%JSLWr)~%MYLP} zua_Q=4)Z%n=^_K4!t0q;SoWc<*TK10P5`=O*Yy0jH}KC?yO#|_S_43M<Y*sN1irz^ zi0=Tvinx(YRDm(v$UAc(vzylUSIJE(dj3!RbtzYdkvv7A=Cy58nFF^kW`Jd~<i-d| z&O7qYE%qu1DhS&GIj)PC)9|TFi2>;`^O68m+ggOUjo{1s(t85ZwZi1G<O3GcUgQ4n z=yGQZKz_v99}vDA<Y#>hYdeHDmGT=S5Qd5-kKdXm5TN}(j-<}JP5`Y{p(DQvz+qu- z$?vU-I1Lvj1NV2n>B~;FmXN&y)tvUQO`)zeVTu$+Bjw;*4n^EFAsED!>F8l_qJS#M zy-m>oZJnIwGq&D=6L&H0(KmznAv4p_ZPH^qYM*L#6Mjn#dgr%Z0WH_lkJ>gsvz{E1 z9meP9bMZk46bK%=M(HFXdyI+F`@35=>b6_0&KIhss*`{2Fr`@nFSRMSF9k}S>I2hl zzPFQeZ?DKF7ZKWN2|`Z@gSrp(uhX*wr8hrr9TeW$n^?WI=e1^+TI23C!f&2iQQ*9l z$u14id^}8|t0|HzO*9WQTO3M~F0xr;N<Y*twnrBo48pkd3(}x`nRQo^8nc-l<6M){ zwXe>$aa66At=m1pv6PGBdN(9+?ph85b(4MN%eZ8<*`nuvkT^hJ{#u-6To+-4n-Mkg z7N}lwrHsjK?**%D>`S6v*S&#v2kxcVB_^IZb$Qu`)*K7$7rdq-y4=5Jk9)6hFs{n$ zh3h5C4L5$~40)h}ul7pvs@p4W%3`3eDo6@g#y!<WWf-?D+s;42n+$C^hf0S<fMs== zrV1_g-GE^HlSfN3?H>&}Zxkq6iFOV!*{UEa=8$91xX7D89X0j=`@k5YmmMWZK^X8G z`lY(MHthdCnQM}O%HKZ(9)+{|vLEmHm5JDfa+Udk&UQV8t$EU@G7F%U`d(FK>%dcX zZ=}E@U2FLkUHl)w|46G1MR*wGb>l^CzX1QuHiuz{*mt(4Z@#8#y)Zklv+_86JT*lL z%5vi$d(tGuTpkpWi~$Fi_&Jg*>eaNS>>{##PBSEjjdD2ZP5v&?2uBDaELN&kSDhCm zH~Y*cx+^)wn7;S<I51KD)HE%c!Tg3HRA-KaQm}_mokFu3cRx@Yx7c0d>Yilw>3d*e zlA`xZqZ>Hxu3xT(Bb;%F1U=|#ic`@Y+yH3xg+8S!x9=4<Z}g1O_w{Ugz5z)nst>Pa zxMFCgC`9z2SavM!>6far)eemX+?iTysn%PCU9_Nmo8`!x_B71#bed16uhgaB?Z=vx zg%mj@kOHJNTO*>1@)t0_K_UO%DpS&&*Qs6n!z~+6OXWcs*paJV!X1*LDDq|-XVI>W z#h$0KJNVARxw+(n>pdEz*B?Oig!#X~;a;N^9kLpFq6=MjPp<xB@+<KqWx+M1x`sG? z4%*+VZHl#MD16O1{3Wo6Geq1g{Gdki{Kzul&R}wnYdb#L`Kw!VB+pf0H&~=NGg2rg zM$n|LMKeg!s2gE3^P4<92T42lcBMV%AlPH8+2HbzcptZrx>2r_l518^|5i@+pc0pT z2|=-~c<{$j>LivE1nDmf@pS`q^2L>P-vt?hUrT?6oBId$hyzv3@6<*g8%8HH*&~iK z<C=mG0Zu>qS@u_mhy*TmqVQC{uYRrm`@!5pg*QG24#S*4ffX=4lM{+L;ay-Sv5DYx zKhN-rQ%>^yqak4e50)Zx`n-N(FZkyLFQnGO4{JXWfypgWCdX<*u>o$m&?@0Bq*Bsd zd(aw3$I)R45}+g>4bY$|wVZb?`z2q@M6c_Z%r5Nc%$Z6nkhJ}lC&epQXw;fIBbn2v z(u*h>urWHuMlI|Y9D8s##KTGooZGq6wkInTNHT6C;vw(aHSTXT2rSDPaUZ8)HVa*a zq`DYmGZN8vwq+}B+oz`K^uU57`rmgg9A=n&B>G|b9>lGHJqeIo3>pIc1{)6s&%^L* z)EoyP32AS|n^;}qx<Y#VCBNh!r!;`=Me|c!zaYw>U#gt2LJKFRMSAbqT;y94k5R>R zYg7UcL)@DSB56m(XLc9TJT!|S{@hiVJe`&Xiiz`u^~Ej+)qrzfgvD}VVmB<0{PD>b z)riXl#o~ncFF?-d8|n~d=AW0nRS)m%i#K|g!j)Lf^2gZHlhVJ*Iu$Syo3h$a=s3Wn zzv4j$Y<Y9N2UUlQ&YvbfjDoJy@;z<gM|!qKz?(3hkfN$XeO%gmwPGt^c?<5CGX{_1 z^KU9tWM<H>VIgJ{+$`8?^j~XC#E@>AO(b6xqwNwkQifKJEsdcSi|QMq>+qfe!;1h4 zQ>bu}va$YTd<29p`Ddzw5Bvv3LoOE1Yj&9!A*WBd)2{VjyN<(J2F*QcThPQ61h4~w zGw^*bJzFxs^I@tbl6{etbr}<M_JFtnbO5we=<yhb-R6B@RB<~g*|^01fsFU+(<0Jt zp$Pyumv=c(KL$s%3l#i$&!jBmVKSCAB_(PEEj$a#y$v7aY(&imGxc&)zP9;Qf|u#f zKUECx^(UwSnx+=$Bu(c_NG2WtO{UYthrI%pbj+Q>mzzZ#Wiu`^<;2;?gDyai*3&B{ zIGv<yV(Jg$;~;@=^uSsFrNKLcC-#Q1(!xhRIkFo|Wli3DUPu@!&7f_^2e@kZWawab zU(%193bd;_D80E|@^qwzX?2z?<>6>~(0OmqZuonX-@QN!>Xm*W$=<5H=q}3?r=!%= zjnj{auaC!2VM_j7YztmodhD*H9UkGKF>>hzl0on);V`ox8Qalx`<D&g!>*&Y(#&ov zL-m0?`}3JEf4&Q5TK!g)@Cehp=FfZnB@D|$5R$y%x!Xj*1r#o{h)^|46K(b(f`a9N zOG?Ff(5=}pydqO(OdBx&zK=r=!R)=$)uY<@`yX0>kjS(ofF#{v_7y*$_shU$qo@Sd zqM0fwWprVwJ)Ga@!^M1Y+e5nmViz=2WzQ2~ZEkA!V%6yoLG=D^BgJwbgD|*hbHo{_ z-F|o9W`Z8f1<Q&CzeXBmo-NbRfK<`-G9l08X6{i}_>hX67~0O+nuoA8ZdT}$cP7J? z!r+Knuj%kXW%$bGiJE;Z%E!%Ns{Y0Sk)ll>sFVsF-mG}CGRRl{VBHwKPT6%7u7$c} zPn1EGqs6aVR|XWJhC-#T@<i9MU2D&IcYrXewCldOa9dP;6R3qxN?oIUqu<)ObL*jo z2ft<hr4Uh&v}@=gt3!Y|BT0toxli3ViSTZp;mP9hL=S?NmJi%+QzAV{wMfV$e&c`$ zCIG||x(w@p{(+bZ3V(-<sw5}R#>S=ZX|8?wexShjap`kf3jC#x3UV3aVW<w>estBD zbPTDVud9inIXD6j!tE3XJOYZZ&Pq23?UH8p*?e^q(ZgHeO`$@kA#qN?%UAQJE`&v} zo}~sYmjcHicNdCb?w@4bga1@2zoQ-N)ZMknwbHF#e>xf#rUtUQw6mSStW7k>0AEE+ z%l`)L*GNEr6${eRKc@J3Iy+XH-|(0*%Ywd_3IwXCe{et3*e}SQ;=rCBIl2Sw9oRJW z=RqEO!R1;o$2L14YK!nLSpS+bt+VpNi6PnXXC(Zw{;@8<2WtiGIgQGj#u<hinogQ? zXUB7Zida(tS}SIx5iX(sPJK&MG{;)U^cmQ!Z>207=#7ti4nlgo>eb$I!8@Z7d3h`O zC`X0YN=CH}uug>_@(ZWN!`%WsHhw<74#1k5c2>iui`Z*^V`v%QyX6O+?F0wW8C{IX zP8#s6ef(A<=o9}FSc(M}oynT773DrQ-niwNxiqAw#Z)KYrs5Ci`FnosjzKOJTA6Y^ z#~!Q)Wo0!C8*ztDQxFwtDb5AoC>7Q%^D6fi&6R_1kMI>PsPb|^DNyU}N``5;fTkz8 zlU=}NHc5b*Zm`mkHh?^kX4M78<h|$5ia5_Crjf)T6D8#<kuOq%)6#9RF&W$^S#F*b zpC6qcc5q|MHv%=om=#=zXqECZT`o(&;RiPIw0#%#LW=R{H$k3G8XAHhM2NVz<z=f; zhGECK4i0lPI3izgTI@LI$R0erT`>#_A^{7#^PvhVpqbC0mj27P&us91!_$X0PC7Cl z%`zK&3(OBY#}pbVM>C6tyGEt?peH*MY-Y1{6!5G`T@NDXp>uUG1PaodvWCoL+i=yF zCo;g^;#83GP6VR~O6&(~6>9b)UorUfx!HSbwetowfj#~(yw4oXskzVa!+rn7W`^JF zj^-iUE3&@^u0vLTq7#-4iY6SfjpDtBCKsh+;y`#PSAxp!dMVz%zcndELN0txpl&PL z>h{W>#|@#OYoalPHdLj1kK+16sH(fEJ$gdO^$BQrg=Tgem9_Q+@t;2@L;e&+{zl8R zbwC>~D@pY(%xnvd8W}&Z>}l}>mO>20++q_zv3M(BA82*bx7>7wp_5gEllhlrJri=z zd>R+tdTV+{S5b!%Y;d&(mQ(aM5d(M|Y7S|=mk7tGv9~vhQI~DP2i?q{nLz-?tMzME zy}h3!Md-Ri?_6#B%H@&_Ut{anL%HnrhX%ji?J-okiV9GI29XfFM-;dFao&Eg_LtP- zuP+p|H6&ELvej9h59xQ$1L@h@`P*r>lrn90Khoioqopb+V2(ZC6klf&Ls2Cv*^ieb z$D)CBwkEcNa|&U3Gu{i7dStqMw*mkQ9>2HV$X&Kp>$Q?*E0$u|9TKi7vA@};4q<5( z9UZc4eKbf{jmK1tX@A_G@99onGwX6d91p2m$Ov%WT<q_8D_pyn)x^}7*Kd3}l;+H< z8|`yUR<PQHy0uz?!Z>)IuGd-FWBrx6fM`a4tt0=>`QZC!j7qFRIYaj8HBYY;miI8| z&-^UPKAqSwQIh~%S%d@^f)|D>aJy;!n-PceNQQ#-4#cr}H`i8SrU!k>fe^<8Y`A?8 zH|CC`Ka&2eT!}#nybtT?>i@jR@f3QHeI5jj-wc-**J+TsbTd<<oIYdkL?VoI-=jhD zyA*&*L0w5YM6RRP6zJEzH`C2nX2evUfO>a2UmIok;<=>)6dB3Pxf~d2*k=&Z$gU=^ z#*@V1Iv~qVD9~==D{kCkV;J@_U~BVo1^(baywrEotFrrEqD-Fbk%=w<bm<ptkPl0g zQxm<OH466o$E1~oQ~L&a8knXbkgnHI_j-n?X8IfkNSYX4p7H3F#o~H^y)*>+cEbte z5yp!R(I<XaI`n_tS^cGz&!<PgyVKpFm?~Rl+WQ}JFNv5e6e#+`PVILTtL+38g6dJL zdd9(b%1HacAk*Jkn=B{XE3oIp1`0LpqJku3x+o0**nPpANAJ=8Dk4ti66Y`OZfQ9Y zxq9{8O^P0p^qnjOy62H2b|QwZmFV&WN&I=wKuF!{i%Ir+5Jfz1F=TM+i(r=Z`J5Vs z$E~}tbNb28@ZD&b>5=Q_gij}qz)3;!x+G@~l?EMFv;1O$F0dq!H@5{*Ls~rKmHOjs zX3`+ie~vYmYB)<wieht~>nae-gYET@z~u<f-8;V_o;=={4Nspy`-8Qo6<9H(8p2ul z2r5xtNLopAWI`l(QN36{tp5JX8~+O_fU}|Ya6M$VB_L(osjOE}vozm^X7OKOhy+c| zvYG-^GQ4&}g3=@FHEzJroAC9`i=%TdVjorJI91`fHBc|=d4*)aDATfzNQv{&RJl@^ zHN$jzun}8<?&peb(;5Or?{b?q!=Uz{LfTssYbCX1M%Ts?1qIdKl>$c&;wW~WmYf?m zE|p$jlIrhR<%GiJh7__So9HP1=sm$bOGAn(EAn0}&dbTfAmXhtT}f3qAizs>X?Cg! zcn%I@!QS{(MwbEZ=9SdgMsu{grdT8Q(fAV%vVq-D83UJQbxi_Pz4t<ne*BhssrP9P zFv&)3@agvBq9D%cGv10I97{RG*PHG(fa5K^e~(|IxIaCGK^2VtwfH?B0F!!od!itj zxC(&Tn*&W%`d$hW0&Jb`xetcAArjhi=>GXwJ51-rR)1ibA(PN5Y7LcGXI&d;;T21d z<Z`dMzK+foBLxt(R#xi0MD(ujBndHTIuThwWk`v(Z1bl&5(xf#Hs64P%`?@J<@r+b z=fpI#&O=f$ifT~WVfQ=)k`Jc?vKI2QVJt)&Dj3%RMi8g(UDM}~a)0tkNqcDV)++@n z`uk^R&qTs+LLWdOERQyS;?Xt5PH)CjU9aDRi$XrJpU$NaTv!#FWVRJ2RNU%_RSH%L z6S+{uR;Fi;<%fWNs?$0GhJs}D1Q1k(RO%N`e}WaI1gldsZ^jw3?D9fVSjoq0_HeoD zXz+f^D=PFCLIYs1HHLYHB)(HQ>(#qLg`L)jPg%>gyA8<ocEmCG5iE#U4o*g~>VNJ| zhkNTN%8;9}=E4^us8D%u>r6O8E4vQHFcWNm#Ac*03ObzIN-G6fv0q)J?VytwdlaHG zFQ4k;iQqnp)VJ|@(K9fu5R&brtse}*N)zzy#cZHpns7mk2Qo;29Wj_LHH3z#O{JI~ zXm2qU)&FM5{aU@Z6^(!k&=l~oVmw)tvD%e~2YWKm22WYc0Zn=&-qTGD4^8kw<zLBG z(x<dMJYBFPV@R_dl(X1CaJya?8cPa*B6Xo8K0UbP)|20q*y4iccrk2WKxJ5qz3KzC z9bQP3vxKG_v$fW5B~>(>SgB#-BV9oDszNRo0-pwP`^nGz8q0EVVQwimq*69I*Xws= zsagR9qo7&^XYm?PTPj0pHP~Kk9y^R#H;8zlu^(Xgac*3WL>yvn?o={SU6Gf1mVZ|0 z*NLjHoCg;;?-F~)z0#I05Y9#OB=zL<{*f$BZnFY&q`xwTKSzmlf7vps{IT0zM=V0I zk76_U&b6dF;qG>LA3UsF9lNSbEe<rA{0}mj<j_Uw7(UNnB51tjo8T|J?X7@vc);In zRDtF%zdLBrzHs$-QEb;w^g~}w8GcayN0LNoX8`qe6=TCa-=#q|@>ocC0&ag#HpkpH zH;RxX5;o{eiLk-bvtH!MJq;?%+HYyH9^SAtpr?pK_nF4}YYodZCk?WuCHs>4Q+IqP zxv7SvG&~`182gQ&0nEHai@6Pp%wT0`--l<N^n@k(MH{geU%Wyx$~%MtY+W<3Qxx%^ zM!_kLoz^IY1<<`(5hs>ib`!2}v$t1SwTh_DXsmwCX(oJrS#Wtz=$WNXniPetqcC`@ z$ZubzYy7;lS9u6W$A!6D8{fOOaGp`)2W+AMTnv4tarFktiqA}s$8mEJTj;USLp$}_ z=$!_~MRDhkl!?0?SG_$beF(}u^s9;g%`fkE!8!euEJ(LQVP+-<ERn2cdW-yKgWcaL z)KQ7Gp|1%)un;9#he60leTr)}FcZ(##0a4rHw#>~{oT^$D;ti!TQ@wo^<069;XX*c zm;z&(hLu^w%m<gTy?)wgt7av8hFfB?AF<)v4!Lh33hsZCgc%)=K<X2g%X{S*&*!;E zrpTOBfa+|T>$0=}wV`0{(rIY-H35MIuE<2_Q&>-0O(;(zoMv#69t0~oY(@0wTYiW9 zr42}?xt|zB0*?6LdQ&|!G=@XMJ=Qq$Eo^sucRE^l<XIah`^cj&!2e25?2Ow}$hnlm zuJlne4&8Q*%SBOa9(JSJKm?|5I}e({o;?KFA~4}1eVk70U=^O~dg`8;)(AT{FHn~} zru96^0&~oviU$3+=Oi$NburV-?v8b#>JfID2}&VePuG8~cqk3tuEjKwWN3Z8h=!*- zTrOV9wJODLN_l`$A}N-K-D$mNXqz^jO|h=DIL}Kd^M*&mq#9sm($kPd@9voD3KiOt zHZQg?x0k7vp9wy(xO*_9*OHES++UG(2~~IS$5qvlt8edJ+`fmoQyo6LDJ2oO{h{ZR zJhZHyB1%1-g35niyGC6TP8N00zFb-3am4JbM!hXMdAs<Sh3G;jsOf1?N_o0TE^TN^ zdVp5}gLc+$8yZL8f)jSQ40R>xC|AL|tIHW;NaOBF<$$Aph<QaTS4ha~gBnk#2iLDe zz)keE%2%}VZ8=k+?OwWoqn!^Mnx$hYm1r<=6b>#OD65)(^VJXxAHHE)G{KzkEaobu zW*zcd8)U2Uby=jAgbJ<<<%JOfRb2{_jK#6yQ9!%o>e;#9O<ttaaQ6Qww=(jj-rUpE zYh~yj$`5E|JWp*HxR&$Eo7heCb};1YLN5U$UCZXU(g|c$seExcZ9&ys*-*S&E|&=o z)bw1F*_6~Svf7#x7t_}b@MpP&8S@_`rM!0zlCc|QLc{Rg#l5JbL$)+7iUqMaMas_- zV`(k_qnqK8;Bv<Oa9DoN%A?CN6NRchS5m&}Om)&X7L|Kt@IP4FMfhX)e)4N-m&DtT zwjKmv9{fPhvCqEm%x!clxg%d#1<-e$5nr6X{h~80W2}WTCZEBWm)u-I=#Hna-#V2) z0$(vt`aVZ&J|wwJ7q1XM(`!(*&9b=HG-~Ix{*hT+lGDH+!BEA2kD~XY8l3UhD#=@~ z`xdD3Y#2y0wErvyw$X9p65WDJh<f%TMYdAS`vaACk<O`!25WgeiS8!C8bX;CeGqoo z&R4*dzY2Xn;IQqt5teX?<UzQlPfHauF6<Dk|4swn+0)~#s>%OlPR{K2n)2Qn9#yPY zQ{as2TQB90DR$(lY}n)JGB=c11=diK_UNa!`%pfGh2@~_FJ5A0x-6-lGi$&W$U~eR z(9$zk+>{B&4t5qSsU%2a2LitEDEaaJ;<fe7)7osO^o@DUP9x3hynBY|8B+Vfh<O=B z>fxfI*a`d<2{o?169N8<g`K?qy)bnq0L7;aJp0i*C_I-_+vM~)45JODn`3ywN0Y;E z>fdw#y529Dz{+E|>zFbDQ0%Sw-{!=FxRwHn;p5)a)_$Cki8`cPmGy9|&7y*4I)8`a zr^5(nGwwvi8-DYA|0vUUt>(hIab4!B6D_1k{9c?XOBaV2%z^sEsgp9C6s#d%{}Y7G z26LHq!dYk+RPysD>W99hE6)|CPdYr0FG{6#EIs9(e<e|-Pa~mJv|XSP4xH3aR6d=` zYMMNY%tq*>FmJ`{X?8%-I*%to^)MA-Qv<<5p&xaxPuq2;NIf<~WhL>)JH?rUt3VL$ ze+EWZAgC3WTJ}LCUdOxRdJ^mQuKCCedCd~j?pdr7&IY9yk(HIzjxhgRmLVG;9UgFk zg=<wGMwTGGL-;H;r0_qhfow(SD_Q^n`;Xkqr;907#7cX~qJt}-ir9F2Ve~cEw_fwo zZu-wd2>tJ(Iq7h0RF&gs%?`*wr^RH_NE`-Ql|y$s`imNR6T1ZJzm)9PL#5jAS&8rm zxAZ>QXxk!c1W@=|hzw*ZZ8w>34=w$E*SWcqSmjI9<n7bXb&rB}w>Q3kg=&g^{hFfm zbY_@P<zinoh)od^GLy`|xo2A89f=$*8637Ff*G<71F`HkVtFRRqLsG6$dZ+{o^hLK z>{<y}$}$=LL991KbFd%bb^1S%X6k$e#@Aby4K!bOK3LC<0NMI-jEta@Qx#vm0n&P@ z<Z|==rR{@5b|dt&Btg^076X?tTfUqhh$rz?yE+znjCDm8ZvMrKwQxQTQ>=jfoGyb8 zlR-N)laAr+@~Ba<y0N`_tAoko37>xFR9i}ShFV3TnID4A;s~yl%I!~0A#1TDl5Gd6 zFVU87TB&9K6#HGOnJ%qaeT6Sm_}RsLL~5joVJKi`z@#L^1Pqyxqa177P!r2$F~Z~^ z1VUTGFv`lTlS56orIQ>CkzLXhJnLv`qSYqo1m(=LK-ZRsq)UMEG#U9^wRA<cz$vCk z1Tn7mH<Irs9;)3#_)`7mQ`F;@mpj4sBsbHE5R$C+L?~fB^e~i>Rw~0G3G@7f>^Fmm zb3t2g?4nBdtB?rEa=UJKxRd@dfdOULkhm@;*wS9LT&kDZ=!wkko&1deAh&X)LeO{t z2UN-MAy!HLc9J2cT$ETSC*w&ZYucahQQY#_+{s#wuGRXiu6vk&Ozfj3)`hl?!J}8L zEz4;O%(bRjm65aeE{yZPp(SQd-*aUe?=N*=un{Ay4=BhJln1Po+}PBQp23U>0=nDA z7*tkGqkf-<tsf1UaxxA2+$pZ{2HZF^2)#b7ke#mty`uRd{NMAtc)}Dw`c2870VT@{ z47qCB-iIt4_J$m8fR{V)4rZu{0mj(4O!#KElT|uAzaFGI>2vxR-Q(gHspwL`OHm`$ zq%x^Mjg9{_JLAGt3Zm}h-=fW*A?IIyC|m(Z4D}Zl^Oybrxb{!{<FWzdvei`roR0>S z1{ihk(C6JXN)j?pTV4aE*bM}5Y_F-R2dxGBPD|*3Gtg>@sN7`=rPiSUy+#Vs^oGEi z%z|4t-vsA#mC$cj{^iyFRImR1$3HU+vsgdgwT%)X7Q#6%$@*6anpCt)do4c!{(N@v zrdFj6v=q<r0H8fdYYiYR+kzrYk(kTqkht@R6|haJq`0gl!*nSIh{K<iBON5V-A~5f z1R20}M4jZwG@#`{$Fg3dWy8!~6OPhk|IM|CqtF%4<m5^LI^KB+*E9m?-W-1g1V($4 z;VgyVU^K~E{v6>BoMM7NzqWX;W{w|<7y*!JB8Y-~^XPIZnrXoEFx=myRXalsUj2@O z{Bxh0XDdZ<<y{X1f{tYh=Kjs^=ASRa->*+x9u<d#YX!)BBy&T+$@HwlgCTaRg%|~@ zllx$Rj|@KlLGQIOM*!p~7bvbDfME~`$LzW4^wK2UGDKXm;M!(jXrAvL7C75Eja8SD zh<Gf&LE-tjaGTzft8|oX=y<aEw_@=1*d}tso&t@ce<eHp<$oVs0}p&Xgimu40ypY! z{^c+I#q<1^)AnCX)PFf`{}gBbOW^#ADDh`B`M)P{s{6+Q`J{BImCb*Q8Ew5)@}%R; zU!pC|m+gOzyoU`J*6?z%ys_cG05%16RrzP}|8^t$mpefB5MXZ=)*tr>XHnRxJpXd< zUj+Vt1d3lglqpO9P@7kO^4t5%ZT_PO4K6D%1Q4=d{x72ys9*nSe|p6McC2UrPcd5m zmE`whY)b1NT7ZAIc>ezP@=&C-t^dVp{_nN+Utse8z9t|D{TG=0ufgJf*4O_JO#au! z_&>k!m$&|60V;S>WgaBk7KfmvOMZ3``A4P95%*DdHU5{;(_icf+F!wXPAFlXc^Yj9 z4ivxq%fx7+^d`}n!}u0%Ar|M~`&UJX%V!JN7KBF5{Zp3lm!CDI%JdiMM;4&gv!$Q? zPu|a^^I#8TeiJ-<ivcj*3*w#@zHABxz{*PQINX2W6Y#GPUZ<miBex#A)G7!3QMnKI zq)xmOM_cA5!?n#b>JCw~r&Uy%V}a$z$X<VM@T#@ptq}nLynlI9d^PG*n^0o*^Du@1 zQyvAL7jZQ2f0}O<mJ7OkfEc$Qp@oDy)_&Bl@7tBvCD$zYxvU|SOiNu0DxJ^RaGHF> zU#=4`4NmTWGB4)R?uZ9Ce(tt3f6|3@DfM1@HjIRXk(T2esD0Ec^YY44NA!)X*ALQG zg0h@aeL4C>Fz1T-%G{2Ape{s9m|8r3O&qw>L0)|SgpLfGHaF-!*!F2SsJ}gN#yT6R z94*OFYY%*m?&LpGJKNatOD=Kz+HmX|e(0PnJ8q#|0>|CO_-JM^;hjUB?KS+NOpcMe zl4s7IsaaX~p$u>DJd(eR);OX{u5qNcLcL<m<xHU^>Ipta*}7&WgdC88952D_jXm7U zkvTf_99B)Od{W-s#b03nnJLsrrQxVIJ-dP{+9y_Xe60M^6l`i{6=KIW+L?A`Wmu@g zyX!$kgZcYg<xr&>o14AX<`$(vhkL52H5GjZv#iE#=jex#USXVA`R)Ndn|l1t&m^-h zf|+%rpg@W6QRjwSgZ;u2e4{;L!(-yd6TH~f{yXON!>D3^*9C9-a~v~%mxroa!!Ro3 z!HHCW0Q<VCqyc$Tx<))x7_dSk^8|Gxk=1hN4)Ql`&wuibjiDHAWXo=@R)eL0nOLz3 z3Vt2q=aUd5hGqXjzlL^eyH>aJ!h5(>B``S@*)32-CvW6pxlJ1o#=bmp9jD4U(Q|iT zhAN}8lK^Xzt!UaC=?m^&Eg__gdVMf3no1nF8^nnf?p9@Ta(WwFHhSZrq`~aV2l7Ky zL9FB1pJUHu=1m+s#1~4(Ip42lwV2{C#e%5r2;05Iap`_8NpyIn7UQLYx@LI;*3pkX z2DtjwukL$qqr^EH3~S9rtAPjDwvx8Vb`*OOZZl$MoFs>Ch$QTICkDxc=q0<fwyNSV zYL%rkd$|dInwRs{<SlHte~f8QoiDmqUzuKExpB9b&U8$!3~f%HzH3?<tdVSMD*n3i z4zE|qc>2Am>cQ_qRXc2}sJh>5k*HF=6L36B$O68R_ZH*Gyc*V9!lhhXFe(a#i?%E( zXKyrJkp12)GjLgU-1XA%FnQU;i>LH3cw>?NUlOLj3~W{b6jUYp65n@YUJwM9UsV23 zHJo#;^vE=}UJ++A#64Es@C_harXy=CBjBrJ)-o<*SMb#}Uph%=r?ZLjN6SxSM|TmA zXz6N(+LmKXU7SjJJ)su(0*$f*FmbBB7cd#m?ET!5By{vscX0N+z?cclw8~&i&0oDx z)+d;E(03p26XH_lWMQfE*s49mIAZ*U+0gY*XY`-OIbq4K#qDi(LT|fhU<$@-vQjHu z=jrA1=Uj!V$}^2&0$ubLwApV)WC%qUbf4uRA%l_vxT<c}?*(~YE(un}7AZ^m`UPD) zhLBt88Yo;uuVAHd7b7C@z%i5~va0fNKmybEh>E+6|3SnSrC40Vko(GKD2^WT#o?yo zMvi*+Zkyh4n0_u8vaPLpSYpXOhu>?QAN?w(GQRM31f3ki)!(zXK`Jgf`O(@fSNyei zXK*)Ct<Kjp9*r5_<!iGOB1JfRuf#d@n)kKJbXz}-)8H_;j(E5C1<#fK!9|CBE?}q5 zE79=udDiII*JXoSPOf!c56TjxOo{Rng-k~CpVCuDf^xlo#tzE2&&f%a*dv&TNp{2m z8zSmDE%`^16E&5i^6nR$Aa51P)y6|7KV8)Oo$bOdobg_@;aU5X?^TY^#O;kg%N}*t zK3}l)!~KCo<4-cXFVWL}WEE1^dR=O)!RS1_c?myncyrZ~uBu{##bt@`U3UEmE<hx3 zP=|TEGM}?tP0uOil9T0OvORb252llLvVPvV&(-zkj2$@WR?}d2?&ye<P%+2b^f~MB zMzyZdE_~y5nMWD+y&>pf8TjRZFF3xVM`v+&#fArTtr6z$3T~Wp3(T}(fpm~#vmffd zF@LJ9fk%5}xs2#rXLjSBaQFO#3TkM+sge*T!UR)y!=8~gQdNcj?e6$Lci<`1KH|>e z9dZenA&r0-&7EMqSUXvBeSB^-rxmxs?n$3lP1-^z$sFXjj@z=vC;JEaM90RKEp3S7 z*otp$$zk(t!wweqHHSqzB!G`8GN-2^NF-_JtC<9olfCkm^L(M9MchhC_UOo~<4fbj zU}>jp!Y;Y<`9aNY`>^<c+h|kq;m8v#<adk;reu8A$8cS`dFpyZ^_qNTc<X&Nzoh<# z43Xg1sEZ%JTDzH#W2E;*IA=c$4v%zA6mAHGY`a2SHeZp)wNo;TY91G)lQym0cpl+> ziPJ*EInc0ji>Gk~9tAY1zB=r@_48F~@*P!J_=0bU+!w>M93D};@#g}6gtge2%x~G! zl8fzw+PoTF`N-|YoB|bno{18i3ycdccsuW&Y8CPVzvc7w(QN$4&!C{TC%?5gRvTCh z{ZM|pP3OFEQ%I^<9j{!2!lDQ`jqG7Rt%3IJLv+W_2u5i-{lLMQw~&r1!^SN?E<#;0 zL3|9=2tCXy`HM{GAE)Dgd_)S_>^$w5MN6s}4zNEExQ|Npup=+rf||c{(V?maPlyQ* z{(4dD?u<KOnYR!YZYsqVlku_kyTvclqgtEMk=J|MU**<bHXMrd76rLP_|zRj(P80c zI{kJ>=+C*=dG7}#VK-yi<V5AI%=FYq6?PpBw!fp*SL5oA$U@o2Fq?Sq--nkj%?_}> zL(5!Gz+p`%ew1m2Y(eWTihV(HHlpnL8$2>CF5PCDc1p4{!479UPYhvXX5P_SV81k5 zJN;AKyR%85-13}DRkWqiGT}+)n`;~)iuMZ&xo~7@(*D;cXN5b!uHPAZ*|*T`u&%%h zHkEwi?#Oh+(Ta7Q=TC@FzU|@0M5XwlhGi?#<3wc%Bi&w@$!FjSq)}yT@!8Vxj);av z?5`6OUn{qR*KX9gX9?H)j0i!9Yaj4QQd}z%2_vN}y;~<XO+;T;zAYxM-OBA7T`1q+ zKd{BuC@UrNiLV@@K5+fhIr=ZR1<Ii5L+}Ay<7E1-yH42{GWKg<3#=B@G@R}#NP1#| za#vDhi<w<cO2VTyB>Xai56T|7&G8+1g((}zn(~gm(5RD)rlG6RXImu{)Y5v^<d=M7 zMz^sKsH?xK5_VfQwlmrrKTPsbSEBtITpeV;e)n)HXS@35-uyYs_O1|R?%pv6pGRcq zk-Gqd@2AHkVWZF?n)l<-J+WcAnx3;K7+fa~Dm#k&G3>Xc9Va~NmKVi)tedBD_OyCR zsC^zXjeMIHQ}G@+8(sg_%PIZOy<k6(B+x~~`^kAgy3U`SE0~`vs&Jnfe!j%UEnl8Z z9F%SKla_2}yA(BecYVLUdF`Od@R`%M@g?u>)4g(e5oc!k+1u8ep9<ax{$TS~YXeds zxja(k9T=juC{&#;;#zv}4!RiRyPUT+d`oIrT^)rBM)e{+^CT|ehhqz@>Y&7{z5juo z&nhJs_kJ_eZZV_{J^-dEMCs_ywsWIpUZ(X<@$8HF&K_;D^-X2s&Lp9`#Ft#h2l;o4 z1DebmPRGNW^y1WavM0ej6gFVyu9icGOKP+_ak6f~FGN%0b*WbIx{jU0-oza&7@|d% z@fi9&zT;zaWLk|A^6NKb>PjEh*1N%V^pnahQ>OA^MUwEZ7yV&)ZUF{jnmvg1YlC8~ zT=IC4%EwQAmy$Q6O(%Ln6Pm;JezUmKrbhZ#yUBb;a}rSb<<%i^0wW!SaWxTlmrWVt z@oubITtV$QABcr5NP;FgXAW{bOQ-|H_>!(k9+Nl(xrJ8lwJ@{K4bP33|Bo4q!z{Qy z7k3yxm9EPv7S)E(rb&Ch6Kp3#lDDVC2uSGQNSut^UOot42n1FbiplQxKx4`V^sHSv zNf|H$raxv8H&4QU(P&{8G^sC`u@%}x`v$B`n0HmCl=_yNZ`TW-68FWzy|E87_>Ms6 zn1lQ>G6sK7;Q9~NXj1oW<Ec`aqL5nD?<DY7`ch^kDNk9X@{={uhuO_7a*O-|6NbOu zD_nUbIKCR>J7Alfh~p3CF>G%n-g@<ajDVu9ltg21TVfZ@+Ya3l4mBNbFUv3YKy${( z<bEJ^JrWxH#SX@vxdj;O-?HEZx<L}`yg7So&jIdsklRaq65z>KcleuRO8ll4h$-Cl zd017t;O$<8J*_B2+S`edy(M-B{-dEmDhMsR-2q#lIg&2PNe^+*SXi*(HnGChWH3CT zf2Jc&e3_AW+7wvdy$$ZJ>|ftS7@PY(6_8n&JlEqtb)sg?SD;Jou-ks^#CyaB45t%j zmLRnk;9&9yde@ZHTdJob3F*GTF(c*8uml}GGn0kxGH6S-{o@sDD4&SLC~<uk{)V%` za8f`2-CfP^6cWaZD<w76P4L3Q@9^SOTan*MBV~da>nfZxsW>jabQgtaIqxT_iiwvv zjDCs6yBOLh4-Dw0N_!!IO0(mfpve<TZw){K@D>3?Tfnu?@LHbTDKaI9`~I{tEgjg% zkab?v<`A)a<R#Hev6fLlo}^$>#X}DF`B7f;$@V4yvshpjOZ(4((W>pVQI&IY5a`yC zL2pz#M5MwQH&E+MgsE|Q#goAFv5CwM&}M;NA$mSd;{uR>Ru0=f21UwGpTVI<EdJhs z>I;x>)XJYa+t68BnrR;(BOP2U${|+aqR<v$s^K!y!sx8rz`L4t`bRF-2NnO~eCjqN zR#p!An^f7u2y*+}qq^^Pgb!p0IJUUX?2l;!tYu_H<yo?(KzQJxh{h_4t)Xu;owo|r zvgeDqXHNR<zUO*)V_n*ZY27M3ASu0by^K8(rxpDh-9_+mf5};)0giXoibYl%QDhtP zZ>7|lKEu%E?VuE?wns>zFf-mwAc}g+6i6(b(6<h`wPlQ0N7v^1wzy51IB@rJtfzi0 z)6?j!NJ}XjZ0t7EwL03$ygnZ3U!_?=pOh#sXh%32?x&_A3IF`{BgVV!Nh6Qpk!YRx z;#TFMn#x<sg(uODn~`73*3Y_h3Go$r&JEvr?G0Tx>vF#>8!_?lmD3myx@o>Ds89U( z(cvtwW(9ynU;l>OIVZE(r|dE(uUIq_D-+9OSV?OPT&7_fR*QX~$$({RSR+N-0JQ!F zbMAk4t5mQ#w+(RKE<nuB+{`FkZ?&|v6q6htq;@QnXk-OEmA$d%KE{fQla<^)NwJdC zC+mRyHeijFVSB=SOeH!v0iX%kF54QKdnKfY9PZ#tPbq`Pey7+<-{Ev2S5lh(wIMo% zI3wq)Z9)~@5jmRnAknZ<^(+bZAq6&f3iFpHHS~ag#tWQ3o)__v7jc~FnI7T^BkjEB zOe{iqXLB5PRk<hRc*Zsd!vgE(E7=SxS_dP;tcuNsT0wc>X|QV^kKu<e=L0r3W2;Qt z?yon<?(LWatQAy_XPSQbJ~}H<m%@KH|3FlJLMXt`xM{<tcg?}vG=Qu^Y!$}hBpdro za?kxDcV17fJZGUR344)Q1AiSj{Udg`Jl#$H(9GB>30*N3U`Ad|bJj{<C}7axP%QEZ z9=F;GF6peBNP+!+Hz@MxNLUCruV1n|wH~;)MU$Cy?r?E*ZMf{U{cg`wFneF&)$gI< z{Qd3(_o=H}zh2M~ZYNn-CN-4&NL+CK6-yeP8O7Z>NWmNkpO@u1eHldWE3*o>Ptlw{ zsbRI5sfE+PO&B_H*jJACx)QyfRSwhJP66A9)-_;EvYzGW=s29C!JbOOyHz2FHqueR z3x+(O>Lz_uta-H^$|;zraxAp=%t)<Q0kKp~UVx9U3J6S$-Q97Wc-INa=%WXn+}~*g zH2mkb!9!QW7=@mm>ucOuoyCM5qrzuDcQw&_r2%292BT5dXn)dO+KXVWQ;=ejlD5Ds zzyCB~wX}_&&^kSBT?eS_6nc;c#h633;mUatsu)TEZ$_59T9XX+fy|`l*-Y_~Ansi% zsbwfz^r*z!@+C%b<Njfn@z8H=Dmak^?<#ZYZ6)RPqxViejSH!&eLGZG{^nZL!wMCr zDCffzCH#C%#vC|k!EBGDzln5zGEt_j8A65Gqerh9)ouEwmS=(8-xm(?#3!g#RDIZD zNxO2z7p6>`=<Sl^fJ|vksEe6g;%{LBqr1(Q`DuTW+aFYkcTcZwvC$s?d|gnUTo?=7 zd!u|BVOQHpU0L1UzZf;T>L1wp?|eoQ<3pFcxMp=1qRXOJ-{i96hpi`8^c73xI6t@? zz^zl$p;o5*7A*meCcPfg3HhT?`9_z`Fol+rg#;sK#`5U;bQJ8IQ}Pj@+}YjVq$u3= zwLaarEQE?2W%fAu)y6Gu{q2E(AZe`qDPX4JFW9F&zH{eJ6&M}dYdqSMw}%}UgOp2x zSs)nkmSPd?S?O)6lSA*C#%equ(Bm^RGZ41>n_Pbv6&(vr0pxW=4W|>3v^_aFJ2wXi zG)x@gMqnh~Wq<qEaVSb%U40dJsaJpiF>&E1fJVB8)3K15EikBaw~VZSn~BficWqnC zgH`b`vv<$ZE`Va^3yMReC~xAZA~+yodPAYm>^AxCDr|5&{Yf+0t)h}XmzGhyPJl1` zf@kV5w~QG6hGubKkf3~prAXcX*WPzVHMw=&3W5b23W!RzAQGC2)X+phL4vdZ(h-pk zN|i1s77#2nDFFlt5PC^~gep=5={+G7DWM}>`rXlUzV|!ldwGvz+;M;0dvnI{3=u-| zJkQ>Htu@zNbK2e1ONK-cPJy9tFLCdtE72PZ&*<JhUsTLftHjg1f*&9O=%U3wBiDWt zsl#V~7DQT?9+M2)&yUM5_n^W0X}rYZtgHtTi~+`X;A?d>=Iv|2T(n!2nag%SC81sK z%`L?3P1{7`c8irgZEnC}tNvg`m-X7^&dfXdn;Q--2mZj`p7O_!Gv45jInn7dGwrUM z0n2-|y}1I__>gkw)RkKChvWTM4)yHkjxomOX-=1IZ)Tyv81*o)x}l5wX?1g$)@e@u zYKMU<v7;z2_D@#JAmAL)HN8dyLAXI$L(e&R9I!%(@df-zC<gqAI2nr6>$NZ2OwZ14 zZj@Y5#tlAWDXzEaEo=cXG>*>oDW`TNhp7T6`aXb1M@J0ca+L-7&XR|!kDjjaYwu$G zmcGHgB(Bm4g;Q1K?5Qp-gBj@_Ed7jr6^YS##m(&NkI)TYAWq0m$7neXDLpQ{*$oU` z3f+iwKge(3K~dfWm1TUv<WG2H-!8P}DRb^wLaz$ji4)~?ef{Lz<A-1;K47VoXFdNF zDtwwKUX{t(ioYCH6CwTr+;9g`iCZ<mGJRRwrN<QGdOrYhDWzzdNYs8=Z;%BR3BD7Q z70aKKt*2`ISE-nCCZM%RIVs<o&vKYUsc@fskaJEe+BJ(`eH*4fd$ocI(K35p=so)~ zLEh~C<Lk%;NsEH>ou{Q5kxhhqGW@+Zc@d27{bC|*kJ)5pesM7tY|=zC3Bw}RMmXFs zoVeO8!;w_uZnUi*uoN*~Us1{k8~A{F2#brJWs_TR*^jy1>~T$PPGsHNuGDMOJl2e4 zhhC!P3O~kd%OCYwx9saZXtAqCn`Y(+Iw})77ajAs0U>fBn>ry@KO0-?{hq|)@!Dno zNNHABs9m1@R$W1v7GrmBm_H^b`?JgR`+GR^b9!Z8&zZ|WtmwwPr9DD6i#hu{N0{^s z)l!qVYjo<74_(R|Q$<p=QLgU2Z1eIBDyQiysG|c9Of_=|<W0T%l&#PsalS>me`Wuz zU>Kb>RCkrETfucJT#RrMFtFI1ny;E++-8bM_{H%yM2$Vr6oZ0k^J_Drp`2YCs|yII zHqcmi)x)`D$ltg@_E)k2lPTGNjH(xSymX>qi*52c%Fis$XR9bfzo^y0(Gg)LbougB zx9Mv%)$Tnyp-`D68D4L&^hJP02q_uig8y<@@_YH^^#q>o-UrdKlB>fZ8J2D3(K3sL z;o#RtZ2~e@qfbsw4hE3Wbb;?jOzD!N8_abYxC1pU11ZDqPyPpNflo(xRMf=O0@*s_ z28UNZ*E!7%SEbq?<P_h~mu&YF>$BxXk{SU5{@3^XtZIDS8C1jcXldHPKS`3-Q{_}q zeV45}`K$rcYhhEZzrL+aie$gE`5govOq}=Hm&lRIO*=`4;hVRVP(SP+yDf~0d+{5U z_U7j0A(TSbyo-TH6XEC$R<#*d-KAtRBF|^wP%`Z)+EI8|Y+zUNnzDY(?D^Is(m%?9 z%aTn?g8cFfZdPKbgE5eYho`ZWoYa`vpk<6a=lmDEjQV{%mZvN|W=jgl3RqF1f*v!& z&pEswlp48Cw10WngRzYs`cNud3Uu-z@m4A&Y|0Wq;G9j#7$jI^x|}$bz={{Pm`!pz zzb$5EY5+14Eov`<5ZrGEL_!`Sow6+7+#;P^WKUbs^s*acRg|A@5bbw@_&JZaR;3Dz z_B%Cx0}~XEeID>2gV{;<SuoK(n-zwh@Q&p(z_ufmBfohX#yB>LHzMIggP}Ikdui@v zqN@?<q5sgLcV?3qqFxPsFDS!xwoip=BtO4g?r?`&3*5DLiy#1j<en6|FSgwP#J5%t zc8IehlE-_C@*EGF_vD(XEQyGRcjez+v*{|GTreUbuE3K&J?<#t$(30Dn!B$(9He>p zclV$KvPjP}aT_dWnV3glMji3)bnCZtFZY<F^UtJ%{E&ruxpsjWwR7qHNoK`WHSmq9 z)Y9eLgzxWAdi;iZ_jnyJx=omuo!C27%<J_mX%G$mx<0GPg}@Ar`bU#)U9Z~y<N|a{ zHYOx`G1W|%ZaaMq&*TSqZ&i5gsUcP&n4pdktfHjYPo4LI0QzIM1^3iZr$gDL&+baZ z@`~7?t9s-+&t0m%tXHGg_OaQhY)M2_0&hoq-ZRY9RHkV;c)O)dXzKNdzsOcSdSoU9 zay0l9zVmLKo6&oKQj*KTdg4@MEN>wf*L6bDa||8y>5rdj{BT%b!;#sz`(5mW&h>>> zXT7O+%n{;LnE_D{o<4VdD0lNn|ED_z7`dcVl?L|aJ?SH*j}hA^qR&-zZ*sdnpth`- zPLo-fLW*kdd8+m#LT%sFOChLkfzqe1gy{oOzGvwNsYA4t(bl9gecnXR`1ME^x##5} zP94N-YJKd*1SG>#tg*VG@i^Fh`8lRF67`2z#hQT%NY5J_imx{5z-8?EQc{E=>VXH{ zHKNxF5oi!MKQ?o6P~oO_KAoJ<35+Vt(_v9R<ZAJqfLr-3J%QmVuwCQH!>UwI+(Qt^ z&JmZn#ho8c1@LBOi#v{n5=vCQOV52~FjJA82qxYVDEhp$Qnn2jvoo;K7`V<{2m}#S zq14-JU1d`s1m=;|2AobSz?elA*%?@Wq$AjS=zaxab}9o|?OnHE{Z#fPOIqtchF;fy zAHz+8i9s9e3uNHHh*uLhOwbI4t+e*r$ni496YnLQt^B93kJBfFDwt=vRbnhwdWEW? z9q!-v;4!w7o<1|pAD%3PLR!a=Pv>=&mD3wyH$BQV=!}6KQQiJiG@|_5;Pi{yy8qqY zZkL{Dqy;1o)Tf<`h+bRlmvb=(Hj72bCcgXiJ?E-aY8SIB4?AvoXQiYn75RzNRY?P7 zT=+N3qL`SNQ+td0yw`0>v&V&r_eS@``$4sCE<fIV*r~5<ws7e1ta(s)+meNsfJN_! z@TQm3Qipbg8wwf6ZRE8SX7FgxKRhPJhAf*UWLFX~S^OFgRP9G;8W<f~i&zmXJXt*Z zkfv&VFxRk(E~nlZ5oe9T?alseao>Ugq*v=hU>cH)P|cyP&t0;|a}a;%w2-ppy2+Yl zk&b%s()T*MeBH@v1FyTCnB2%U#q4{Vrn7Wh7qg{iIe-<V@7ht&$C$=Tw~VHz7ps3I zo|Wh}!R^%=Jq2|Rg8gtYxcNldYURGm`ith|5xPDLv#Xgfe=YzR`nG+9yy`hG+<1J1 zu_rvkm+3f%xNzm3MP+B~K68T%j=J^vKXEOCQ#r0!1EG&WE2KNO=%#Y_*QZ}dIcAjY z>t|7L(AxaQ;v8*@=F9m6=I}k5Z*Ah(?O*1oVJr;P%AG1NM?NsQkFG2|&1OutiJ+s+ z+?=M0F80>S*oS!2SHnK$WvfGI-G2d*qOQTjOI*5R=y<z!T-@NtT-gitj$IJoET!VU z9g+mJgbTiYRZjLRFLv{Rx@M!~Z`5@Em}?T_hIPy@EFkJkKumM+?j&wwzbDB)^Mgx7 z0^<nL<|>|o4uv<?K>66E`lPvzp<!&^9XMaNS%g81>Wj7h+$xPhjA>2qa@_Vt&1xB; zQF`5G9c1q%>m9h28I>>^m`N%WN(_lXReuNKgkeQDwZlXKx+%L#jk=HkO<01a;yx}( zW1Pk>2flut2V5t`X9cm}Rquo`*!*&kPI>tl*b*=gIWIgFxSw_=K;UrNr}TBHjW@t8 z3-vff_Y2w7N^`Ec46Y{MPwZIS#Fu>e#MT58CEg=@Fn;>7ww1Ph1(Ds^;f^|!fRtt$ zb%-t{89BAcH@d3A4~YY(7esk@skwCwhv)YX4D_l=5wE4!YE$VFS-3Rex2_5mSk02H zq%=d}aPmxlJ#JI9?@?vZgN*4}48g9^dvZ1yIE0DyJ1><OnPh?x|9QW9VFU0n7$LG; zI>x|&C}Tda{C;5LkSuw`;nUIP{sH&6_CvOG8R1=v#eKLX*HSqQKo|_d44$zJtH(Xr zbI765Ys_mE$kFo@+(t|`dt~;pz{k}{=i3?kfLt{`n7W)U0eBr&y7hOO2YZ-CqF(Y` znC$<wD*5n<K5+WVGVop<X}s?&o$N?bK~9*j@wGHO#S6ksHNi+!ITAI3iph-6rB=gp zz;CwAf51cmq4lmwS(24xN5$P~AW!K4`8>%Q0?8R)xJ@O5z_sL7T+Iaal2|oLD;3!l zxV05p;%Bl}?AWBi^Vwx2O#2yDkMFr`2^}c1wCyAUuYgSbt;==H?A+61C%Q{l-n4)R z?zInq{O#s}?K)7??a}a-Gksd=gu6{%B?88Eo!*Fdw!LMZBN5vGX&}8a`gVxUk`52r zm?rB>H*?;<zp(CHao-%T4Ht7FTuV0VE=NfE=xY_gj}NzozR@nu?ZqkjSKG1lHKwAH ztvu|v3;Wn(zop5#G&jPgN;RZh!=B}3b{-k=D$3=I@N8r)=supw<4~Pw>Dbg)=0Dwb zwhF@-fln4%u))W%l$_2AeQMz`i?Rd4=~fjcShX4qdT8B4Ni7Zk?Y*luAz!={hsc!9 zMF;g}O)>82kYeWp?(`oHu!?M|>*bqW8{^f?y?5U;%1fkNgDVX=y}8m~05Y|{I|f(J zkvC}DOWp#%Ae0^t%~7i~5S1W$bQe>{hd*qG($MK!xL=1wq#y%zQ3sL80|qmSSK-H- z<$1TE^Biu&M_GV=gX;@-L*|NhP?IOoM|gbGfR{LRB?){=wd_T;a|sC>q_-lHtx$5= z+vUEPjQsYZ+U2#$ECNXAX4pvJSY)}#6a-<8aqhhHK|PNZl-->1{ZcTq4@kQ6Yf}7K z<KG&9T;~bZw?{O8aVS4AeLvzLFMorud!^sLhSgEI{5}zN(LEc;fi|u<0Cf#^4SJ;x zjVrK1>b)~TRPHLwB`a(f%U6R_11qsNS$my67%^`+Kh*CxWhzv66!f&7P=Ft8xuU)W zV~$%wXu{e|d0vf(`0wd0U7QW)*V~hx7TAe3&Qg7kdc?Cau$)HAbP<@cM4dOdYGqq_ z$h_!kCO~iXz<gWhrL&c(AJYy@YPKF+VfwNL0xcVre+nZzylp+jFBgsmkQ2TXVnYUg z-HbHNO#IEBL_<f0fOC%WAkWIeHy~5vELVYI%v`vz71p)nmaxDDc794;G2|nzjpo^c z+qb@5Ddiz{%55HHsDSa}U}`n1tvDVq$1b|CDhlIHmDMycF^P1%9v1mr$j(+f?)ItI zjgw>dudUeMD7ft(z9gRUFcr`pdYg2lNJdn61EaX-61P7#8PO7?e++m{;?dS{!LzY9 z;`_(|0#uw$;T=dEZ%UjZZ0pGFKWMY<@r51WpauuP#$jZ4UzpDff6Gpq)@@rdSi#fH zHqjmSa=CV7wuvN_*L^?hJA4l7eNzu=GFx6WRYq=WE)kv~QC{l-nIkGKIvvv5$A{fV z^U%v1U8R<%n^@aF37njYc8Je+iYBhz54Wvd(R5RM5s2A)yXk?S;b3~2t^a(fK4@tC z(6N}PF<lcrFz{$~lGS5g$cTRWU8OD|a_^&0I?U3z&-eKjU^OY0mx)%U?%wbjEu6<Z z#2y`CAaTB@%3B0pv>*w<62a^?ZF8NRRk@5on@gPuHZ#7lAuok(B}_=MQwK_+{XWrj zdPN#66Q5oRD6ASiO-<hp@YBZ*<=Xd`sxa{iBlI<O>dSb#KjP#OE0a%YNW)QUJ^+m` z=4NARR#&Yrvy46>vysij<mQ(HkQ)pr>BP1VgUQAN`r9BOL)h{>T>_;?SWYt|9o8Z# zzyPbWGPsvRjC=h4*Y_q8A5ch!NQstIoa$yY>QKrj->8}QaIQUIGV>{Sd>|29sSEn8 zlL>i!3z~zbTN|s5RSvXz9Zsj$E04%5_BF5@Hl_bEbd?=w4`6~#XEd=FK<dDN^_Zs5 zAv=_20?WR3#<5m^2ee?>Mr$f6Y4(eIaWT){P2MRKHiG4thVw~ypLz!o2o;3xSF}W- z>IHCLR}C}DA8)TLq5Slt<kSZRy^`T(Ve?zw%~h`Oh1M1GZOe*Y&WPpPCITze&@66p zH$j@#sd2b;eb&`4_u8|A50P{SlR)&o1xGVlscVc)kOjBK+<~)fqergaov82v;1$=n zFhhFT_#x$8sLzFNpWWn^$U@}9#g-d{Ye%FQmq{<TNv|586brfKYK*s(fnoE;NCE9Q zZMwOM>f!+;%Yr82*6Ax=82{E!tE`$#8I^}wrZnS<7h7*lzq=*CQ*etIpPb6nvGGJ7 zh)<vsUrSe~UYNB%S$uRUap5{@$_41}L_^x!=wJL1G)~<96-H**O7m2ycS9wqp`cJU zIY9IL`JQEE^mCP_echRmJBNxL?aJFdjry@6T%Q%h!(tB?5j0@(8S)`I>jM*ZBYX0J zg3{Yfbe*G`!E{hP4%k-5;-t0<9^~293Z_2r!GEm6&#;BWka!O`q<-t%<j7dIyHSyE z;&COf0w;<l3LWE@7QlXz{&Yv1<<QT#(M3BH(VadL%NdT8j&U$J!fia-fA7lT;HuVQ z6XRR{=+F2YUG6i6Sj$$W^{FF9Rs6IwDlE;t%l$l6?)fmjyo_ukNgI#=p!n%6fw4|t zLU~A($`x`J4GOHS;1=5B1>=p4^D}$+?MLb$4hSHyMfO`3Pa8k%ZE#L~tghq&{Al*J z{8|3Q5EImB(zxjr;w>|NumU`ik!#JEUWT*^FD!HBVxhq2alaVU;VHDX4~gbO6e>P7 z_dPWiDj4J+zSyJ9{+0$8n`a{hN-ZE&14vaQa$U8}--@UR`(pxAgl2=+!7`wKK#61G znhC@o)vk#~gJRhX>msN*xu5two+q}Q5d#qra1nU5SG&D+0bA<>mW_lcXG$tI<I`8G zEm4;X_mBan>4cxRqJZ3w&t8k@8K;>M+pY{cq*rHY+Unk-jopSHUIqRfKYc)ZWhri} zPkSF6_Th~GBRNDX8USb$uAg5VRZ00$CRc>B7cBnnNA}P&^D7kXeek4YeFoQP9whAu zv9fdKgEy;J3BrwzkQP46)WX%`zsSUp3pwtX^aZg&%!BG_@52*9nunPXuhk!@Q1J<G zgSIz)=`@BAQ^ORKmfjk!X9gp+IVEy1ov)OdPd6ffD#1!GblO%M`~{O%$u#$*fp_0Q z$wCcl`Hk|EoYecShsr*9Gdb+lHeHukADa)I*jf$G`=U{$1UsF$*nWZxKsK_Kb+7*z z#0jIJH!y;(930zM2<N>chP-A<LxiT{4J6xm4HtXW*PX{l>1+@8XG9XkTOA`*%m6rv zXkC0-6kY%9)3>{c>DtlP33=AJ(`Ak*(G#OCry8+%1+lA{wuG;TOU+}M7{eqg6<@u^ z#Aeimf9-Vi$>N_ENRBHjN=jx>U7yK<xh#Dgq4I^g_P=9D%&>ocj)2oc9l{F>$A8nk zUc!0uAT_j5_9HAK1v<<mrrxG_C2U$SYt_h8onDSRM$R@2=pG$a?8tC>_{A3MnCAgJ z1gdyxW1Oh36k3Hrs4d)&i_(l{rZK$6AAzr(5_=G@afw%~o5}9YtqOjGr)FD~0IW*O zu&vw4H7)9sCEeSU)!X$0naKz2=$tL5P^=2syzSb|^`}*F)b2*BK*kFJtt47KMiX}H z{alL{uc){Bli*b9Oenu-X`e;$kE0y<^F}iunOfeH0FIOjg1U1WP^_y@otLohlO*Le zY-68pFXsW+D<B8^AQ>50hkBG|iMitSzBFR(_Lq@<ZE%B$<=FtSljvVS^TRt(DXD9- zG2)IfkDo%lia@1tS`;R#NPhc?YqGOwy3q@TiO5tcre}wi?u%q-=v@_9i3x(ZPkQxl zmoy&&9*cGU%!Xr0pr!j!L*BqQVP39c#xKg-aFACRF5czgBNoTKbyWbd-R$;eJ_@;C z%ec-KbpivxaEUl^2@Z9`u*?bel?l(o*tRneR{o*7C{(Ov-OX*zE`Uy$3zq&!SXfJe z#EfvPsmtfqNwcKkn)qJJ+JZ@4)FF9H4iTi>c)KHPyUA*!E;_ygoL&CU^K%^!&-ZqW z_Xm4C@-?&luI!UEx~E7wGN;AP$2@6ePGirN0^VRNgUl}L{>*|K$!jPx15XQH=%nmz zBQ#JB!;G3S;Y(&Sa>aSQ+N8oo<E5b7ga&R*-m+z><+;i`qA{FZb%*q(e>`VyA9G%w z=^&;X2sKG7uk$y>zK^m^6I~02e^*FMXb7Gre9b)B+L?+{07uUnL*a74UYq%~JLuNI z{o`I!zI|QK(EPBp1c;6mN;UD=#t53MG|!aP&ZtjTGLf4p0O`8OJOFdV%r=ODH!4^< z_tyhNmjKr`80kGdA%b|{wm%QV{aU?2$RmU45M+w@_wwB(xBWpKb@MAC_mU>fwk5A{ z(nqDS$?I`5^ZZ$s60ESzQ7yB5XpV63nZDEX;_%K#^_bs<goIQQIIVy2Zj603cst>s z>I?@E1w7eZ`MdBw;+1$7R!~<llOECRty)BAR`6`{({F5Ek&vj~bLf->Xdym~l$8bR zYa7Me;db<ElyH421l)L(2ZN&X+TA-KK9?KGYLo<@6sk_WpM+$oa~jh79{TJ<N{7}@ z^F|SiX3n<l%`^rp37Mc<vn|`3vm`2@#4nYe;CP5B$e;u7EEJ;)lerC6J{{k<V{$R_ zaTdyWJf?P{qjZvHCKq^$k*;ZWq)B8ThdLL7P>)hMqp5Afgd^+wKsnlU195h;uLLJ_ z=z-aE4Tn!Y08t5dhQYRT^|QY6cNP~S=J3z@8$}P$5d(J%Yv@q<s97iKLhVw6QS?-l zc7#WS%rA<<#>BZMpPa_n)w@BiJ!;qR_&JYcahb0BZ|bLwmviOT$=zUQwbISf+;R-y zD1O*(bhe5#7BuSadG~F1@;B5MEZ8CbNr2o%x*QzhgEwCB8Y@b?W&4v+^+p5<349(j z2U8o@YNi{Z^<2ua<x4Cw4^R?@`L9-Pc&@u$Ep5=zG+yXr4A)DV9P4YC!VJbj%z?p5 z3Wx6(UL+p9V3Zlw$Uf$cL^Kb6&&DL-Xq|z_EcF4I&Bc(a&!0nkkUk><VI@A383ka? zp}?B^c=-n%EXA(__!3Phv#IKwI8oh!*oZnVTOqKG#NBf~s%Was#D~yau$RbLU2GeQ z35l};WS3rsTzn@`>o7#>>bPCR)~j=`ZA7bFw(?<m*G8LG<VXtJ|Iw1}6iogac|RO& zHfV`3bWd%I>?2v3M!jA;DPBSz(b#uASJprq2x<)shup@<2Of_^5oUU_;xvfofSLJv zT(v5^N)XnRk{wYRHvug|YV>0}97A*fz!$`_61oCKvxBNKEG%q9nHGrzUK!<VN^POT zii(PToZ7%gcB<{R%po&)_*HOZSn*x-+49s#x<DJaDD6JMlPuOzxoLkst+Cn~D1A!9 z*_10Tz{Nd5i63J^mM2{%yLrxj8LD}G<U|z2gxq6D)tphG)#>PV?o$x`<PVA_AO&_2 z5^CuVmr^ImFZLul%1!j!qAnv%>6H$c_jc(!1_^N`G!n*UE9#<H-Ypz)FaQqY$Tuz* zM5WgHl~WgNfWn#H1zgSLeeKbp9&%4aCf+0icq=!|>Ht+_9ama+v2tZzpELO<9XnKz z-tLX{>RN`&x3i^6>YKQ8gl<P@7@=qE%bn$xullo&x8n$4NaI_oQ?}c!)Ufb1WG7vp ztc`LgSGC(GtuR=IPRqkS-QossgW{gPZLTiq=%MvQ)%w>`X~5wlTz&A?xpwEhL~&70 zzU5!6sEhP-QzYx@qO4B$b%!VV?#5$J4ityw|6-1PK#ZkNpi6S%KYPEAun$3!Xf%03 z#?3_+FEHFqv+|GxNP#eOx4ypd^Q{MwW)Yf(m$Fgpx;5wUq;+YNFFA^Ee%<i}?8U@D zNi0qyBVoYL<E~PD%H;@@zCT`WzXPrPE#|jQa~8m&6`88pi-d~6iKtwpafHezDS%Bk zB0gG4^oW>zq9OHfX|NnVdHHkEO~&30K}i4!O18?MLxYD;)N2?3XX>J1JY7d(!pQvm zyt0Ov1s%2MD`az&%6%<!y5|pSD%SQ*y`bjs*~k$>hs@Bq`a}R<UxO2B-5M}(Hdg1e zLld~ypMu58sVe1*J?xNr_m#lDNoXRZYzBY~W_wQ5wFg!3TH-Uh3_TjErB^@N^75mD z*`WCLRE?5AGH^r6l-nD1cMc@E1tBUDsk#<+@&d3!$k}DGJ9K;|jpkKVk~mq{A!_t? zSlQARlS*0xXBYTHCS-?Zp`{EzSvuB3Y!dBP_%lA~S1?sFK2}drV#?6mESBJpX=2#s z)HZ9|*18hQuZIzvT{*Qt7Wk~v99N=BMd^wSu|r+b$9q-aB%{vsJEnVCA3PRf1esx@ zl+<#!Y2#dr8z1~#dJ5V9t<N-}X{5cq9pw^4I+~(QZbR3>%-@3cf7;CJn=pZyuFaG& zz%inKq3;VY2LdLN?a_)PFJ66O>LWz0#K+9ln#h-ZH^5K#8vA?uRr%PFc4Y8`UBkQG z5eMW^xhrdXW%O-(imDp#zZ*)NUOsBZt3s~Gz1DDosxCv#7!jMSD+kOCmYDU?Q!*si z9HPXYtvQ#$JV2$%rJl801KtYmZbe?A{R|SS(N2~~GmOfGYxAp9lJ#|Sy-d;X7;S4- zZs!5eT4c@EC@HItEo5qOH#Kh>xtBY{e#fGxsMM0VzpyyX*={^-lqo=_9-t17sO<&T zKP!-V0SbT@5EV4`NK=RKKwGPddquz%o=`OW?iMvB&5{Q027y8eZk|9TxiibC?9F=S zg<4_P8GVgaZ_=iOc#pzsc7yxTQO{Jlxtv8)qh>-SXNwo6UUJ7~lbgG*fi&sEKAv40 zqVePOc7=m`NT;`X?l=`p0MV~+l9>=A$T&x@Q)^3^U%1bk$#6ZpIjwUVDU(2{4ALd1 z(V5a39wmSrm+@BwiZdGV!$3+Ek~agSTBcqAr%ZwHRJaJ&)!Mzjv_}COl+IQ_C%ZgV zD*=k<wQ_H2_IN&1tQ{uvhx`)yv}zYfzKhj`Pr|q}57dnaZ_ifGv<ILbuYa#R0u79N z@M%AwE|{eSOcnv(b^I!O8t5wayYaSafyJB)Oz*Bt<EZ!2DQLD|Vf$DrYJTsY7}LXc zfb3NBzP1H-6i$sgoaspCegr-ui{NMu4H(4W4?0-#0sDexXK=zsHRg=XM(5{WA>Gd| zEG&FH2tcAID#DKbtxf`o#i&W$s~>>4RX}jCOC!PpD!eJ#vJ4IcOMR3(GJ4u678n3J za?bSINVqx<zrCU5Cidy%N+^#8tF~|to8#9@Bg-VMt8F15(t05cK^g<k%%WXfNs*q_ z%ut5cTkN||mW#OwJ@YErkc>u2i2}-+C~_|ieRmGcr$Y{kL*tg#Q~vgnu5~F(py7W6 z@pdpn0j^oxU>BSJsWg^!fQPNEAd=`V*MM9~n=0ArThZ=;ZW9LB0)09JS1KmYXJ%)O zj=DueK2T$x>=9@o7uGoAjbqX1Ugp+Q-Df*y#FL(oOL;Ha+i58^AjOg4uPvxI)E#B( zVrL7n`O0%LJa!^=A}PQu?knCRvH#1wfMdl~{^{atx)L%+d~81O>lIY3x&nMT`jH|s zDftJ)Z(Qu4hlOuO(+UkS3UnCr)uj09ge1Z9Zci*9lZnfX$SuoKd;KS&EU1&;K8f4| zC)-Vvc!*V5fs(+YX-)tYD1dsJ6doIEM<+gh-6$m^fiq$zn-!Ehu0l+-pL?M&bi5wb zB(SQ@1_q?!lMv1%+$rakM4ttj$j&rv!DwLcv5+qyH-0xXirNsHhz23O5AJ+MoB7QK zuP>;Do#vf>d>>SC=0J>TGUWlit38VuA>|S+D5z3LdqMSgGM9jy@}k@KR|4DmJ?YUQ zA*Q?c9&!M{Q0w6H@wR$C29#9&>Bo<63;^C51{}bI{TAaZYRmyoqLE8tbDswr8I#w5 zZ%-y};EyU_i)KQiHYu7xlL$9?3fy)=Pv(_|pw5I#PquHA5wQIo!qW*J4A;N!(HyxY zsy>FxgS;rzK&*ogOH~G_byR6sAM-Kj^l(AHfanFJQa;_e6!mPo3lEdU&ey_u1*Jp) zV-CKrcx@uhg^UgO5GH$Nzpv}SsH~y2BhR84MKpFP&DJxO*iVjLgb%4FIc~B!;VqNH zdJah?JMu@pBSTZm^Ywzz`lkzS$CTdGmpoJ;-B?_?^WBX#=qmh+a6@KPa1*=7l-h{N zKJ(sOv5Az#7?yp`b~oTrPm<f)%{x+)V<$2gM}gwq+8S$H!!y)aI_hrJ8L>hyz~}9o zSVp;%)pfLsjDU=z7nvVs|8OmkEEVMJBi3ohhw<-`?+exy4n%*|GE0kW-@N(rjPI7F z0mwVr%sLe@KYUj&cBsfWBm5n`t=Hvud=lsD?t>A@V!vavj+Q)^me-ODVB1-WARAjE zf}9zpEfuEM4hr$<k6YuITM7wG5$`u$RbpWa(Yk7;KZfx$$JyA-0P<S;$KZfw`ori? z>IQnB3G;{aY>DS@KdvhS%VqHgzkPasYMxieo*?Nzxd0k6RvTW>b9Wr>zS=Cl(C;9+ z&WfHc*hY+JSS|lZ?h%>8vCfVPMb!{$OWM)_k)Xau^KOWbp?#kA52PdX=gg1N^C(v8 z&a1n8b?H+S-=|@&>EjO}oYcd33)Ym=v@&8C+$FB2Tx@4H@*dyMBrh+{HQ?+AYK`1f zCL&G=T|yRmqvC-fQlK}S=he8Euj~;vxELkvh1GC3bQLfJ4Yxj%v2)`l&)G&}1{{;k z+F!z8LGeiAaF)K-_CSfb)IfQws51(ihXL&@vQ^dhvO)a3{T4HBvCv~)ZM&0}Kd350 zeHk=U2!MKG&a3T?^w4frc156gijfadYravhoJlDv63CAqyNlfxVpO9%-jX>U<nD*| z^Jrj+70*hwsWLue4nNV}9uW1-5;#TmaV^Cr;7Z|cs<ZNR29QFf|H8n?y91K7CXfXw zK%GcX;<k&H^1uk$e*YRNRPuWK*$Zi}H8B}nn;MUe^QLo`xUb;0<p-y$227qyQk~l# z8J!)N8?R0b+K>RL(5aL(0mW^_s<s6kK`kaVnRq?#GS4V|UQ<&8?e8)F`hHOPz^ICR z(m(_Y25cUdEJ+L?y2JO6NhxXY9%h&9*7U-mkkS2q_SF!31pcstZC`Ou(NUGQ4#>Ta z-!mJbH2s>R!Sb`~bmzuPHvJZwTpL#l2hSl~n;oOxX~V)!5*H)~J!78&)4N*5u+9!f z=}xz(aDFM#3u!#p6KXWk5HU&po}B&Wz4%N%vh}0WhlPu%>?B7?hb~f@T&uYFWQKg; zXk-5?5Ir&y>n81-*U7D9x+GL~+W1D()BOy9_sU-I?%iF|teSY?hcT3)qvUH@FLFQd zw(VMg7}!)tU2mSC2iaot7%kX8T%X<U_`59V-ND=o5>(b>x0}5G&}Du9v`y33;Zp={ zxYyjOU}ukzQF^MwI$gBXLoIHCaHZ&`iP+?*odBAFLyw+bcY))npEffGzHVl{S(Fxx zL|T&vgT1YjyvjJsTIa0wUdQ#cxQq|5;2?Iy?-K!!$4~O&Zx(d!Uv3viSg|70jzs_x zKj%3rSl*BC?+W;FpP6&{R!W4<w`5Lu-pzm|pXj||XO}6o^wLk62|bTAIB3QV(Bkpn z8%sFv%{3*_B%G=9TN3C)&k48!-WUN;$5lt@e^QO?;M>qMn`y7Y3aDt&GbJmAq;Da* zU}$p)KE6rLsav;PiO$-|QIP`rMKJCk0wq(IXWL&g*~Z%vFpXFQ)HTzA;|>`tKCX(c zV6n%3S;r+GIEmFsZyrO!Vo^D$#^jab1}Vs21F5Qd)Xr?f>P#mMoLtIq6AH9m+nUbw z22VSy9>BL%#gt@tpT<AVD{Yz(Qti-nGBJYHPb{cyH`Ue6YjL#ryTHUd(bn36fqpc5 z*___w!3sc4jGyW$^YGD1(gkLSRXMs&POqG&qsDs|0eTl-5n@_{2XwY6gV&tewk2!b zhd~$dTzs_Ta<8Kxw?2baniWdN6^dpXZgn9JWNc+P9zq>9RBKz$^HY@A9uOg3OlH9| zUUwiAkzyw^jwRKA#`S(KP;PG6ziKm=Q&8ATx_^rJBDt)gw<!P+%W47V{>7WaFtH&Q z=%cMw64}Md1#$&v`d~YwDfKzKXY-}51`lTa2fnTn3a(zn&=pXnx*6TZbJIpM3+N9M zk<!<M4erTP6~A!__oq*}Mn2<T)FaOt{Tv)T3m=M-?sA>OdEjUW$sS6wHQ46O&0f#- zwI<2>Mxxc^0VO^z0X%t34#)<$Jeox^8FpuW!GerkWLnh7IZVXzp-cA+tj^d|#x;b$ zZW*3;vYWR<qTrQap1$I^$ogoO=eo7LZ-W7tay@X%rYl$x<DrlXCUhK@6BEL5McvYI zC11P^-`G#i2k>X5w6}(srkk~iL5)e8EbY7<P+A=#2fsT|0lZ0{k^ve%^0RLRJ##wy zR-K=Kt{ptM)sc>!t;j<IXYt_HEya{OTmoHb0K^Di_jHMcZ9Od6w0}AKGy&)BsUOOQ zb<}`58)Jo%?mjqRP7Gtg;Mwdm^CRm$HTbO74fMFW5oZaL;hNBCFw`pW<ca<a1DSr_ z<b&=6OmawdA-{k~U2r!#67f(L>&%n<?PGAoFo#I@uo2k{#_XE&I8Tm?azD}qzr~-v zDx)Ey@M-eRCC=vev?9#R-Ju=*-HXn7HVRwE^e|jqgJUQ9zb@Y#x7n?`m~)nJFn72+ zH>t<E4R%@po~qWtyNy&*gRIV|II0t+!N#-Hn^*zdVCR{~PHFdwyv9EEoqo<b)hmTB zu<w7I2^5^jjdoXvP7(974d!M=CHO|`OGTpaWWOer>?F^?NWVF7Da(t)zDI-Rn&t_B zb2@!czRDXUB?jnKrr5KZ8f-tF7xrFC$*m}SI26P1xB^z6rW7&rUGt7NIcJO|lgp>U zy3e02-InH5PMy#L?9F(`w|cX?$t5cpPSJ?Z1m;d@)b)T8<BW<dgmp-39=!*6k1AX` z+w_kityU73gyDo%S{t}|OO?+y5@LjEPYCQpojKOac&s@;a7`u4SPL8!^=YSG`rRQb z8UniY9vitqOaJCxI+K|Y(3)6as>Of`S&|A4ksJxtK>4@50iYw~g}clVvniBVrX@oJ zzY+WQmDebRRKHN9@xj=>Y{0hqu%`&H++&o+)&zgtmqYA6b;Tkc0cesc=;ew0s9-|b z5qQ5k`m&c@S`@DFdFnh)T8Ih40u;0vJhe{1NFILC!Ef#8VuZ|t3y$H!E!&Vm<GtPJ zE<+a8B|w0z0R+hBpoCacMZSK)M22ggBT<3tw}7t3EkpfLnnH*b_NMpb!|52=2%ofZ zY#Bd)_ClQAH)8uA^DgyHJ|t+`ROQLoaijL?S5wB%r;eZa(RyOW9a?{%|H#38g_9R9 zJly`m79*?sV11%V5;xuuhCz30+=(wn(swhMyX4#1z7NiwG0IqcTpr9HpFNf!td|bj z+YDk>#Pn}(EDe+_Snm{7VeCwEs;b_jEsmM9Mb+q9-R&^Reb5Pa&g8NVw9&Zw66k;2 z8y7wZvxV^G(DvxrT=ULB+aBkb?>57FZfdoKR!)jC=~*RkXZNPc7gtqZ@8A+AD1cER zeOc~SFkm*U|5@#g1;}|_R17<uHGC%YTuHq8NdcNzy&ROPKQ$a{t-;L#Foz*NFn-`M z32ZMT8QxW_zln>pUt@u7qJT)bUJFn|?t>FsP&}qr8hjxZ;~y;^JW4MPvMN4>L$O)7 zP3H;ZuHH7+n6AjC28S<CJZ^RgmxU``G8~ja+z8{%BLg!4N<0dQ4;)&vOPy_7vuSf3 zA4rXM+Wpkds@b*i{rmETGi!%4XOpmxGNRAtAM(0!c*Mgt<(#;<IC)G8DhjnAd{9<9 zK7qMIp0(_LOY3y@y`4jw$2^cQHpp1HjYw;T@w?k=UnoG8`Fz@x+&>~VrXMVAPo@@Y zKG$@<M|{KFNRqP+*7M=D;+qja)06rQ*Jv<~l--7a>rFFTT0wrQmvUdcNEEw%&Deu1 zBO}GiRjp$V+HMoCI&p(_fB|sA8;s`K*v4jQTInjiLMsO4$&1Tl%+dr07@2IBYg12( z#3!4d3VqO-k-^!O&PD6e^VCc$KPg}RCT)w|$<D^$v7rMAmIs+jvfBf0d9HU$OZ6Qy zO|)sjo*|4DC`Kw5Ud*eIV|Lz#d;qoXP7}^Qzj4M$w&OrDEc!mVvyNhIwYnkOaZcvP zz;1I>RBJlRRGl?SHWhN;3e0O+oT7%3>uI*>7r8PWWFZLt%v1b;OkurN40EaCtuG-+ zkvWBg?=Hug%v8$9r#ZR^l^UK4*EsSW8E~`hha2Yy)Ad*Y9?>G<*n3y6uv!SF<)j>n zDDgQ!NWKwZ%OilkZ9dwQFC*%H&5&n*%Q9FkF{xkMt5pn48A=UE#Fal-OUPHXV7lzm zY$nFi(X&m)(CeNxOOesSDYo5Oa^S@JPnQh3Bcn}m!2FoaJSmBboJZ@;_LY#kBp$Sy zCzYuL;L0+9f<FyV8J@(D=;%r1l^^8kM-8gmQCId~rE$3l0xfjd#4K4390*J(&4vha zDfHFcdU`dh%U#raH2%2DmjSK5IN{B%4Ey`yZQ7|^pXCWplFh}g0txGkAkHrG1pgGN z^i3qvTM}uMw<{&0tTBgMW`W=Fi%G`x*WHpP=?CHr?h1vkB27IPos7_zq{<+!X+$Zv zu<=`gcmaTQ-Ia-s;yBv5v(E0X+u*B811gviW%+2Z5wnUxC<fp*C=fY3=Bk*l-9eb4 zPJag@34k*>gb)svn7F`l>F!gFhqtIQd-BW)AY#~zw<a|%kS7sAb_h3}<O?WYJ`2RC z*TuD7<sT+%*HBqCpZ^!%AoBxCt8&@m{u5VwD=<Hy>#6VLzx$v$5x>vD;G*}-2Hlzc zcP%F>dAgP!P~YFOz2^P$kk_M9rcELFd-dmYmRr!V^Rc2ZUCX%5!L-68C4=Nc7Iy2i zp?9V5=fiunh#Wj1W%$nzn99f3wa=}_u6Ryi_8Oo`<$MX@)>BZ}ql)H>r)CDo=WB-d zX(__?eZ6+r@$=BNu|(@4SCQwk!=U{b5Mx?#^OP((gGvO<BJ~a)*zNbYqK{u?|JJnz z0!Tc@kq<f#0W!{+JA3<un&<+Q5SO^BZ|F5??H{?jRf4I-#ejjk@K_buX<V5|Pe({N zL8R$CwXVb6{H5tP_dHy0p|9eQx(e?4M2-vpcvZf;sNloyz~9NXKAgWZ@x~G8_QnEP zjQv8#hsT+Nys|6c0PC6PNP`U)fii|v#&BD*1^686J}=3$q&Z~>E~%1Zw?gw{@-f6- z23nBraS?EfmC}N`(R99ar;8pgDwycoHs;f9o*$4=nJl3FF!C(JWux+d)zg*#*$uVJ zc%TQSJ!_V2?{^)vwBDa{m8;C^3iUs3zn{;}m)!bbdU?bDQU|#if=$kZ)Q$xI`?lIX zC|Wr?LU77Pan4smK+BZ~y1{*sJj<WO+3JmZ7uS^5ZG!FBDleUdcAv%x=Kz=jYV)<f zZ-hvv`@zD{%Z8=if_>H?zwlo4=0%x)azZL}oT<B5*ndQ8TmtJVgtHYJ-%@>b=hu+R ze_mR?(_|Uw<wxx&95cWu7)rQ~PL$CK7<2B{3oPi#3KRwUH^X~qQuDud=Sk>p+wm|h zGuL4q!<q3#L(CopEolY`C6Cl1E)$B!ijtNmTO0anh@27ZC)Nh2?YS}*Lv^AZyjFB8 zdUaHRjX`~ZVw)p1Dij3co<BM*VJba43SIvZ8-EFjTqy*%b&m|q!T8f;+_S_R@Vo!S z<2nC^$9rVD#)}@dwXR%N$^#2J_S7ZeOV!e)nI7fs{wS>Q@CRD0!lZUW0YIuzK<>ho zEO+rIAisO<7a*^Uc>mu4`Du8cnTM-#Zrc$H_G~*)EkI}9`iCPXqh02Hv6f1$44r)z ze?m|HxSeSxZh^(?rPy}+I=S>-uT;PDX7ay)*w1Ywms~0AxxEJ`ehGBA_0<3cr7CyK zt^5a_#9Vay9-_EleB6N}c4j2j-cN4nDUYIwD_ant7$7K%tl9h*BulLRFG%*(kffF_ zwm~`)-J(zyGGZ|5_e2-(_B`Lon|-TWP7h-jxG;M>HAiIbo${^QbLo@8Cf(N#*m#w4 zk9D5osYV7(n5d~a`+WV~3nZ6po6&8iG~`9K{zMI2Ao<9EX9=tvJ|lh!uQCy5hr4%9 z_u<PPAJTA7zBo%sQ*zShZtgCZg0Zm+pp9aCu`nT=-I~DHsEe%bPC)DNmDPfwJvK7S z{55gDS}9tBASxYH2FNl%I4CEMc|>n!^w?}S(`Wbf{z$T7hZ`^@%d`FFD&9x>w}2X> zdz{Q4fErfDc=7MTHGf%tKl{Dp{~ZFp1!-5i$FHc9BgN+16hI8_i`%}7kXopUg6w?< zAjaD<9ba4;ZY~P2G-7{had^3<+VVzsIbg~(086OAJfLK;LBie#khPaqL9-_#Y<bgf zL#ZZ<zH10%$6%PaIum6iT8uqo>|Pxp(h4Nrq?}c_HQogMIkov~OZ?Yo`rDUKBsry7 zD9qJ94VD+(QOK(*!0xhai)(7k`y!KBu+872k4y&AEKnyB(q*FD3HS^E6$oq@AKu2b z7-5zsYPV!30zlH`>324XH!ua{Da$8u>C4hU5yv6!(RPHs$5t9T99>bsCdJImVs>K+ z|Fuz!lL!XfF9^B#7oFeEt~kGqtpKA=kOfbm3kF&asR)eE0qd=%&>$05IxYEsig@IN z$9Er)foH1N`}{)(*%AgTnyGSxTzc~sba&eFVG2*=9fy5OzqX)r3zm*O28VSKF%32i z)pzxBF}0DoIoi*!-wJ-6*_d5YZ};~S0qr|7S%Aj}Rbjj}a+1y~=mnn7>HMQiu;5Go z*)RRa^+1RKpK5yY(IvbtS+Bl6-sYdhPJW#Y@d_YjS$(cnf(DQu)yU0Uj=w#_9lk7I z29{RV>(bt@q?JL^W<s4S@vDH?;phLghJii?*ojOEBDrMVCf@Kh>yX0lJOn^j;v=Vr zopbl>QDiO2C}TcgI`oh4NB$AjUjlStL3V=RdNC1atHgfIiu}_F>C2`EqEfJzXAcen zw%Ob<G6&*6rNDoF_XQ33tZyGMp1Ae|96VMR-6ekWBI&;aam}jw4{D&nVAcLS4)Mzt z`XAr+i~>05KC{y8X{863cuEc-{d-qPMdJs;*j$ta*?i&D(x5r%_g?4w0;u~jU3%{4 zdxb1S@=P@uSRee;?fjLY7=v3=eEt*~yiCFCM~~a@y^ixPcmVQWKNxc!It`xw>GpAk zKX3Lwye+5BV@~F*mkMCTrm1mwyRiS>>t37ypYy2Wg%dZgffZ}D&w1^iDuO?MFZsBr zvQD5p!oRIr$|Kx)ssHcq!t!PI;R!GzaxJ@s`}dB;$Flqf`1A{#-@SXsCoSD~*VL5% z{Q2sHgaqm>jR<$XV|tpv$E862TltB$Ww7V0*Tqy`9s6^U|L0BD-2zUP>9HH{H`6r1 z?h~Zn`O5!tY5>R@94q^8_+Gm59-I$*5|e*h%U*_jtgup!mA~I<N@V!kG4!u5|9_4Q z{;d<We{uo-vIYOP!6|`$=et7*^#A_ePy+qm58;2^r~myx|9@e+{lmv)x_i&AT{KkP z+eWzcUFR05(PDCscTrK(?4#$D{r7(nrVh{-R?|6mI=(hcRW#&3|M1V>GjQO7!|F>* zD*4RuA8fb({crv6Z<umabr|*X)0zF?6;H8||NUD#eJCT@xAnJ`!TZ2!W*_~hPyg$e z$p$?>qYYy`uDI`l16O;)xg9R`zrXVjaM|8>b!FdLOL*5X?DRSQ^$IH*#v-eP?3;43 zZ+So1o&S%w^w+D(nN^498QQ@6w9P?d|M|YEo{g`CGx*CN1FzWcEVO^eC-$!oRr>f$ zMBMx1s>4yi{d52N=baw5?<w#EqAu{gqgNePN{Lqd=SRo+otCj^<8%JwGhI#_!QB6R zU)#YG=(uk3_9=KEazy2SessHh1><W+xRKy}kVCGL|9oHL6=Z?FI9=d5@Ia1D+&}iu zk8YnQmArt=CI0wYVYafN-?*=oEkW55JMRt3mY_t5oen}ul%Pb3og+OZaiSznJH-`B z;zX$>c20gNwFIS>*eR}1%4<q_y>p#SDX%Gr(@t@Pf;dqSr~iN&Qb1S=2)o1bpn$NH zzQj&l1`us1eTje9m-t*Gx%MX);D2;2C_M^F+ir)BAEj+aY1{pe^WtA?h0@8Ubh39^ z9+XZtrIWo=$AO+g?x66Ub~-p{D4lFdCwr%k1E(ydlTGPl?-W-kooq@cd#8?r>|;tN zo6^bNDXvgD*_2K;rIY=aJ3!eIlr8a>1@V`HjY96AkUMrtwJ78c3b|v4?mfA3qmVl& z<c=MdM?7W1?*I7EX@IY3?4Mi!$^hz4<5YlRLYcOsOxx|WJSaU1N{?bEEQ!*ipvV;b zrB?n+okZzTP<j-9SrGrCQ-MW8=}}O66g$Ng3Lr}XWGR5`U+w^9OHj7NUlzn)@-9k` zg3_bdDb=F%C@4LO9YE+EdK3eAwCR~$#wYgN-MHg=gbHVV`X<WBbLZ2CidvXjE;C94 z=o@nWuIAkX+Nb(kK=TgRLT#}BmcAjqLq`l*-|+PBYTog34$lM4yQlhXq?O;(H++*e zO4c{r_q&>R`c$VQfaV?NaFle}@97&p)fY}C>l^;I3?$vYq75JedAe(HRqD6&4LOHV z;$(e8x!;w6)RwIs0Wy&LijYmSzo&0_TDyS<=o`}it_)-$wVZ$tkb$ff_VRxHTl$9k zimX(~`i5_Q7hhqbcUT27kaC&h3m(6xZ&(X=B<mYK{aqQz%*Su)fea+Q11zrp_w)@Z zTjIAQKPg*+vL$xPT_{oF_Zm}_DDhij!IUWRTVlcgFD6dPw9XE@b{$75UcajOpE6l; zrmT9Fl0;FGsGX!YeE(nE9+WNd7d-9He59NbG5)`e7?dqR*%E(}qEe1h&?gG|v=fR- zi4wm@WuPQZzvatA0c3w`YJdXB{yY7<{}Hn(J&NDbyrc9eeoNqs0?1MT*_|~>C~Z4R oCwr%|d4STR_`M#*52<1IJ>CYvSy_snyTE^n@+#Le<&6FQ7p2K6?EnA( diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.tsx index cfc6e8af97..4a5c1b9bff 100644 --- a/plugins/fossa/src/components/FossaPage/FossaPage.tsx +++ b/plugins/fossa/src/components/FossaPage/FossaPage.tsx @@ -22,6 +22,7 @@ import { import { Content, Header, + Link, Page, StatusError, StatusOK, @@ -63,6 +64,7 @@ const columns: TableColumn<FossaRow>[] = [ title: 'Name', field: 'resolved.name', highlight: true, + width: 'auto', render: ({ entity }) => ( <EntityRefLink entityRef={entity} defaultKind="Component" /> ), @@ -70,7 +72,6 @@ const columns: TableColumn<FossaRow>[] = [ { title: 'Owner', field: 'resolved.ownedByRelationsTitle', - highlight: true, render: ({ resolved }) => ( <EntityRefLinks entityRefs={resolved.ownedByRelations} @@ -146,6 +147,16 @@ const columns: TableColumn<FossaRow>[] = [ ); }, }, + { + sorting: false, + render: ({ resolved: { loading, details } }) => { + if (loading) { + return <Skeleton animation="pulse" />; + } + + return details && <Link to={details.projectUrl}>View in FOSSA</Link>; + }, + }, ]; const filters: TableFilter[] = [ From 776b92721fc769b7ed26436ceb0a8f9e9dd1525b Mon Sep 17 00:00:00 2001 From: Dominik Henneke <dominik.henneke@sda-se.com> Date: Tue, 20 Apr 2021 17:10:48 +0200 Subject: [PATCH 033/262] Update changeset Signed-off-by: Dominik Henneke <dominik.henneke@sda-se.com> --- .changeset/unlucky-starfishes-vanish.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.changeset/unlucky-starfishes-vanish.md b/.changeset/unlucky-starfishes-vanish.md index 90ee10a81a..3bb341bee9 100644 --- a/.changeset/unlucky-starfishes-vanish.md +++ b/.changeset/unlucky-starfishes-vanish.md @@ -3,19 +3,4 @@ --- Add a `FossaPage` that shows the license compliance status of all components in the catalog. -This is an optional component that can be registered as a route: - -```diff -// packages/app/src/App.tsx - -+ import { FossaPage } from '@backstage/plugin-fossa'; - -// ... - - const routes = ( - <FlatRoutes> - // ... -+ <Route path="/fossa" element={<FossaPage />} /> - </FlatRoutes> - ); -``` +See the projects `Readme` on how to use it. From e669a8013f9013e73bdae27cca29274ec99a6e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Tue, 20 Apr 2021 13:50:42 +0200 Subject: [PATCH 034/262] update the standalone frontend contribs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .github/styles/vocab.txt | 1 + contrib/docker/frontend-with-nginx/Dockerfile | 18 ------ .../Dockerfile.dockerbuild | 59 +++++++++++++++++++ .../frontend-with-nginx/Dockerfile.hostbuild | 41 +++++++++++++ contrib/docker/frontend-with-nginx/README.md | 16 +++++ .../docker/multi-stage-frontend/Dockerfile | 23 -------- contrib/docker/multi-stage-frontend/README.md | 19 ------ docs/deployment/docker.md | 2 +- 8 files changed, 118 insertions(+), 61 deletions(-) delete mode 100644 contrib/docker/frontend-with-nginx/Dockerfile create mode 100644 contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild create mode 100644 contrib/docker/frontend-with-nginx/Dockerfile.hostbuild create mode 100644 contrib/docker/frontend-with-nginx/README.md delete mode 100644 contrib/docker/multi-stage-frontend/Dockerfile delete mode 100644 contrib/docker/multi-stage-frontend/README.md diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 226af9bf0a..432cd19f25 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -16,6 +16,7 @@ Config Debounce Discoverability Dockerfile +dockerfiles Dockerize Docusaurus Env diff --git a/contrib/docker/frontend-with-nginx/Dockerfile b/contrib/docker/frontend-with-nginx/Dockerfile deleted file mode 100644 index a444c9de83..0000000000 --- a/contrib/docker/frontend-with-nginx/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM nginx:mainline - -# The purpose of this image is to serve the frontend app content separately. -# By default the Backstage backend uses the app-backend plugin to serve the -# app from the backend itself, but it may be desirable to move the frontend -# content serving to a separate deployment, in which case this image can be used. - -# This dockerfile requires the app to be built on the host first, as it -# simply copies in the build output into the image. - -RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/* - -COPY packages/app/dist /usr/share/nginx/html -COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template -COPY docker/run.sh /usr/local/bin/run.sh -CMD run.sh - -ENV PORT 80 diff --git a/contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild b/contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild new file mode 100644 index 0000000000..dda9779eb0 --- /dev/null +++ b/contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild @@ -0,0 +1,59 @@ +# The purpose of this image is to serve the frontend app content separately. +# By default the Backstage backend uses the app-backend plugin to serve the +# app from the backend itself, but it may be desirable to move the frontend +# content serving to a separate deployment, in which case this image can be +# used. + +# This dockerfile also performs the build first inside docker. This may come +# with a build time impact, but is sometimes desirable. If you want to run the +# build on the host instead, use the file simply named Dockerfile in this folder +# instead. + +# USAGE: +# +# - Copy this file and the "docker" folder from this directory to your project +# root +# +# - Update your .dockerignore, make sure that the source folders are not +# excluded, but do exclude node_modules and build artifacts: +# +# .git +# node_modules +# packages/*/dist +# packages/*/node_modules +# plugins/*/dist +# plugins/*/node_modules +# +# - Update the copy of this file to add configuration arguments to the "build" +# command, for example: +# +# RUN yarn workspace app build --config <config1> --config <config2> ... +# +# - In your project root, run: +# +# docker build -t backstage-frontend -f Dockerfile.dockerbuild . + + + +FROM node:14-buster AS build + +RUN mkdir /app +COPY . /app +WORKDIR /app + +RUN yarn install +RUN yarn workspace app build + + + +FROM nginx:mainline + +RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/* + +COPY --from=build /app/packages/app/dist /usr/share/nginx/html +COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template +COPY docker/run.sh /usr/local/bin/run.sh + +CMD run.sh + +ENV PORT 80 diff --git a/contrib/docker/frontend-with-nginx/Dockerfile.hostbuild b/contrib/docker/frontend-with-nginx/Dockerfile.hostbuild new file mode 100644 index 0000000000..6e5912dd67 --- /dev/null +++ b/contrib/docker/frontend-with-nginx/Dockerfile.hostbuild @@ -0,0 +1,41 @@ +# The purpose of this image is to serve the frontend app content separately. +# By default the Backstage backend uses the app-backend plugin to serve the +# app from the backend itself, but it may be desirable to move the frontend +# content serving to a separate deployment, in which case this image can be +# used. + +# This dockerfile requires the app to be built on the host first, as it +# simply copies in the build output into the image. If you want to also perform +# the build itself inside docker, use Dockerfile.build in this folder instead. + + +# USAGE: +# +# - Copy this file and the "docker" folder from this directory to your project +# root +# +# - Add the following line to your .dockerignore to make sure that the built +# frontend actually can be transferred into the docker image: +# +# !packages/app/dist +# +# - In your project root, run: +# +# yarn install +# yarn tsc +# yarn build --config <config1> --config <config2> ... +# docker build -t backstage-frontend -f Dockerfile.hostbuild . + + + +FROM nginx:mainline + +RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/* + +COPY packages/app/dist /usr/share/nginx/html +COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template +COPY docker/run.sh /usr/local/bin/run.sh + +CMD run.sh + +ENV PORT 80 diff --git a/contrib/docker/frontend-with-nginx/README.md b/contrib/docker/frontend-with-nginx/README.md new file mode 100644 index 0000000000..eae70b8bba --- /dev/null +++ b/contrib/docker/frontend-with-nginx/README.md @@ -0,0 +1,16 @@ +# Frontend with NGINX + +This folder contains Docker images that let you run the Backstage frontend as +a separate image, rather than having it served through the `app-backend` plugin +from the backend. + +Note that when running the frontend like this, the app configuration becomes +embedded into the actual static JavaScript files at build time. This means that +you will have to supply the list of configuration files as part of the command +line at build. + +## Usage + +There are two variants: one that builds inside Docker, and one that builds on +the host. See the comments at the top of the individual dockerfiles for usage +instructions. diff --git a/contrib/docker/multi-stage-frontend/Dockerfile b/contrib/docker/multi-stage-frontend/Dockerfile deleted file mode 100644 index 3190687c52..0000000000 --- a/contrib/docker/multi-stage-frontend/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM node:12-buster AS build - -RUN mkdir /app -COPY . /app -WORKDIR /app - -RUN yarn install -RUN yarn workspace example-app build - -# Contruct backstage-frontend image -FROM nginx:mainline - -RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/* - -# Copy from build stage -COPY --from=build /app/packages/app/dist /usr/share/nginx/html - -COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template -COPY docker/run.sh /usr/local/bin/run.sh - -CMD run.sh - -ENV PORT 80 diff --git a/contrib/docker/multi-stage-frontend/README.md b/contrib/docker/multi-stage-frontend/README.md deleted file mode 100644 index b6ae4fdc6c..0000000000 --- a/contrib/docker/multi-stage-frontend/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Standalone Dockerfile for frontend - -This directory contains the resources which will help you build backstage without any requirements -other than docker itself. It uses a multi-stage Dockerfile to build and ship backstage. - -## Usage - -You can simply run the following command to build backstage. - -``` -# Make sure you are in the root directory of backstage then run -docker build -t backstage-frontend -f ./contrib/docker/multi-stage-frontend/Dockerfile . -``` - -After a successful build, You can simply run backstage frontend with the following command. - -``` -docker run -it --rm -p 3080:80 backstage-frontend -``` diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index ef178b2977..383cf0615a 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -232,7 +232,7 @@ package, which is done as follows: Once the `app-backend` is removed from the backend, you can use your favorite static file serving method for serving the frontend. An example of how to set up an NGINX image is available in the -[contrib folder in the main repo](https://github.com/backstage/backstage/blob/master/contrib/docker/frontend-with-nginx/Dockerfile) +[contrib folder in the main repo](https://github.com/backstage/backstage/blob/master/contrib/docker/frontend-with-nginx) Note that if you're building a separate docker build of the frontend you probably need to adjust `.dockerignore` appropriately. Most likely by making From f6b8cf96cacda208834e593835eda06a3906d05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Tue, 20 Apr 2021 19:43:39 +0200 Subject: [PATCH 035/262] fix according to designer input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- packages/theme/src/themes.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index b6810d9a84..94cf38656e 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -102,7 +102,8 @@ export const darkTheme = createTheme({ }, }, primary: { - main: '#8CB4E5', + main: '#9CC9FF', + dark: '#82BAFD', }, secondary: { main: '#FF88B2', @@ -111,7 +112,7 @@ export const darkTheme = createTheme({ info: '#2E77D0', error: '#E22134', text: '#FFFFFF', - link: '#FDFB9F', + link: '#000000', }, border: '#E6E6E6', textContrast: '#FFFFFF', @@ -124,8 +125,8 @@ export const darkTheme = createTheme({ errorText: '#CA001B', infoText: '#004e8a', warningText: '#000000', - linkHover: '#FFED51', - link: '#FDFB9F', + linkHover: '#82BAFD', + link: '#9CC9FF', gold: yellow.A700, navigation: { background: '#424242', From 4792df9e789dd28ba0d45cae1833565e06753b3b Mon Sep 17 00:00:00 2001 From: Rian Bogle <rian.bogle@ncendo.com> Date: Sat, 20 Feb 2021 09:58:51 -0700 Subject: [PATCH 036/262] AWS Fargate and Aurora MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .github/styles/vocab.txt | 1 + docs/deployment/fargate.md | 21 +++++++++++++++++++++ docs/deployment/helm.md | 4 +--- microsite/sidebars.json | 3 ++- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 docs/deployment/fargate.md diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 7d0f36d858..4f3377de92 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -21,6 +21,7 @@ Dockerize Docusaurus Env Expedia +Fargate Figma Firekube Fiverr diff --git a/docs/deployment/fargate.md b/docs/deployment/fargate.md new file mode 100644 index 0000000000..eff8a7d570 --- /dev/null +++ b/docs/deployment/fargate.md @@ -0,0 +1,21 @@ +--- +id: fargate +title: Deploying with AWS Fargate and Aurora +sidebar_label: AWS +description: How to deploy Backstage on AWS Fargate and Aurora +--- + +There are any number of ways to deploy backstage containers on AWS. One of the +simplest from a management and ops perspective is to leverage AWS Fargate and +Aurora PostgreSQL, where both the container orchestration and database clusters +are AWS managed services. + +However, to use them properly there are a large number of supporting resources +(VPCs, Security Groups, Load Balancers, Certificate, etc) required. One approach +is to use [AWS Cloud Development Kit (CDK)](https://aws.amazon.com/cdk/) to +simplify and automate the creation of the entire infrastructure stack along with +automating the build and deploy of the container. + +Check out the [Backstage On AWS](https://github.com/rbogle/backstage-on-aws) +repository, for a ready to use CDK application for deploying your custom +Backstage app onto AWS ECS Fargate and Aurora. diff --git a/docs/deployment/helm.md b/docs/deployment/helm.md index fd36aeb81f..cbfcb1bc57 100644 --- a/docs/deployment/helm.md +++ b/docs/deployment/helm.md @@ -1,12 +1,10 @@ --- id: helm -title: Deploying Backstage with Helm +title: Deploying with Helm description: How to deploy Backstage with Helm and Kubernetes sidebar_label: Helm --- -# Helm charts - An example Backstage app can be deployed in Kubernetes using the [Backstage Helm charts](https://github.com/backstage/backstage/tree/master/contrib/chart/backstage). diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 1ab242ba2d..ab7e530479 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -206,7 +206,8 @@ "deployment/docker", "deployment/k8s", "deployment/helm", - "deployment/heroku" + "deployment/heroku", + "deployment/fargate" ], "Designing for Backstage": [ "dls/design", From d367f63b53943462f458e8c8178b77b0d63215d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Mar 2021 08:26:26 +0000 Subject: [PATCH 037/262] chore(deps): bump helmet from 4.0.0 to 4.4.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [helmet](https://github.com/helmetjs/helmet) from 4.0.0 to 4.4.1. - [Release notes](https://github.com/helmetjs/helmet/releases) - [Changelog](https://github.com/helmetjs/helmet/blob/main/CHANGELOG.md) - [Commits](https://github.com/helmetjs/helmet/compare/v4.0.0...v4.4.1) Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .changeset/grumpy-games-shop.md | 5 +++++ .../src/service/lib/ServiceBuilderImpl.ts | 11 ++--------- yarn.lock | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) create mode 100644 .changeset/grumpy-games-shop.md diff --git a/.changeset/grumpy-games-shop.md b/.changeset/grumpy-games-shop.md new file mode 100644 index 0000000000..7426786f89 --- /dev/null +++ b/.changeset/grumpy-games-shop.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +remove use of deprecated type HelmetOptions diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index 07da975184..c17545779a 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -18,7 +18,7 @@ import { Config } from '@backstage/config'; import compression from 'compression'; import cors from 'cors'; import express, { Router } from 'express'; -import helmet, { HelmetOptions } from 'helmet'; +import helmet from 'helmet'; import * as http from 'http'; import stoppable from 'stoppable'; import { Logger } from 'winston'; @@ -195,14 +195,7 @@ export class ServiceBuilderImpl implements ServiceBuilder { }); } - private getOptions(): { - port: number; - host: string; - logger: Logger; - corsOptions?: cors.CorsOptions; - httpsSettings?: HttpsSettings; - helmetOptions: HelmetOptions; - } { + private getOptions() { return { port: this.port ?? DEFAULT_PORT, host: this.host ?? DEFAULT_HOST, diff --git a/yarn.lock b/yarn.lock index 370f3f5a7f..6cc6ab938d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14929,9 +14929,9 @@ headers-utils@^1.2.0: integrity sha512-4/BMXcWrJErw7JpM87gF8MNEXcIMLzepYZjNRv/P9ctgupl2Ywa3u1PgHtNhSRq84bHH9Ndlkdy7bSi+bZ9I9A== helmet@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/helmet/-/helmet-4.0.0.tgz#34c187894ed001834f997c688f2b2df19846b193" - integrity sha512-HyoRKKHhWhO6+EBfgRLkuZR4/+NXc1nJB7x0bWwW89i9eoPciK0qUqyZNOA/zowpgrW9C4+J5toqMkZrpBOlkg== + version "4.4.1" + resolved "https://registry.npmjs.org/helmet/-/helmet-4.4.1.tgz#a17e1444d81d7a83ddc6e6f9bc6e2055b994efe7" + integrity sha512-G8tp0wUMI7i8wkMk2xLcEvESg5PiCitFMYgGRc/PwULB0RVhTP5GFdxOwvJwp9XVha8CuS8mnhmE8I/8dx/pbw== hex-color-regex@^1.1.0: version "1.1.0" From c713442c3030717184d9d51900ec6a775a56a44c Mon Sep 17 00:00:00 2001 From: Tim Hansen <timbonicus@gmail.com> Date: Tue, 20 Apr 2021 14:16:13 -0600 Subject: [PATCH 038/262] Datadog RUM minor doc cleanup Signed-off-by: Tim Hansen <timbonicus@gmail.com> --- docs/integrations/datadog-rum/installation.md | 28 +++++++++++-------- microsite/sidebars.json | 5 ++++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/docs/integrations/datadog-rum/installation.md b/docs/integrations/datadog-rum/installation.md index 50ebe722be..f96298a33b 100644 --- a/docs/integrations/datadog-rum/installation.md +++ b/docs/integrations/datadog-rum/installation.md @@ -3,28 +3,32 @@ id: installation title: Datadog RUM Installation sidebar_label: Installation # prettier-ignore -description: Adding Datadog RUM to Your App +description: Adding Datadog Real User Monitoring (RUM) to Your App --- -There is a basic [Datadog](https://docs.datadoghq.com/real_user_monitoring/) +Datadog Real User Monitoring (RUM) allows you to visualize and analyze the +real-time performance and user journeys of your application's individual users. +This is an option to profile and monitor the user experience of your Backstage +installation. + +There is a basic [Datadog RUM](https://docs.datadoghq.com/real_user_monitoring/) integration built into Backstage. You can enable it by adding the following to -your app configuration: +your `app-config.yaml`: ```yaml app: datadogRum: clientToken: '123456789' applicationId: qwerty - # site: # datadoghq.eu default = datadoghq.com - # env: # optional + # site: datadoghq.eu + # env: 'staging' ``` -Replace the clientToken and applicationId with the ones generated for you -Datadog. +The `clientToken` and `applicationId` are generated from the Datadog RUM page +following +[these instructions](https://docs.datadoghq.com/real_user_monitoring/browser/). -optional arguments: +There are two optional arguments: -``` -site: datadoghq.eu # default equals datadoghq.com -env: dev # allow to specify the environment -``` +- `site`: The Datadog site of your organization; defaults to `datadoghq.com` +- `env`: The application environment for Datadog events (no default) diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 1ab242ba2d..e2a57bd426 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -109,6 +109,11 @@ "integrations/bitbucket/discovery" ] }, + { + "type": "subcategory", + "label": "Datadog", + "ids": ["integrations/datadog-rum/installation"] + }, { "type": "subcategory", "label": "GitHub", From 68f3e891b8947f91b5f3d101d60a915fad8691df Mon Sep 17 00:00:00 2001 From: Tim Hansen <timbonicus@gmail.com> Date: Tue, 20 Apr 2021 14:36:19 -0600 Subject: [PATCH 039/262] Move Fargate doc to contrib Signed-off-by: Tim Hansen <timbonicus@gmail.com> --- .../docs/tutorials/aws-fargate-deployment.md | 7 +------ docs/deployment/index.md | 4 +++- microsite/sidebars.json | 3 +-- 3 files changed, 5 insertions(+), 9 deletions(-) rename docs/deployment/fargate.md => contrib/docs/tutorials/aws-fargate-deployment.md (84%) diff --git a/docs/deployment/fargate.md b/contrib/docs/tutorials/aws-fargate-deployment.md similarity index 84% rename from docs/deployment/fargate.md rename to contrib/docs/tutorials/aws-fargate-deployment.md index eff8a7d570..bc530441c6 100644 --- a/docs/deployment/fargate.md +++ b/contrib/docs/tutorials/aws-fargate-deployment.md @@ -1,9 +1,4 @@ ---- -id: fargate -title: Deploying with AWS Fargate and Aurora -sidebar_label: AWS -description: How to deploy Backstage on AWS Fargate and Aurora ---- +# Deploying Backstage with AWS Fargate and Aurora There are any number of ways to deploy backstage containers on AWS. One of the simplest from a management and ops perspective is to leverage AWS Fargate and diff --git a/docs/deployment/index.md b/docs/deployment/index.md index db4ceca6f1..86ad03d1ae 100644 --- a/docs/deployment/index.md +++ b/docs/deployment/index.md @@ -30,7 +30,9 @@ There is also an example of deploying on [Heroku](heroku.md), which only requires the first two steps. An example of deploying Backstage with a [Helm chart](helm.md), a common pattern -in AWS, is also available. +in AWS, is also available. There is also a contrib guide to deploying Backstage +with +[AWS Fargate and Aurora PostgreSQL](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-fargate-deployment.md) Please consider contributing other deployment guides if you get Backstage set up on common infrastructure, it would be a great benefit to the community. diff --git a/microsite/sidebars.json b/microsite/sidebars.json index ab7e530479..1ab242ba2d 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -206,8 +206,7 @@ "deployment/docker", "deployment/k8s", "deployment/helm", - "deployment/heroku", - "deployment/fargate" + "deployment/heroku" ], "Designing for Backstage": [ "dls/design", From 29a7e4be8538f6d6bc909586cbf4db338a270d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?W=C3=A9dney=20Yuri=20Lima?= <wedneyyuri@gmail.com> Date: Tue, 20 Apr 2021 19:45:18 -0300 Subject: [PATCH 040/262] allow import from HTTP repositories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Wédney Yuri Lima <wedneyyuri@gmail.com> --- .changeset/giant-onions-obey.md | 5 +++++ .../StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx | 4 +++- .../src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 .changeset/giant-onions-obey.md diff --git a/.changeset/giant-onions-obey.md b/.changeset/giant-onions-obey.md new file mode 100644 index 0000000000..fbf9faa0a3 --- /dev/null +++ b/.changeset/giant-onions-obey.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +allow import from HTTP repositories diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx index bfb2434926..3e918db419 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx @@ -127,7 +127,9 @@ describe('<StepInitAnalyzeUrl />', () => { expect(catalogImportApi.analyzeUrl).toBeCalledTimes(0); expect(onAnalysisFn).toBeCalledTimes(0); expect(errorApi.post).toBeCalledTimes(0); - expect(getByText('Must start with https://.')).toBeInTheDocument(); + expect( + getByText('Must start with http:// or https://.'), + ).toBeInTheDocument(); }); it('should analyze single location', async () => { diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx index a33fe388d8..49bd776db5 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx @@ -132,8 +132,8 @@ export const StepInitAnalyzeUrl = ({ validate: { httpsValidator: (value: any) => (typeof value === 'string' && - value.match(/^https:\/\//) !== null) || - 'Must start with https://.', + value.match(/^http[s]?:\/\//) !== null) || + 'Must start with http:// or https://.', }, })} required From fa1d892930def809a35735231513565c8dab85eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Apr 2021 04:05:50 +0000 Subject: [PATCH 041/262] chore(deps-dev): bump @types/morgan from 1.9.1 to 1.9.2 Bumps [@types/morgan](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/morgan) from 1.9.1 to 1.9.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/morgan) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 85d67f4ed8..e0ab932286 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6281,9 +6281,9 @@ "@types/node" "*" "@types/morgan@^1.9.0": - version "1.9.1" - resolved "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.1.tgz#6457872df95647c1dbc6b3741e8146b71ece74bf" - integrity sha512-2j5IKrgJpEP6xw/uiVb2Xfga0W0sSVD9JP9t7EZLvpBENdB0OKgcnoKS8IsjNeNnZ/86robdZ61Orl0QCFGOXg== + version "1.9.2" + resolved "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.2.tgz#450f958a4d3fb0694a3ba012b09c8106f9a2885e" + integrity sha512-edtGMEdit146JwwIeyQeHHg9yID4WSolQPxpEorHmN3KuytuCHyn2ELNr5Uxy8SerniFbbkmgKMrGM933am5BQ== dependencies: "@types/node" "*" From d56c915b4389379a85ff302f9187f0681895e8c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Apr 2021 04:08:51 +0000 Subject: [PATCH 042/262] chore(deps): bump @types/yup from 0.29.8 to 0.29.11 Bumps [@types/yup](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/yup) from 0.29.8 to 0.29.11. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/yup) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 85d67f4ed8..e0d58b2bd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6933,9 +6933,9 @@ integrity sha512-/emrKCfQMQmFCqRqqBJ0JueHBT06jBRM3e8OgnvDUcvuExONujIk2hFA5dNsN9Nt41ljGVDdChvCydATZ+KOZw== "@types/yup@^0.29.8": - version "0.29.8" - resolved "https://registry.npmjs.org/@types/yup/-/yup-0.29.8.tgz#83db15735987db9fe5a38772a0fb9500e3c5bf39" - integrity sha512-MBSp62AjB1KrSOI3gX9GekddXU5YYQAVA93+aSl78biBqoSzxg876aQY2KJK5Gnfbpqq7O2cadVX5kPAtBqIXw== + version "0.29.11" + resolved "https://registry.npmjs.org/@types/yup/-/yup-0.29.11.tgz#d654a112973f5e004bf8438122bd7e56a8e5cd7e" + integrity sha512-9cwk3c87qQKZrT251EDoibiYRILjCmxBvvcb4meofCmx1vdnNcR9gyildy5vOHASpOKMsn42CugxUvcwK5eu1g== "@types/zen-observable@^0.8.0": version "0.8.2" From 4d3cbd860131e0e9eedd5ba1696d72568c2b6efc Mon Sep 17 00:00:00 2001 From: Dominik Henneke <dominik.henneke@sda-se.com> Date: Wed, 21 Apr 2021 09:12:39 +0200 Subject: [PATCH 043/262] Update test Signed-off-by: Dominik Henneke <dominik.henneke@sda-se.com> --- plugins/fossa/package.json | 1 - plugins/fossa/src/components/getProjectName.test.ts | 9 ++------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 39da3638ec..2f656c476a 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -52,7 +52,6 @@ "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", - "@testing-library/react-hooks": "^3.4.2", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", diff --git a/plugins/fossa/src/components/getProjectName.test.ts b/plugins/fossa/src/components/getProjectName.test.ts index 461cb18ed7..93f5187890 100644 --- a/plugins/fossa/src/components/getProjectName.test.ts +++ b/plugins/fossa/src/components/getProjectName.test.ts @@ -15,7 +15,6 @@ */ import { Entity } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; import { getProjectName } from './getProjectName'; describe('getProjectName', () => { @@ -31,9 +30,7 @@ describe('getProjectName', () => { }, }; - const { result } = renderHook(() => getProjectName(entity)); - - expect(result.current).toBe('test'); + expect(getProjectName(entity)).toBe('test'); }); it('should return undefined', async () => { @@ -45,8 +42,6 @@ describe('getProjectName', () => { }, }; - const { result } = renderHook(() => getProjectName(entity)); - - expect(result.current).toBeUndefined(); + expect(getProjectName(entity)).toBeUndefined(); }); }); From 5f41b3e09fae8cfd73c6238a0122fb926f8c7306 Mon Sep 17 00:00:00 2001 From: ImgBotApp <ImgBotHelp@gmail.com> Date: Wed, 21 Apr 2021 08:23:28 +0000 Subject: [PATCH 044/262] [ImgBot] Optimize images /plugins/fossa/docs/fossa-overview.png -- 329.99kb -> 182.82kb (44.6%) Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com> --- plugins/fossa/docs/fossa-overview.png | Bin 337907 -> 187210 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/plugins/fossa/docs/fossa-overview.png b/plugins/fossa/docs/fossa-overview.png index 6298fb95573dea5f3121ade63e2e8814f84d2b98..3e9482ab55d15288e982eda06420b05f8cb404c8 100644 GIT binary patch literal 187210 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 literal 337907 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%0AAc(J^cD8p9C7pdp5P@7EA%Uc8ZuYkS#qT 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%0AZuyp*Z+WiWZ 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%0Dt|9TTkZlAek&#?-tqAU#E&{inlAFF9a7&NI;;| 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 VZXV%{;0EBw(#+;K!Suql{{jc5CQ<+Z From 50ce875a05389367a8e40be33d0d762564c9d925 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 21 Apr 2021 12:13:20 +0200 Subject: [PATCH 045/262] core-api: fixed confusion around wrong error thrown from routable extensions Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/strong-houses-lick.md | 6 ++++++ packages/core-api/src/extensions/extensions.tsx | 15 +++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 .changeset/strong-houses-lick.md diff --git a/.changeset/strong-houses-lick.md b/.changeset/strong-houses-lick.md new file mode 100644 index 0000000000..9739bdfda1 --- /dev/null +++ b/.changeset/strong-houses-lick.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-api': patch +'@backstage/core': patch +--- + +Fixed a potentially confusing error being thrown about misuse of routable extensions where the error was actually something different. diff --git a/packages/core-api/src/extensions/extensions.tsx b/packages/core-api/src/extensions/extensions.tsx index 8ff4055e61..9f6412f960 100644 --- a/packages/core-api/src/extensions/extensions.tsx +++ b/packages/core-api/src/extensions/extensions.tsx @@ -47,12 +47,15 @@ export function createRoutableExtension< // Validate that the routing is wired up correctly in the App.tsx try { useRouteRef(mountPoint); - } catch { - throw new Error( - `Routable extension component with mount point ${mountPoint} was not discovered in the app element tree. ` + - 'Routable extension components may not be rendered by other components and must be ' + - 'directly available as an element within the App provider component.', - ); + } catch (error) { + if (error?.message.startsWith('No path for ')) { + throw new Error( + `Routable extension component with mount point ${mountPoint} was not discovered in the app element tree. ` + + 'Routable extension components may not be rendered by other components and must be ' + + 'directly available as an element within the App provider component.', + ); + } + throw error; } return <InnerComponent {...props} />; }; From e7d2fb93f0a96cb53ae80348eea66b0ae7235f49 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Wed, 24 Feb 2021 16:48:38 -0500 Subject: [PATCH 046/262] Create code-coverage plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to use this plugin, you must set the `backstage.io/code-coverage` annotation on your entity. ```yaml backstage.io/code-coverage: enabled ``` There's a feature to only include files that are in SCM in the coverage report, this is helpful to not count generated files for example. To enable this set the `backstage.io/code-coverage` annotation to `scm-only`. ```yaml backstage.io/code-coverage: scm-only ``` The backend plugin provides API endpoints for submitting code-coverage reports. Currently jacoco and cobertura are supported. These reports are normalized to a json format that is stored in the database. ```json // curl -X POST -H "Content-Type:text/xml" -d @cobertura.xml "localhost:7000/api/code-coverage/Component/default/entity-name?coverageType=cobertura" { "links": [ { "href": "http://localhost:7000/api/code-coverage/Component/default/entity-name", "rel": "coverage" } ] } ``` It also provides some additional API endpoints: * Viewing the latest report * Viewing a more condensed history of code coverage values * Retrieving file contents from source-control, used by the UI Provides a graph of code coverage change over time, as well as a file view where you can see the highlighted lines. Co-authored-by: nissayeva <natashaaay@gmail.com> Signed-off-by: alde <r.dybeck@gmail.com> Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .github/CODEOWNERS | 2 + packages/app/package.json | 1 + .../app/src/components/catalog/EntityPage.tsx | 9 + packages/backend/package.json | 1 + packages/backend/src/index.ts | 5 + packages/backend/src/plugins/codecoverage.ts | 28 + plugins/code-coverage-backend/.eslintrc.js | 3 + plugins/code-coverage-backend/README.md | 150 + .../migrations/20210302_init.js | 50 + plugins/code-coverage-backend/package.json | 50 + plugins/code-coverage-backend/src/index.ts | 17 + plugins/code-coverage-backend/src/run.ts | 33 + .../src/service/CodeCoverageDatabase.test.ts | 199 + .../src/service/CodeCoverageDatabase.ts | 112 + .../src/service/CoverageUtils.test.ts | 325 + .../src/service/CoverageUtils.ts | 168 + .../cobertura-jsoncoverage-files-1.json | 166 + .../cobertura-jsoncoverage-files-2.json | 3952 ++++++++++++ .../cobertura-jsoncoverage-files-3.json | 297 + .../cobertura-jsoncoverage-files-4.json | 351 + .../cobertura-jsoncoverage-files-5.json | 325 + .../__fixtures__/cobertura-sourcefiles-1.txt | 19 + .../__fixtures__/cobertura-sourcefiles-2.txt | 49 + .../__fixtures__/cobertura-sourcefiles-3.txt | 29 + .../__fixtures__/cobertura-sourcefiles-4.txt | 20 + .../__fixtures__/cobertura-sourcefiles-5.txt | 26 + .../__fixtures__/cobertura-testdata-1.xml | 479 ++ .../__fixtures__/cobertura-testdata-2.xml | 5721 +++++++++++++++++ .../__fixtures__/cobertura-testdata-3.xml | 357 + .../__fixtures__/cobertura-testdata-4.xml | 348 + .../__fixtures__/cobertura-testdata-5.xml | 441 ++ .../jacoco-jsoncoverage-files-1.json | 319 + .../__fixtures__/jacoco-sourcefiles-1.txt | 7 + .../__fixtures__/jacoco-testdata-1.xml | 282 + .../src/service/converter/cobertura.test.ts | 56 + .../src/service/converter/cobertura.ts | 126 + .../src/service/converter/index.ts | 23 + .../src/service/converter/jacoco.test.ts | 50 + .../src/service/converter/jacoco.ts | 96 + .../src/service/converter/types.ts | 92 + .../src/service/jsoncoverage-types.ts | 71 + .../src/service/router.test.ts | 79 + .../src/service/router.ts | 229 + .../src/service/standaloneServer.ts | 64 + .../code-coverage-backend/src/setupTests.ts | 17 + plugins/code-coverage/.eslintrc.js | 3 + plugins/code-coverage/README.md | 19 + plugins/code-coverage/dev/index.tsx | 26 + plugins/code-coverage/package.json | 57 + plugins/code-coverage/src/api.ts | 102 + .../CodeCoveragePage/CodeCoveragePage.tsx | 31 + .../src/components/CodeCoveragePage/index.ts | 16 + .../CoverageHistoryChart.tsx | 169 + .../components/CoverageHistoryChart/index.ts | 17 + .../components/FileExplorer/CoverageRow.tsx | 103 + .../components/FileExplorer/FileContent.tsx | 137 + .../components/FileExplorer/FileExplorer.tsx | 280 + .../components/FileExplorer/Highlighter.ts | 54 + .../src/components/FileExplorer/index.ts | 17 + .../code-coverage/src/components/Router.tsx | 34 + plugins/code-coverage/src/dev/index.tsx | 28 + plugins/code-coverage/src/index.ts | 23 + plugins/code-coverage/src/plugin.test.ts | 22 + plugins/code-coverage/src/plugin.ts | 45 + plugins/code-coverage/src/routes.ts | 20 + plugins/code-coverage/src/setupTests.ts | 17 + yarn.lock | 280 +- 67 files changed, 16733 insertions(+), 11 deletions(-) create mode 100644 packages/backend/src/plugins/codecoverage.ts create mode 100644 plugins/code-coverage-backend/.eslintrc.js create mode 100644 plugins/code-coverage-backend/README.md create mode 100644 plugins/code-coverage-backend/migrations/20210302_init.js create mode 100644 plugins/code-coverage-backend/package.json create mode 100644 plugins/code-coverage-backend/src/index.ts create mode 100644 plugins/code-coverage-backend/src/run.ts create mode 100644 plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts create mode 100644 plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts create mode 100644 plugins/code-coverage-backend/src/service/CoverageUtils.test.ts create mode 100644 plugins/code-coverage-backend/src/service/CoverageUtils.ts create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-1.json create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-2.json create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-3.json create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-4.json create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-5.json create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-1.txt create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-2.txt create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-3.txt create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-4.txt create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-5.txt create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-1.xml create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-2.xml create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-3.xml create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-4.xml create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-5.xml create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/jacoco-jsoncoverage-files-1.json create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/jacoco-sourcefiles-1.txt create mode 100644 plugins/code-coverage-backend/src/service/__fixtures__/jacoco-testdata-1.xml create mode 100644 plugins/code-coverage-backend/src/service/converter/cobertura.test.ts create mode 100644 plugins/code-coverage-backend/src/service/converter/cobertura.ts create mode 100644 plugins/code-coverage-backend/src/service/converter/index.ts create mode 100644 plugins/code-coverage-backend/src/service/converter/jacoco.test.ts create mode 100644 plugins/code-coverage-backend/src/service/converter/jacoco.ts create mode 100644 plugins/code-coverage-backend/src/service/converter/types.ts create mode 100644 plugins/code-coverage-backend/src/service/jsoncoverage-types.ts create mode 100644 plugins/code-coverage-backend/src/service/router.test.ts create mode 100644 plugins/code-coverage-backend/src/service/router.ts create mode 100644 plugins/code-coverage-backend/src/service/standaloneServer.ts create mode 100644 plugins/code-coverage-backend/src/setupTests.ts create mode 100644 plugins/code-coverage/.eslintrc.js create mode 100644 plugins/code-coverage/README.md create mode 100644 plugins/code-coverage/dev/index.tsx create mode 100644 plugins/code-coverage/package.json create mode 100644 plugins/code-coverage/src/api.ts create mode 100644 plugins/code-coverage/src/components/CodeCoveragePage/CodeCoveragePage.tsx create mode 100644 plugins/code-coverage/src/components/CodeCoveragePage/index.ts create mode 100644 plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx create mode 100644 plugins/code-coverage/src/components/CoverageHistoryChart/index.ts create mode 100644 plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx create mode 100644 plugins/code-coverage/src/components/FileExplorer/FileContent.tsx create mode 100644 plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx create mode 100644 plugins/code-coverage/src/components/FileExplorer/Highlighter.ts create mode 100644 plugins/code-coverage/src/components/FileExplorer/index.ts create mode 100644 plugins/code-coverage/src/components/Router.tsx create mode 100644 plugins/code-coverage/src/dev/index.tsx create mode 100644 plugins/code-coverage/src/index.ts create mode 100644 plugins/code-coverage/src/plugin.test.ts create mode 100644 plugins/code-coverage/src/plugin.ts create mode 100644 plugins/code-coverage/src/routes.ts create mode 100644 plugins/code-coverage/src/setupTests.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4e21603c63..803ebd6445 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,6 +8,8 @@ /docs/features/techdocs @backstage/techdocs-core /docs/features/search @backstage/techdocs-core /docs/assets/search @backstage/techdocs-core +/plugins/code-coverage @alde @nissayeva +/plugins/code-coverage-backend @alde @nissayeva /plugins/cost-insights @backstage/silver-lining /plugins/cloudbuild @trivago/ebarrios /plugins/search @backstage/techdocs-core diff --git a/packages/app/package.json b/packages/app/package.json index 4d2dbe660a..95e14766c3 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -15,6 +15,7 @@ "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/plugin-circleci": "^0.2.12", "@backstage/plugin-cloudbuild": "^0.2.13", + "@backstage/plugin-code-coverage": "^0.1.0", "@backstage/plugin-cost-insights": "^0.8.4", "@backstage/plugin-explore": "^0.3.2", "@backstage/plugin-gcp-projects": "^0.2.5", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index d4db2b0e63..601134362d 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -102,6 +102,7 @@ import { EntityTravisCIOverviewCard, isTravisciAvailable, } from '@roadiehq/backstage-plugin-travis-ci'; +import { EntityCodeCoverageContent } from '@backstage/plugin-code-coverage'; const EntityLayoutWrapper = (props: { children?: ReactNode }) => { const [badgesDialogOpen, setBadgesDialogOpen] = useState(false); @@ -303,6 +304,10 @@ const serviceEntityPage = ( <EntityGithubInsightsContent /> </EntityLayout.Route> + <EntityLayout.Route path="/code-coverage" title="Code Coverage"> + <EntityCodeCoverageContent /> + </EntityLayout.Route> + <EntityLayout.Route path="/kafka" title="Kafka"> <EntityKafkaContent /> </EntityLayout.Route> @@ -347,6 +352,10 @@ const websiteEntityPage = ( <EntityGithubInsightsContent /> </EntityLayout.Route> + <EntityLayout.Route path="/code-coverage" title="Code Coverage"> + <EntityCodeCoverageContent /> + </EntityLayout.Route> + <EntityLayout.Route path="/todos" title="TODOs"> <EntityTodoContent /> </EntityLayout.Route> diff --git a/packages/backend/package.json b/packages/backend/package.json index 40e5a1cd2f..984b8b60a5 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -35,6 +35,7 @@ "@backstage/plugin-auth-backend": "^0.3.7", "@backstage/plugin-badges-backend": "^0.1.1", "@backstage/plugin-catalog-backend": "^0.7.0", + "@backstage/plugin-code-coverage-backend": "^0.1.0", "@backstage/plugin-graphql-backend": "^0.1.6", "@backstage/plugin-kubernetes-backend": "^0.3.3", "@backstage/plugin-kafka-backend": "^0.2.3", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index cbbdaecf5e..00ed248df5 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -37,6 +37,7 @@ import { Config } from '@backstage/config'; import healthcheck from './plugins/healthcheck'; import auth from './plugins/auth'; import catalog from './plugins/catalog'; +import codeCoverage from './plugins/codecoverage'; import kubernetes from './plugins/kubernetes'; import kafka from './plugins/kafka'; import rollbar from './plugins/rollbar'; @@ -75,6 +76,9 @@ async function main() { const healthcheckEnv = useHotMemoize(module, () => createEnv('healthcheck')); const catalogEnv = useHotMemoize(module, () => createEnv('catalog')); + const codeCoverageEnv = useHotMemoize(module, () => + createEnv('code-coverage'), + ); const scaffolderEnv = useHotMemoize(module, () => createEnv('scaffolder')); const authEnv = useHotMemoize(module, () => createEnv('auth')); const proxyEnv = useHotMemoize(module, () => createEnv('proxy')); @@ -90,6 +94,7 @@ async function main() { const apiRouter = Router(); apiRouter.use('/catalog', await catalog(catalogEnv)); + apiRouter.use('/code-coverage', await codeCoverage(codeCoverageEnv)); apiRouter.use('/rollbar', await rollbar(rollbarEnv)); apiRouter.use('/scaffolder', await scaffolder(scaffolderEnv)); apiRouter.use('/auth', await auth(authEnv)); diff --git a/packages/backend/src/plugins/codecoverage.ts b/packages/backend/src/plugins/codecoverage.ts new file mode 100644 index 0000000000..c06e0e516f --- /dev/null +++ b/packages/backend/src/plugins/codecoverage.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { createRouter } from '@backstage/plugin-code-coverage-backend'; +import { PluginEnvironment } from '../types'; + +export default async function createPlugin(env: PluginEnvironment) { + return await createRouter({ + config: env.config, + discovery: env.discovery, + database: env.database, + urlReader: env.reader, + logger: env.logger, + }); +} diff --git a/plugins/code-coverage-backend/.eslintrc.js b/plugins/code-coverage-backend/.eslintrc.js new file mode 100644 index 0000000000..16a033dbc6 --- /dev/null +++ b/plugins/code-coverage-backend/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint.backend')], +}; diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md new file mode 100644 index 0000000000..2e2f5ba91f --- /dev/null +++ b/plugins/code-coverage-backend/README.md @@ -0,0 +1,150 @@ +# code-coverage + +This is the backend part of the code-coverage plugin. It takes care of processing various coverage formats and standardizing them into a single json format, used by the frontend. + +## Configuring your entity + +In order to use this plugin, you must set the `backstage.io/code-coverage` annotation. + +```yaml +backstage.io/code-coverage: enabled +``` + +There's a feature to only include files that are in VCS in the coverage report, this is helpful to not count generated files for example. To enable this set the `backstage.io/code-coverage` annotation to `scm-only`. + +```yaml +backstage.io/code-coverage: scm-only +``` + +Note: This requires the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location) to be set. + +## API + +### Adding cobertura report + +POST a cobertura xml to `/:kind/:namespace/:name?coverageType=cobertura` + +Example: + +```json +// curl -X POST -H "Content-Type:text/xml" -d @cobertura.xml "localhost:7000/api/code-coverage/Component/default/entity-name?coverageType=cobertura" +{ + "links": [ + { + "href": "http://localhost:7000/api/code-coverage/Component/default/entity-name", + "rel": "coverage" + } + ] +} +``` + +### Adding jacoco report + +POST a jacoco xml to `/:kind/:namespace/:name?coverageType=jacoco` + +Example: + +```json +// curl -X POST -H "Content-Type:text/xml" -d @jacoco.xml "localhost:7000/api/code-coverage/Component/default/entity-name?coverageType=jacoco" +{ + "links": [ + { + "href": "http://localhost:7000/api/code-coverage/Component/default/entity-name", + "rel": "coverage" + } + ] +} +``` + +### Reading json coverage + +GET `/:kind/:namespace/:name` + +Example: + +```json +// curl localhost:7000/api/code-coverage/Component/default/entity-name +{ + "aggregate": { + "branch": { + "available": 0, + "covered": 0, + "missed": 0, + "percentage": 0 + }, + "line": { + "available": 5, + "covered": 4, + "missed": 1, + "percentage": 80 + } + }, + "entity": { + "kind": "Component", + "name": "entity-name", + "namespace": "default" + }, + "files": [ + { + "branchHits": {}, + "filename": "main.go", + "lineHits": { + "117": 12, + "142": 8, + "34": 8, + "42": 0, + "58": 6 + } + } + ] +} +``` + +### Coverage history + +GET `/:kind/:namespace/:name/history` + +Example + +```json +// curl localhost:7000/api/code-coverage/Component/default/entity-name/history +{ + "entity": { + "kind": "Component", + "name": "entity-name", + "namespace": "default" + }, + "history": [ + { + "branch": { + "available": 0, + "covered": 0, + "missed": 0, + "percentage": 0 + }, + "line": { + "available": 299, + "covered": 116, + "missed": 183, + "percentage": 38.8 + }, + "timestamp": 1615490766141 + }, + { + "branch": { + "available": 0, + "covered": 0, + "missed": 0, + "percentage": 0 + }, + "line": { + "available": 299, + "covered": 116, + "missed": 183, + "percentage": 38.8 + }, + "timestamp": 1615406307929 + } + ] +} +``` diff --git a/plugins/code-coverage-backend/migrations/20210302_init.js b/plugins/code-coverage-backend/migrations/20210302_init.js new file mode 100644 index 0000000000..0edd455e7d --- /dev/null +++ b/plugins/code-coverage-backend/migrations/20210302_init.js @@ -0,0 +1,50 @@ +/* + * Copyright 2021 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.createTable('code_coverage', table => { + table.comment('The table of code coverage'); + table + .uuid('id') + .primary() + .notNullable() + .comment('The ID of the code coverage'); + table.text('entity_name').notNullable().comment('entity name'); + table.text('entity_kind').notNullable().comment('entity kind'); + table.text('entity_namespace').notNullable().comment('entity namespace'); + table + .text('coverage') + .notNullable() + .comment('The coverage json as a string'); + table + .dateTime('created_at') + .defaultTo(knex.fn.now()) + .notNullable() + .comment('The timestamp when this entry was created'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.dropTable('code_coverage'); +}; diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json new file mode 100644 index 0000000000..79de777dfa --- /dev/null +++ b/plugins/code-coverage-backend/package.json @@ -0,0 +1,50 @@ +{ + "name": "@backstage/plugin-code-coverage-backend", + "version": "0.1.1", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "start": "backstage-cli backend:dev", + "build": "backstage-cli backend:build", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/backend-common": "^0.5.4", + "@backstage/catalog-client": "^0.3.6", + "@backstage/catalog-model": "^0.7.2", + "@backstage/config": "^0.1.3", + "@backstage/errors": "^0.1.1", + "@backstage/integration": "^0.5.0", + "@backstage/plugin-catalog-backend": "^0.6.5", + "@types/express": "^4.17.6", + "cross-fetch": "^3.0.6", + "express": "^4.17.1", + "express-promise-router": "^3.0.3", + "express-xml-bodyparser": "^0.3.0", + "knex": "^0.95.1", + "uuid": "^8.3.2", + "winston": "^3.2.1", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/cli": "^0.6.2", + "@types/express-xml-bodyparser": "^0.3.2", + "@types/supertest": "^2.0.8", + "msw": "^0.21.2", + "supertest": "^4.0.2", + "xml2js": "^0.4.23" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/code-coverage-backend/src/index.ts b/plugins/code-coverage-backend/src/index.ts new file mode 100644 index 0000000000..7612c392a2 --- /dev/null +++ b/plugins/code-coverage-backend/src/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './service/router'; diff --git a/plugins/code-coverage-backend/src/run.ts b/plugins/code-coverage-backend/src/run.ts new file mode 100644 index 0000000000..b96989e4b8 --- /dev/null +++ b/plugins/code-coverage-backend/src/run.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { getRootLogger } from '@backstage/backend-common'; +import yn from 'yn'; +import { startStandaloneServer } from './service/standaloneServer'; + +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7000; +const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); +const logger = getRootLogger(); + +startStandaloneServer({ port, enableCors, logger }).catch(err => { + logger.error(err); + process.exit(1); +}); + +process.on('SIGINT', () => { + logger.info('CTRL+C pressed; exiting.'); + process.exit(0); +}); diff --git a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts new file mode 100644 index 0000000000..af734dd358 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts @@ -0,0 +1,199 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + getVoidLogger, + SingleConnectionDatabaseManager, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { + CodeCoverageDatabase, + CodeCoverageStore, +} from './CodeCoverageDatabase'; +import { JsonCodeCoverage } from './jsoncoverage-types'; + +const db = SingleConnectionDatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'sqlite3', + connection: ':memory:', + }, + }, + }), +).forPlugin('code-coverage'); + +const coverage: Array<JsonCodeCoverage> = [ + { + metadata: { + generationTime: 1234567890, + vcs: { + location: 'local', + type: 'local', + }, + }, + entity: { + kind: 'Component', + name: 'test-entity', + namespace: 'default', + }, + files: [ + { + filename: 'src/main.py', + lineHits: { + '10': 5, + '11': 4, + '12': 4, + }, + branchHits: {}, + }, + ], + }, + { + metadata: { + generationTime: 2345678901, + vcs: { + location: 'local', + type: 'local', + }, + }, + entity: { + kind: 'Component', + name: 'test-entity', + namespace: 'default', + }, + files: [ + { + filename: 'src/main.py', + lineHits: { + '10': 5, + '11': 4, + '12': 4, + '22': 0, + '23': 0, + '24': 0, + '30': 1, + }, + branchHits: { + '10': { + available: 2, + covered: 1, + missed: 1, + }, + }, + }, + ], + }, +]; + +let database: CodeCoverageStore; +describe('CodeCoverageDatabase', () => { + beforeAll(async () => { + const client = await db.getClient(); + database = await CodeCoverageDatabase.create(client, getVoidLogger()); + database.insertCodeCoverage(coverage[0]); + await new Promise(r => setTimeout(r, 1000)); + database.insertCodeCoverage(coverage[1]); + }); + + describe('insertCodeCoverage', () => { + it('can insert code coverage', async () => { + const ncov = { + metadata: { + generationTime: 3456789012, + vcs: { + location: 'local', + type: 'local', + }, + }, + entity: { + kind: 'Component', + name: 'test-entity-for-insert', + namespace: 'default', + }, + files: [ + { + filename: 'src/main.py', + lineHits: { + '10': 5, + '11': 4, + '12': 4, + }, + branchHits: {}, + }, + ], + }; + const { codeCoverageId } = await database.insertCodeCoverage(ncov); + expect(codeCoverageId.length).not.toBe(0); + }); + }); + + describe('getCodeCoverage', () => { + it("can get coverage that's in the database", async () => { + const cov = await database.getCodeCoverage({ + name: 'test-entity', + kind: 'Component', + namespace: 'default', + }); + expect(cov).toEqual(coverage[1]); + }); + }); + + describe('getHistory', () => { + it("can get history that's in the database", async () => { + const cov = await database.getHistory( + { + name: 'test-entity', + kind: 'Component', + namespace: 'default', + }, + 5, + ); + expect(cov.history.length).toEqual(2); + expect(cov.history).toEqual([ + { + branch: { + available: 2, + covered: 1, + missed: 1, + percentage: 50, + }, + line: { + available: 7, + covered: 4, + missed: 3, + percentage: 57.14, + }, + timestamp: 2345678901, + }, + { + branch: { + available: 0, + covered: 0, + missed: 0, + percentage: 0, + }, + line: { + available: 3, + covered: 3, + missed: 0, + percentage: 100, + }, + timestamp: 1234567890, + }, + ]); + }); + }); +}); diff --git a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts new file mode 100644 index 0000000000..44109e8e2e --- /dev/null +++ b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts @@ -0,0 +1,112 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { resolvePackagePath } from '@backstage/backend-common'; +import { NotFoundError } from '@backstage/errors'; +import { EntityName } from '@backstage/catalog-model'; +import { Knex } from 'knex'; +import { v4 as uuid } from 'uuid'; +import { Logger } from 'winston'; +import { aggregateCoverage } from './CoverageUtils'; +import { JsonCodeCoverage, JsonCoverageHistory } from './jsoncoverage-types'; + +export type RawDbCoverageRow = { + id: string; + entity_name: string; + entity_namespace: string; + entity_kind: string; + coverage: string; +}; +export interface CodeCoverageStore { + insertCodeCoverage( + coverage: JsonCodeCoverage, + ): Promise<{ codeCoverageId: string }>; + getCodeCoverage(entity: EntityName): Promise<JsonCodeCoverage>; + getHistory(entity: EntityName, limit: number): Promise<JsonCoverageHistory>; +} + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-code-coverage-backend', + 'migrations', +); +export class CodeCoverageDatabase implements CodeCoverageStore { + static async create(knex: Knex, logger: Logger): Promise<CodeCoverageStore> { + await knex.migrate.latest({ + directory: migrationsDir, + }); + return new CodeCoverageDatabase(knex, logger); + } + + constructor(private readonly db: Knex, private readonly logger: Logger) {} + + async insertCodeCoverage( + coverage: JsonCodeCoverage, + ): Promise<{ codeCoverageId: string }> { + const codeCoverageId = uuid(); + await this.db<RawDbCoverageRow>('code_coverage').insert({ + id: codeCoverageId, + entity_name: coverage.entity.name, + entity_kind: coverage.entity.kind, + entity_namespace: coverage.entity.namespace, + coverage: JSON.stringify(coverage), + }); + return { codeCoverageId }; + } + async getCodeCoverage(entity: EntityName): Promise<JsonCodeCoverage> { + const [result] = await this.db<RawDbCoverageRow>('code_coverage') + .where({ + entity_name: entity.name, + entity_kind: entity.kind, + entity_namespace: entity.namespace, + }) + .orderBy('created_at', 'desc') + .limit(1) + .select(); + if (!result) { + throw new NotFoundError( + `No coverage for entity '${JSON.stringify(entity)}' found`, + ); + } + try { + return JSON.parse(result.coverage); + } catch (error) { + throw new Error(`Failed to parse coverage for '${entity}', ${error}`); + } + } + + async getHistory( + entity: EntityName, + limit: number, + ): Promise<JsonCoverageHistory> { + const res = await this.db<RawDbCoverageRow>('code_coverage') + .where({ + entity_name: entity.name, + entity_kind: entity.kind, + entity_namespace: entity.namespace, + }) + .orderBy('created_at', 'desc') + .limit(limit) + .select(); + + const history = res + .map(r => JSON.parse(r.coverage)) + .map(c => aggregateCoverage(c)); + + return { + entity, + history: history, + }; + } +} diff --git a/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts b/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts new file mode 100644 index 0000000000..5a5cffbced --- /dev/null +++ b/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts @@ -0,0 +1,325 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 fs from 'fs'; +import { Readable } from 'stream'; +import { + calculatePercentage, + aggregateCoverage, + CoverageUtils, +} from './CoverageUtils'; +import { Entity } from '@backstage/catalog-model'; +import { parseString } from 'xml2js'; + +describe('calculatePercentage', () => { + [ + [100, 25, 25], + [100, 100, 100], + [133, 13, 9.77], + [0, 0, 0], + ].forEach(([a, c, e]) => { + it(`${c}/${a} === ${e}`, () => { + expect(calculatePercentage(a, c)).toEqual(e); + }); + }); +}); + +/* eslint-disable no-restricted-syntax */ + +describe('aggregateCoverage', () => { + [ + { + file: 'jacoco-jsoncoverage-files-1.json', + expected: { + branch: { + available: 68, + covered: 48, + missed: 20, + percentage: 70.59, + }, + line: { + available: 162, + covered: 105, + missed: 57, + percentage: 64.81, + }, + timestamp: 1234567890, + }, + }, + { + file: 'cobertura-jsoncoverage-files-1.json', + expected: { + branch: { + available: 0, + covered: 0, + missed: 0, + percentage: 0, + }, + line: { + available: 146, + covered: 145, + missed: 1, + percentage: 99.32, + }, + timestamp: 1234567890, + }, + }, + { + file: 'cobertura-jsoncoverage-files-2.json', + expected: { + branch: { + available: 466, + covered: 380, + missed: 86, + percentage: 81.55, + }, + line: { + available: 2632, + covered: 2079, + missed: 553, + percentage: 78.99, + }, + timestamp: 1234567890, + }, + }, + { + file: 'cobertura-jsoncoverage-files-3.json', + expected: { + branch: { + available: 73, + covered: 49, + missed: 24, + percentage: 67.12, + }, + line: { + available: 110, + covered: 91, + missed: 19, + percentage: 82.73, + }, + timestamp: 1234567890, + }, + }, + { + file: 'cobertura-jsoncoverage-files-4.json', + expected: { + branch: { + available: 0, + covered: 0, + missed: 0, + percentage: 0, + }, + line: { + available: 325, + covered: 0, + missed: 325, + percentage: 0, + }, + timestamp: 1234567890, + }, + }, + { + file: 'cobertura-jsoncoverage-files-5.json', + expected: { + branch: { + available: 38, + covered: 21, + missed: 17, + percentage: 55.26, + }, + line: { + available: 175, + covered: 124, + missed: 51, + percentage: 70.86, + }, + timestamp: 1234567890, + }, + }, + ].forEach(td => { + it(`processes ${td.file}`, () => { + const json = JSON.parse( + fs.readFileSync(`${__dirname}/__fixtures__/${td.file}`).toString(), + ); + const aggregate = aggregateCoverage({ + metadata: { + generationTime: 1234567890, + vcs: { + location: 'foo', + type: 'foo', + }, + }, + entity: { + kind: 'foo', + name: 'foo', + namespace: 'default', + }, + files: json, + }); + + expect(aggregate).toEqual(td.expected); + }); + }); +}); + +describe('CodeCoverageUtils', () => { + const scmFilesFixture = fs + .readFileSync(`${__dirname}/__fixtures__/cobertura-sourcefiles-1.txt`) + .toString() + .split('\n') + .map(f => { + return { path: f }; + }); + const scmIntegraions = { + byUrl: jest.fn().mockReturnValue({ + type: 'local', + title: 'local', + }), + }; + const scmTree = { + files: jest + .fn() + .mockReturnValue(new Promise((r, _e) => r(scmFilesFixture))), + }; + const urlReader = { + readTree: jest.fn().mockReturnValue(new Promise((r, _e) => r(scmTree))), + }; + const utils = new CoverageUtils(scmIntegraions, urlReader); + + describe('validateRequestBody', () => { + it('rejects missing content type', () => { + let err: Error | null = null; + try { + const mockRequest: Partial<Request> = { + // @ts-ignore + headers: {}, + }; + // @ts-ignore + utils.validateRequestBody(mockRequest as Request); + } catch (error) { + err = error; + } + expect(err?.message).toEqual('Content-Type missing'); + }); + + it('rejects unsupported content type', () => { + let err: Error | null = null; + try { + const mockRequest: Partial<Request> = { + headers: { + // @ts-ignore + 'content-type': 'application/json', + }, + }; + + // @ts-ignore + utils.validateRequestBody(mockRequest as Request); + } catch (error) { + err = error; + } + expect(err?.message).toEqual('Illegal Content-Type'); + }); + + it('parses the body', () => { + const mockRequest: Partial<Request> = { + headers: { + // @ts-ignore + 'content-type': 'text/xml', + }, + // @ts-ignore + body: Readable.from( + '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><report name="example"></report>', + ), + }; + + // @ts-ignore + const data: Readable = utils.validateRequestBody(mockRequest as Request); + + expect(data.read()).toContain('<?xml'); + }); + }); + + describe('processCoveragePayload', () => { + const mockRequest: Partial<Request> = { + headers: { + // @ts-ignore + 'content-type': 'text/xml', + }, + // @ts-ignore + body: Readable.from( + '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><report name="example"></report>', + ), + }; + + it('ignores scm if annotation is not set', async () => { + const entity: Entity = { + kind: 'Component', + metadata: { + name: 'test-entity', + namespace: 'test', + }, + apiVersion: 'backstage.io/v1alpha1', + }; + + const { + scmFiles, + sourceLocation, + vcs, + body, // @ts-ignore + } = await utils.processCoveragePayload(entity, mockRequest); + let data; + // in normal flow the express app will already have done this through the middleware + parseString((body as Readable).read(), (_e, r) => { + data = r; + }); + + expect(scmFiles.length).toBe(0); + expect(vcs).toBeUndefined(); + expect(sourceLocation).toBeUndefined(); + expect(data).toEqual({ + report: { + $: { + name: 'example', + }, + }, + }); + }); + + it('populates scm data if annotation is set', async () => { + const entity: Entity = { + kind: 'Component', + metadata: { + name: 'test-entity', + namespace: 'test', + annotations: { + 'backstage.io/code-coverage': 'scm-only', + 'backstage.io/source-location': 'https://github.com/example/test/', + }, + }, + apiVersion: 'backstage.io/v1alpha1', + }; + + const { + scmFiles, + sourceLocation, + vcs, // @ts-ignore + } = await utils.processCoveragePayload(entity, mockRequest); + + expect(scmFiles.length).toBe(scmFiles.length); + expect(vcs).not.toBeUndefined(); + expect(sourceLocation).not.toBeUndefined(); + }); + }); +}); diff --git a/plugins/code-coverage-backend/src/service/CoverageUtils.ts b/plugins/code-coverage-backend/src/service/CoverageUtils.ts new file mode 100644 index 0000000000..0ed1561003 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/CoverageUtils.ts @@ -0,0 +1,168 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { Request } from 'express'; +import { UrlReader } from '@backstage/backend-common'; +import { InputError, NotFoundError } from '@backstage/errors'; +import { Entity } from '@backstage/catalog-model'; +import { ScmIntegration, ScmIntegrations } from '@backstage/integration'; +import { + AggregateCoverage, + FileEntry, + JsonCodeCoverage, +} from './jsoncoverage-types'; + +export const calculatePercentage = ( + available: number, + covered: number, +): number => { + if (available === 0) { + return 0; + } + return parseFloat(((covered / available) * 100).toFixed(2)); +}; + +export const aggregateCoverage = (c: JsonCodeCoverage): AggregateCoverage => { + let availableLine = 0; + let coveredLine = 0; + let availableBranch = 0; + let coveredBranch = 0; + c.files.forEach(f => { + availableLine += Object.keys(f.lineHits).length; + coveredLine += Object.values(f.lineHits).filter(l => l > 0).length; + + availableBranch += Object.keys(f.branchHits) + .map(b => parseInt(b, 10)) + .map((b: number) => f.branchHits[b].available) + .filter(Boolean) + .reduce((acc, curr) => acc + curr, 0); + coveredBranch += Object.keys(f.branchHits) + .map(b => parseInt(b, 10)) + .map((b: number) => f.branchHits[b].covered) + .filter(Boolean) + .reduce((acc, curr) => acc + curr, 0); + }); + + return { + timestamp: c.metadata.generationTime, + branch: { + available: availableBranch, + covered: coveredBranch, + missed: availableBranch - coveredBranch, + percentage: calculatePercentage(availableBranch, coveredBranch), + }, + line: { + available: availableLine, + covered: coveredLine, + missed: availableLine - coveredLine, + percentage: calculatePercentage(availableLine, coveredLine), + }, + }; +}; + +export class CoverageUtils { + constructor( + readonly scm: Partial<ScmIntegrations>, + readonly urlReader: Partial<UrlReader>, + ) {} + + async processCoveragePayload( + entity: Entity, + req: Request, + ): Promise<{ + sourceLocation?: string; + vcs?: ScmIntegration; + scmFiles: string[]; + body: {}; + }> { + const enforceScmFiles = + entity.metadata.annotations?.['backstage.io/code-coverage'] === + 'scm-only' || false; + + let sourceLocation: string | undefined = undefined; + let vcs: ScmIntegration | undefined = undefined; + let scmFiles: string[] = []; + + if (enforceScmFiles) { + sourceLocation = + entity.metadata.annotations?.['backstage.io/source-location']; + if (!sourceLocation) { + throw new InputError( + `No "backstage.io/source-location" annotation on entity ${entity.kind}/${entity.metadata.namespace}/${entity.metadata.name}`, + ); + } + + vcs = this.scm.byUrl?.(sourceLocation); + if (!vcs) { + throw new InputError(`Unable to determine SCM from ${sourceLocation}`); + } + + const scmTree = await this.urlReader.readTree?.(sourceLocation); + if (!scmTree) { + throw new NotFoundError(`Unable to read tree from ${sourceLocation}`); + } + scmFiles = (await scmTree.files()).map(f => f.path); + } + + const body = this.validateRequestBody(req); + if (Object.keys(body).length === 0) { + throw new InputError('Unable to parse body'); + } + + return { + sourceLocation, + vcs, + scmFiles, + body, + }; + } + + async buildCoverage( + entity: Entity, + sourceLocation: string | undefined, + vcs: ScmIntegration | undefined, + files: FileEntry[], + ): Promise<JsonCodeCoverage> { + return { + metadata: { + vcs: { + type: vcs?.type || 'unknown', + location: sourceLocation || 'unknown', + }, + generationTime: Date.now(), + }, + entity: { + name: entity.metadata.name, + namespace: entity.metadata.namespace || 'default', + kind: entity.kind, + }, + files, + }; + } + + validateRequestBody(req: Request) { + const contentType = req.headers['content-type']; + if (!contentType) { + throw new InputError('Content-Type missing'); + } else if (!contentType.match(/^text\/xml($|;)/)) { + throw new InputError('Illegal Content-Type'); + } + const body = req.body; + if (!body) { + throw new InputError('Missing request body'); + } + return body; + } +} diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-1.json b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-1.json new file mode 100644 index 0000000000..b5b861254c --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-1.json @@ -0,0 +1,166 @@ +[ + { + "filename": "src/main/scala/com/example/Main.scala", + "lineHits": { + "100": 4, + "103": 2, + "104": 4, + "105": 4, + "112": 2, + "114": 4, + "115": 2, + "124": 3, + "125": 2, + "126": 3, + "127": 3, + "135": 3, + "136": 1, + "138": 2, + "139": 1, + "140": 1, + "143": 1, + "145": 1, + "146": 1, + "147": 1, + "148": 1, + "149": 1, + "150": 1, + "160": 2, + "163": 8, + "164": 4, + "166": 2, + "167": 4, + "168": 6, + "169": 6, + "170": 4, + "178": 1, + "179": 1, + "181": 1, + "182": 1, + "183": 3, + "187": 1, + "188": 3, + "202": 4, + "203": 6, + "204": 4, + "210": 5, + "26": 4, + "27": 4, + "28": 4, + "30": 4, + "33": 4, + "35": 2, + "36": 2, + "37": 4, + "38": 2, + "42": 2, + "44": 2, + "46": 2, + "48": 2, + "50": 2, + "52": 2, + "53": 2, + "55": 2, + "56": 2, + "58": 2, + "60": 2, + "61": 2, + "64": 2, + "65": 6, + "68": 4, + "73": 2, + "75": 10, + "77": 4, + "83": 1, + "84": 2, + "85": 3, + "86": 3, + "87": 1, + "88": 6, + "95": 2, + "97": 8, + "99": 2 + }, + "branchHits": {} + }, + { + "filename": "src/main/scala/com/example/Other.scala", + "lineHits": { + "103": 6, + "104": 2, + "105": 5, + "109": 1, + "110": 3, + "111": 3, + "113": 2, + "115": 2, + "116": 2, + "117": 2, + "119": 2, + "123": 3, + "124": 1, + "129": 7, + "132": 2, + "133": 4, + "134": 2, + "138": 1, + "139": 2, + "140": 2, + "142": 4, + "143": 3, + "144": 5, + "145": 3, + "146": 5, + "147": 3, + "149": 2, + "20": 1, + "21": 1, + "23": 1, + "25": 2, + "26": 1, + "27": 2, + "29": 2, + "31": 2, + "32": 2, + "33": 2, + "34": 2, + "37": 0, + "42": 4, + "44": 2, + "45": 2, + "46": 2, + "49": 4, + "50": 10, + "52": 4, + "59": 5, + "61": 4, + "64": 2, + "65": 1, + "66": 1, + "68": 1, + "70": 4, + "71": 2, + "72": 2, + "73": 1, + "74": 2, + "79": 1, + "85": 1, + "86": 3, + "87": 1, + "91": 1, + "92": 4, + "93": 3, + "94": 2 + }, + "branchHits": {} + }, + { + "filename": "src/main/scala/com/example/utils/Util.scala", + "lineHits": { + "13": 2, + "8": 4, + "7": 2 + }, + "branchHits": {} + } +] diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-2.json b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-2.json new file mode 100644 index 0000000000..ddfcc729fd --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-2.json @@ -0,0 +1,3952 @@ +[ + { + "filename": "src/index.ts", + "lineHits": { + "1": 3, + "3": 3, + "5": 3, + "6": 3, + "7": 3, + "8": 3, + "9": 3, + "11": 3, + "12": 3, + "14": 3 + }, + "branchHits": {} + }, + { + "filename": "src/utils.ts", + "lineHits": { + "4": 104, + "7": 1178, + "12": 20, + "16": 2, + "29": 3105, + "33": 1601, + "37": 15, + "56": 20, + "64": 42, + "65": 2, + "1": 18, + "8": 589, + "9": 589, + "15": 1, + "18": 2, + "20": 0, + "22": 2, + "28": 18, + "30": 776, + "34": 1601, + "42": 158, + "48": 1, + "53": 15, + "57": 0, + "58": 1, + "60": 19, + "61": 19, + "63": 19, + "66": 2, + "67": 2, + "68": 2, + "69": 1, + "70": 1, + "73": 19 + }, + "branchHits": { + "8": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "57": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "68": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "69": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "73": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/controller/VideoContextPlayerCoordinator.ts", + "lineHits": { + "50": 8, + "74": 66, + "137": 33, + "143": 5, + "157": 18, + "217": 5, + "240": 5, + "309": 48, + "343": 48, + "357": 48, + "405": 8, + "420": 20, + "442": 19, + "445": 1, + "460": 20, + "466": 20, + "480": 16, + "488": 8, + "520": 16, + "530": 14, + "619": 0, + "627": 2, + "636": 0, + "640": 8, + "651": 8, + "661": 12, + "673": 37, + "690": 8, + "711": 7, + "736": 4, + "740": 29, + "1": 4, + "2": 4, + "31": 4, + "33": 4, + "37": 4, + "39": 4, + "41": 4, + "76": 33, + "77": 33, + "78": 33, + "79": 33, + "80": 33, + "81": 33, + "82": 33, + "83": 33, + "84": 33, + "85": 33, + "86": 33, + "87": 33, + "90": 33, + "91": 33, + "92": 33, + "93": 33, + "94": 33, + "95": 33, + "96": 33, + "100": 33, + "103": 33, + "106": 33, + "107": 33, + "110": 33, + "111": 33, + "112": 33, + "113": 33, + "115": 33, + "116": 33, + "118": 33, + "120": 33, + "121": 33, + "122": 0, + "128": 33, + "131": 33, + "138": 0, + "139": 0, + "147": 1, + "148": 1, + "149": 1, + "150": 1, + "159": 2, + "162": 0, + "164": 0, + "167": 1, + "171": 1, + "174": 1, + "176": 1, + "180": 1, + "183": 7, + "185": 0, + "186": 7, + "188": 7, + "189": 7, + "194": 0, + "196": 0, + "200": 0, + "201": 1, + "203": 1, + "205": 1, + "207": 1, + "209": 1, + "211": 1, + "213": 1, + "225": 1, + "233": 0, + "234": 0, + "245": 1, + "247": 0, + "250": 0, + "253": 1, + "254": 1, + "255": 0, + "258": 0, + "263": 1, + "276": 0, + "278": 1, + "283": 1, + "285": 1, + "286": 0, + "288": 1, + "289": 0, + "291": 0, + "293": 0, + "301": 1, + "315": 24, + "316": 24, + "318": 24, + "319": 24, + "322": 10, + "323": 10, + "325": 0, + "328": 0, + "332": 0, + "333": 0, + "337": 0, + "338": 0, + "341": 24, + "346": 24, + "347": 24, + "351": 24, + "352": 24, + "354": 24, + "359": 24, + "361": 24, + "362": 24, + "363": 0, + "366": 24, + "377": 24, + "378": 24, + "379": 24, + "380": 24, + "381": 24, + "383": 24, + "384": 24, + "386": 24, + "396": 24, + "397": 24, + "406": 4, + "408": 0, + "413": 4, + "418": 20, + "429": 0, + "433": 0, + "434": 0, + "435": 0, + "440": 20, + "443": 19, + "450": 1, + "451": 1, + "452": 1, + "462": 0, + "464": 20, + "468": 20, + "470": 0, + "485": 8, + "490": 0, + "491": 0, + "493": 8, + "496": 0, + "497": 0, + "500": 8, + "502": 8, + "507": 8, + "525": 8, + "527": 8, + "528": 8, + "531": 14, + "534": 0, + "535": 0, + "538": 14, + "539": 14, + "543": 8, + "544": 8, + "549": 8, + "552": 0, + "553": 1, + "554": 1, + "555": 1, + "559": 1, + "561": 1, + "562": 1, + "567": 2, + "570": 1, + "572": 2, + "574": 2, + "575": 2, + "579": 1, + "580": 1, + "582": 1, + "583": 1, + "588": 1, + "589": 1, + "592": 1, + "594": 1, + "595": 1, + "599": 0, + "600": 0, + "605": 0, + "606": 0, + "610": 0, + "615": 0, + "616": 0, + "620": 0, + "621": 0, + "625": 8, + "628": 2, + "629": 0, + "630": 2, + "632": 1, + "647": 4, + "653": 4, + "654": 4, + "656": 4, + "662": 8, + "663": 8, + "665": 0, + "666": 0, + "667": 0, + "675": 8, + "676": 8, + "679": 8, + "680": 8, + "682": 33, + "683": 33, + "684": 33, + "685": 33, + "687": 33, + "694": 4, + "695": 4, + "697": 4, + "698": 4, + "699": 4, + "700": 4, + "720": 1, + "721": 1, + "722": 1, + "726": 0, + "727": 1, + "732": 1, + "734": 2, + "737": 2, + "745": 1, + "746": 1, + "749": 1, + "750": 0, + "752": 1, + "754": 24, + "756": 4 + }, + "branchHits": { + "122": { + "covered": 0, + "missed": 1, + "available": 1 + }, + "138": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "162": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "164": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "185": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "200": { + "covered": 7, + "missed": 0, + "available": 7 + }, + "233": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "234": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "255": { + "covered": 3, + "missed": 0, + "available": 3 + }, + "283": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "286": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "289": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "291": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "293": { + "covered": 2, + "missed": 2, + "available": 4 + }, + "323": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "332": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "351": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "359": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "361": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "363": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "386": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "408": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "470": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "531": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "552": { + "covered": 5, + "missed": 3, + "available": 8 + }, + "579": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "629": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "726": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "749": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "750": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/controller/VideoContextPlayerCoordinatorFactory.ts", + "lineHits": { + "9": 8, + "11": 33, + "14": 66, + "2": 4, + "3": 4, + "4": 4, + "5": 4, + "6": 4, + "12": 33, + "15": 33, + "16": 33, + "17": 33, + "18": 33, + "19": 33, + "20": 33, + "22": 33, + "24": 33, + "25": 33, + "28": 0, + "29": 0, + "32": 33, + "36": 33, + "42": 0, + "47": 33, + "52": 33, + "62": 4 + }, + "branchHits": { + "24": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/controller/index.ts", + "lineHits": { + "1": 3, + "2": 3, + "4": 3, + "5": 3 + }, + "branchHits": {} + }, + { + "filename": "src/controller-x/VideoContextPlayerCoordinatorX.ts", + "lineHits": { + "43": 6, + "59": 60, + "99": 24, + "126": 0, + "132": 0, + "219": 4, + "233": 16, + "290": 3, + "338": 34, + "341": 17, + "362": 34, + "363": 0, + "422": 10, + "435": 8, + "444": 33, + "458": 6, + "466": 4, + "477": 4, + "507": 3, + "1": 3, + "2": 3, + "25": 3, + "26": 3, + "27": 3, + "28": 3, + "29": 3, + "31": 3, + "34": 3, + "57": 30, + "60": 30, + "61": 30, + "62": 30, + "68": 30, + "73": 30, + "74": 0, + "75": 0, + "79": 0, + "81": 30, + "83": 30, + "85": 30, + "86": 30, + "89": 30, + "90": 30, + "92": 30, + "100": 21, + "104": 21, + "109": 21, + "110": 0, + "117": 21, + "121": 21, + "123": 21, + "129": 21, + "136": 3, + "139": 11, + "141": 11, + "142": 0, + "143": 0, + "146": 5, + "147": 5, + "148": 10, + "150": 5, + "155": 5, + "158": 1, + "159": 1, + "160": 1, + "162": 1, + "164": 1, + "166": 1, + "168": 2, + "170": 2, + "174": 1, + "176": 2, + "178": 2, + "180": 1, + "182": 1, + "183": 1, + "185": 1, + "187": 1, + "189": 1, + "191": 0, + "193": 0, + "195": 0, + "198": 0, + "201": 0, + "203": 6, + "206": 3, + "209": 0, + "210": 2, + "212": 2, + "214": 2, + "216": 0, + "223": 1, + "224": 1, + "225": 1, + "226": 1, + "235": 1, + "238": 0, + "240": 0, + "243": 1, + "247": 1, + "250": 1, + "252": 1, + "256": 1, + "259": 7, + "261": 0, + "262": 7, + "264": 7, + "265": 7, + "269": 0, + "273": 0, + "274": 1, + "276": 1, + "278": 1, + "280": 1, + "282": 1, + "284": 1, + "286": 1, + "291": 0, + "293": 0, + "299": 3, + "303": 21, + "306": 21, + "307": 21, + "310": 7, + "311": 7, + "313": 0, + "316": 0, + "320": 0, + "321": 0, + "325": 0, + "328": 21, + "333": 21, + "334": 21, + "335": 21, + "337": 4, + "339": 17, + "350": 0, + "354": 0, + "355": 0, + "356": 0, + "360": 17, + "368": 4, + "371": 21, + "373": 21, + "374": 21, + "376": 21, + "379": 21, + "386": 0, + "390": 21, + "391": 21, + "392": 21, + "393": 21, + "394": 21, + "397": 21, + "398": 21, + "400": 21, + "402": 21, + "412": 0, + "415": 21, + "416": 21, + "424": 7, + "428": 7, + "430": 7, + "436": 5, + "438": 5, + "446": 0, + "447": 0, + "450": 0, + "451": 0, + "453": 30, + "454": 30, + "455": 30, + "459": 3, + "461": 2, + "462": 2, + "467": 1, + "471": 1, + "478": 0, + "479": 1, + "482": 1, + "483": 0, + "486": 1, + "487": 0, + "491": 0, + "493": 0, + "495": 0, + "499": 1, + "508": 0, + "510": 3 + }, + "branchHits": { + "110": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "139": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "182": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "209": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "238": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "240": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "261": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "273": { + "covered": 7, + "missed": 0, + "available": 7 + }, + "311": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "320": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "373": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "376": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "386": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "400": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "478": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "483": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "487": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "491": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "493": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "495": { + "covered": 3, + "missed": 1, + "available": 4 + } + } + }, + { + "filename": "src/controller-x/VideoContextPlayerCoordinatorXObserver.ts", + "lineHits": { + "5": 6, + "9": 3, + "13": 4, + "17": 7, + "24": 3, + "26": 4, + "30": 3, + "32": 3, + "34": 4, + "38": 3, + "40": 3, + "42": 3, + "44": 4, + "48": 3, + "50": 3, + "52": 3, + "54": 4, + "58": 4, + "62": 4, + "66": 4, + "70": 4, + "74": 3, + "76": 3, + "78": 3, + "2": 3, + "10": 3, + "14": 1, + "18": 4, + "20": 2, + "27": 1, + "35": 1, + "45": 1, + "55": 1, + "59": 1, + "63": 1, + "67": 1, + "71": 1, + "79": 3 + }, + "branchHits": {} + }, + { + "filename": "src/controller-x/index.ts", + "lineHits": { + "1": 3, + "2": 3 + }, + "branchHits": {} + }, + { + "filename": "src/events/InternalPlaybackObserver.ts", + "lineHits": { + "17": 22, + "21": 107, + "26": 100, + "32": 0, + "39": 0, + "42": 100, + "48": 89, + "57": 11, + "59": 0, + "63": 100, + "65": 89, + "69": 38, + "71": 27, + "75": 16, + "77": 5, + "81": 12, + "83": 1, + "87": 13, + "89": 2, + "93": 18, + "95": 7, + "99": 12, + "101": 1, + "106": 13, + "108": 2, + "113": 13, + "115": 2, + "120": 109, + "122": 98, + "126": 15, + "128": 4, + "132": 15, + "134": 4, + "138": 104, + "144": 93, + "149": 12, + "151": 1, + "156": 12, + "158": 1, + "163": 12, + "165": 1, + "170": 12, + "172": 1, + "177": 15, + "179": 4, + "184": 19, + "186": 8, + "191": 14, + "193": 3, + "22": 107, + "23": 107, + "31": 89, + "33": 0, + "47": 89, + "49": 0, + "58": 0, + "60": 0, + "64": 89, + "66": 0, + "70": 27, + "72": 0, + "76": 5, + "78": 0, + "82": 1, + "84": 0, + "88": 2, + "90": 0, + "94": 7, + "96": 0, + "100": 1, + "102": 0, + "107": 2, + "109": 0, + "114": 2, + "116": 0, + "121": 98, + "123": 0, + "127": 4, + "129": 0, + "133": 4, + "135": 0, + "143": 93, + "145": 0, + "150": 1, + "152": 0, + "157": 1, + "159": 0, + "164": 1, + "166": 0, + "171": 1, + "173": 0, + "178": 4, + "180": 0, + "185": 8, + "187": 0, + "192": 3, + "194": 0, + "197": 11 + }, + "branchHits": {} + }, + { + "filename": "src/events/PlaybackEventsObserver.ts", + "lineHits": { + "24": 22, + "28": 90, + "36": 100, + "48": 23, + "52": 17, + "56": 100, + "71": 11, + "75": 100, + "88": 38, + "97": 15, + "101": 12, + "105": 12, + "112": 13, + "116": 18, + "124": 12, + "129": 13, + "134": 13, + "142": 109, + "150": 15, + "157": 15, + "165": 104, + "177": 12, + "184": 12, + "191": 12, + "196": 12, + "204": 15, + "211": 19, + "219": 14, + "227": 472, + "13": 11, + "32": 90, + "33": 90, + "41": 89, + "49": 12, + "53": 6, + "61": 89, + "66": 89, + "72": 0, + "80": 89, + "81": 89, + "89": 27, + "90": 27, + "98": 4, + "99": 4, + "102": 1, + "103": 1, + "106": 1, + "107": 1, + "113": 2, + "114": 2, + "117": 7, + "118": 7, + "125": 1, + "126": 1, + "130": 2, + "131": 2, + "135": 2, + "136": 2, + "143": 98, + "144": 98, + "151": 4, + "152": 4, + "158": 4, + "159": 4, + "170": 93, + "171": 93, + "178": 1, + "179": 1, + "185": 1, + "186": 1, + "192": 1, + "193": 1, + "197": 1, + "198": 1, + "205": 4, + "206": 4, + "212": 8, + "213": 8, + "220": 3, + "221": 3, + "228": 461, + "229": 461, + "231": 11 + }, + "branchHits": {} + }, + { + "filename": "src/events/TimeObservable.ts", + "lineHits": { + "4": 26, + "8": 202, + "13": 101, + "14": 0, + "17": 0, + "22": 13, + "27": 0, + "31": 0, + "41": 24, + "46": 11, + "9": 101, + "10": 101, + "15": 0, + "18": 0, + "26": 0, + "28": 0, + "29": 0, + "30": 0, + "33": 0, + "34": 0, + "36": 0, + "45": 11, + "47": 0, + "48": 0, + "52": 0, + "53": 0, + "57": 13 + }, + "branchHits": {} + }, + { + "filename": "src/events/index.ts", + "lineHits": { + "1": 11, + "2": 11, + "4": 11, + "5": 11 + }, + "branchHits": {} + }, + { + "filename": "src/player/BetamaxPlayer.ts", + "lineHits": { + "25": 20, + "31": 14, + "277": 24, + "283": 890, + "288": 456, + "47": 26, + "58": 34, + "74": 34, + "76": 0, + "87": 10, + "95": 10, + "108": 10, + "121": 11, + "134": 10, + "146": 10, + "154": 11, + "162": 10, + "168": 10, + "179": 10, + "191": 0, + "203": 0, + "216": 0, + "228": 10, + "232": 27, + "244": 13, + "252": 11, + "256": 34, + "266": 459, + "8": 10, + "9": 10, + "15": 10, + "17": 10, + "35": 14, + "36": 14, + "37": 14, + "38": 14, + "48": 16, + "62": 17, + "64": 17, + "69": 17, + "77": 0, + "89": 0, + "91": 0, + "97": 0, + "99": 0, + "110": 0, + "112": 0, + "122": 1, + "124": 0, + "126": 1, + "136": 0, + "138": 0, + "148": 0, + "150": 0, + "156": 1, + "157": 1, + "158": 1, + "164": 0, + "170": 0, + "181": 0, + "183": 0, + "193": 0, + "195": 0, + "205": 0, + "207": 0, + "218": 0, + "220": 0, + "229": 0, + "233": 0, + "234": 2, + "238": 2, + "239": 2, + "240": 2, + "246": 3, + "247": 3, + "248": 3, + "253": 1, + "261": 17, + "267": 442, + "270": 17, + "271": 17, + "273": 0, + "278": 0, + "279": 1, + "284": 6, + "285": 6, + "293": 442, + "295": 10 + }, + "branchHits": { + "35": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "229": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "233": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "238": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "278": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/player/BetamaxPlayerFactory.ts", + "lineHits": { + "6": 20, + "9": 68, + "15": 78, + "2": 10, + "3": 10, + "12": 68, + "16": 68, + "19": 68, + "21": 10 + }, + "branchHits": {} + }, + { + "filename": "src/player/PlaybackSession.ts", + "lineHits": { + "50": 20, + "71": 90, + "165": 182, + "170": 2, + "177": 179, + "179": 102, + "90": 91, + "136": 100, + "146": 103, + "185": 178, + "189": 178, + "301": 0, + "310": 0, + "324": 89, + "334": 178, + "339": 979, + "343": 445, + "349": 14, + "351": 44, + "355": 20, + "361": 10, + "365": 15, + "392": 178, + "443": 0, + "458": 14, + "485": 99, + "501": 11, + "514": 14, + "525": 11, + "529": 23, + "558": 29, + "567": 24, + "571": 25, + "581": 15, + "596": 14, + "608": 37, + "619": 10, + "623": 110, + "714": 18, + "719": 16, + "762": 11, + "768": 12, + "782": 13, + "803": 195, + "840": 11, + "844": 180, + "849": 180, + "860": 16, + "869": 221, + "875": 18, + "879": 4, + "885": 18, + "922": 13, + "939": 11, + "952": 101, + "965": 1572, + "969": 784, + "983": 11, + "987": 11, + "991": 19, + "1026": 106, + "1035": 16, + "1040": 18, + "1076": 10, + "1123": 16, + "1134": 11, + "1138": 100, + "1142": 0, + "1146": 0, + "1150": 0, + "1154": 2, + "1158": 0, + "1": 10, + "7": 10, + "8": 10, + "9": 10, + "10": 10, + "11": 10, + "33": 10, + "34": 10, + "42": 10, + "44": 10, + "45": 10, + "48": 10, + "75": 90, + "76": 90, + "77": 90, + "78": 90, + "83": 1, + "87": 1, + "92": 1, + "96": 1, + "97": 1, + "101": 90, + "111": 90, + "116": 90, + "128": 90, + "143": 90, + "150": 1, + "153": 1, + "156": 1, + "159": 1, + "162": 89, + "167": 182, + "169": 92, + "171": 2, + "172": 0, + "181": 0, + "191": 89, + "195": 89, + "199": 89, + "201": 89, + "204": 89, + "208": 89, + "212": 89, + "216": 1, + "220": 1, + "222": 1, + "229": 1, + "232": 89, + "233": 89, + "235": 89, + "236": 89, + "241": 89, + "243": 0, + "245": 89, + "247": 0, + "253": 0, + "259": 89, + "266": 89, + "267": 89, + "268": 89, + "269": 89, + "271": 89, + "273": 89, + "276": 89, + "283": 89, + "286": 89, + "290": 89, + "295": 89, + "300": 89, + "302": 0, + "308": 0, + "312": 0, + "313": 0, + "314": 0, + "316": 0, + "325": 89, + "328": 89, + "329": 89, + "330": 89, + "335": 89, + "340": 890, + "344": 356, + "350": 4, + "352": 40, + "356": 16, + "362": 0, + "368": 3, + "369": 3, + "370": 0, + "374": 2, + "375": 2, + "383": 1, + "384": 1, + "393": 89, + "409": 0, + "410": 0, + "411": 0, + "413": 0, + "426": 10, + "428": 0, + "431": 0, + "434": 3, + "436": 3, + "437": 0, + "440": 0, + "441": 0, + "442": 0, + "444": 0, + "445": 0, + "449": 0, + "451": 2, + "454": 1, + "460": 0, + "465": 1, + "471": 0, + "476": 2, + "477": 0, + "479": 2, + "480": 2, + "486": 89, + "487": 89, + "488": 0, + "489": 1, + "492": 1, + "494": 89, + "502": 1, + "505": 1, + "507": 1, + "515": 4, + "516": 4, + "517": 4, + "522": 4, + "526": 1, + "530": 0, + "532": 1, + "535": 12, + "537": 12, + "538": 12, + "540": 12, + "549": 12, + "550": 12, + "553": 2, + "554": 2, + "559": 19, + "560": 0, + "561": 16, + "562": 16, + "564": 19, + "572": 0, + "574": 6, + "582": 5, + "583": 5, + "590": 4, + "592": 1, + "597": 4, + "601": 4, + "602": 4, + "604": 2, + "609": 27, + "610": 27, + "611": 27, + "612": 27, + "620": 0, + "625": 99, + "639": 100, + "640": 100, + "642": 0, + "643": 6, + "646": 0, + "647": 6, + "650": 100, + "652": 100, + "653": 100, + "654": 100, + "657": 0, + "663": 2, + "664": 2, + "665": 2, + "668": 100, + "671": 0, + "677": 2, + "680": 100, + "683": 100, + "684": 0, + "693": 2, + "695": 98, + "698": 0, + "699": 84, + "701": 100, + "711": 100, + "715": 0, + "716": 0, + "721": 1, + "723": 7, + "726": 2, + "742": 4, + "749": 4, + "755": 5, + "763": 1, + "771": 1, + "774": 1, + "775": 1, + "784": 3, + "787": 3, + "793": 3, + "806": 93, + "808": 6, + "810": 93, + "816": 93, + "823": 0, + "827": 4, + "833": 92, + "841": 1, + "846": 0, + "850": 90, + "851": 90, + "853": 90, + "854": 90, + "861": 6, + "862": 6, + "863": 6, + "864": 6, + "865": 6, + "866": 6, + "870": 211, + "871": 0, + "877": 2, + "880": 2, + "882": 6, + "887": 8, + "888": 8, + "892": 1, + "895": 7, + "896": 7, + "897": 7, + "899": 4, + "900": 4, + "909": 2, + "912": 0, + "915": 0, + "919": 7, + "927": 0, + "929": 3, + "930": 0, + "933": 3, + "936": 0, + "941": 0, + "946": 1, + "949": 0, + "954": 1, + "955": 1, + "957": 90, + "958": 90, + "960": 91, + "961": 91, + "962": 91, + "966": 1562, + "970": 774, + "971": 774, + "972": 774, + "975": 563, + "978": 774, + "984": 1, + "988": 1, + "992": 9, + "995": 0, + "997": 9, + "999": 2, + "1005": 1, + "1008": 9, + "1013": 9, + "1014": 9, + "1021": 9, + "1023": 9, + "1029": 96, + "1030": 96, + "1031": 96, + "1032": 96, + "1036": 6, + "1037": 6, + "1041": 8, + "1042": 8, + "1046": 8, + "1048": 8, + "1052": 8, + "1054": 0, + "1055": 0, + "1056": 0, + "1058": 0, + "1064": 8, + "1069": 0, + "1073": 8, + "1078": 0, + "1084": 10, + "1085": 4, + "1086": 0, + "1087": 0, + "1089": 4, + "1091": 4, + "1093": 4, + "1094": 4, + "1099": 4, + "1100": 0, + "1101": 0, + "1102": 0, + "1105": 8, + "1106": 0, + "1108": 0, + "1112": 0, + "1115": 4, + "1117": 4, + "1118": 4, + "1119": 4, + "1125": 6, + "1135": 1, + "1139": 90, + "1143": 0, + "1147": 0, + "1151": 0, + "1155": 2, + "1159": 0, + "1161": 10 + }, + "branchHits": { + "75": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "167": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "172": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "243": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "247": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "370": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "409": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "410": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "411": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "413": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "428": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "440": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "460": { + "covered": 4, + "missed": 0, + "available": 4 + }, + "471": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "477": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "488": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "530": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "535": { + "covered": 3, + "missed": 0, + "available": 3 + }, + "560": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "572": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "609": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "610": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "642": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "646": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "657": { + "covered": 3, + "missed": 0, + "available": 3 + }, + "671": { + "covered": 5, + "missed": 0, + "available": 5 + }, + "683": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "684": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "698": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "715": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "808": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "823": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "870": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "871": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "880": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "912": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "927": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "930": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "941": { + "covered": 4, + "missed": 0, + "available": 4 + }, + "966": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "997": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "1086": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "1087": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "1101": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "1159": { + "covered": 0, + "missed": 2, + "available": 2 + } + } + }, + { + "filename": "src/player/PlaybackSessionFactory.ts", + "lineHits": { + "10": 20, + "13": 68, + "19": 27, + "70": 17, + "2": 10, + "3": 10, + "4": 10, + "16": 68, + "23": 17, + "25": 0, + "33": 0, + "34": 0, + "35": 0, + "36": 0, + "37": 0, + "38": 0, + "39": 0, + "42": 0, + "53": 0, + "62": 0, + "63": 0, + "68": 17, + "71": 0, + "72": 17, + "78": 10 + }, + "branchHits": { + "23": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "33": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "62": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/player/index.ts", + "lineHits": { + "1": 10, + "2": 10, + "3": 10, + "4": 10, + "5": 10, + "6": 10 + }, + "branchHits": {} + }, + { + "filename": "src/player/player.ts", + "lineHits": { + "9": 24, + "12": 89, + "16": 101, + "18": 89, + "25": 198, + "29": 101, + "37": 12, + "41": 12, + "45": 12, + "49": 12, + "53": 38, + "57": 368, + "61": 28, + "65": 12, + "69": 12, + "73": 12, + "1": 12, + "4": 12, + "5": 12, + "13": 89, + "19": 0, + "22": 89, + "26": 186, + "34": 89, + "38": 0, + "42": 0, + "46": 0, + "50": 0, + "54": 26, + "58": 356, + "62": 16, + "66": 0, + "70": 0, + "74": 0, + "76": 12 + }, + "branchHits": {} + }, + { + "filename": "src/player/shaka.ts", + "lineHits": { + "2": 13, + "5": 13, + "6": 0, + "7": 0, + "10": 13 + }, + "branchHits": { + "6": { + "covered": 2, + "missed": 1, + "available": 3 + } + } + }, + { + "filename": "src/plugins/SPManifestParser.ts", + "lineHits": { + "26": 5, + "40": 14, + "45": 14, + "60": 10, + "67": 9, + "70": 9, + "75": 9, + "87": 14, + "94": 10, + "113": 14, + "152": 14, + "159": 13, + "173": 14, + "175": 44, + "186": 14, + "191": 23, + "211": 0, + "218": 0, + "226": 18, + "227": 26, + "242": 22, + "281": 14, + "289": 16, + "298": 13, + "313": 43, + "332": 0, + "366": 52, + "367": 28, + "368": 6, + "388": 68, + "399": 10, + "405": 4, + "461": 7944, + "467": 3974, + "468": 6, + "18": 9, + "27": 5, + "28": 5, + "29": 5, + "30": 5, + "31": 5, + "32": 5, + "33": 5, + "34": 5, + "35": 5, + "36": 5, + "41": 5, + "47": 0, + "50": 5, + "59": 5, + "61": 5, + "62": 5, + "88": 5, + "91": 5, + "92": 5, + "95": 5, + "98": 5, + "114": 5, + "117": 0, + "120": 0, + "122": 0, + "130": 5, + "134": 0, + "141": 5, + "153": 5, + "154": 5, + "156": 5, + "160": 13, + "174": 5, + "188": 5, + "189": 5, + "192": 18, + "194": 0, + "195": 13, + "196": 13, + "198": 5, + "199": 5, + "201": 0, + "206": 0, + "207": 0, + "210": 0, + "217": 0, + "225": 5, + "228": 13, + "231": 5, + "247": 13, + "249": 13, + "250": 0, + "252": 13, + "257": 0, + "260": 0, + "265": 0, + "284": 5, + "286": 0, + "299": 8, + "319": 34, + "322": 34, + "324": 13, + "327": 13, + "330": 34, + "333": 0, + "338": 0, + "343": 0, + "344": 0, + "345": 0, + "348": 0, + "369": 4, + "373": 2, + "376": 26, + "393": 34, + "395": 34, + "396": 34, + "400": 2, + "402": 0, + "406": 2, + "412": 2, + "417": 8, + "428": 26, + "430": 26, + "431": 26, + "433": 3972, + "439": 3972, + "440": 3972, + "441": 3972, + "446": 34, + "448": 34, + "469": 4, + "474": 2, + "477": 3972, + "487": 9 + }, + "branchHits": { + "194": { + "covered": 2, + "missed": 1, + "available": 3 + }, + "206": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "210": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "217": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "247": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "249": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "250": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "257": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "260": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "265": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "286": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "338": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "343": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "344": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "345": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "348": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/plugins/SpotifyVideoMediaExtension.ts", + "lineHits": { + "9": 16, + "12": 59, + "29": 10, + "34": 12, + "38": 10, + "2": 8, + "3": 8, + "13": 59, + "14": 59, + "18": 59, + "22": 59, + "23": 59, + "30": 2, + "31": 2, + "35": 4, + "42": 2, + "46": 8 + }, + "branchHits": {} + }, + { + "filename": "src/plugins/SpotifyVideoUrl.ts", + "lineHits": { + "7": 16, + "8": 39, + "1": 8, + "9": 31, + "11": 8 + }, + "branchHits": {} + }, + { + "filename": "src/plugins/TextParser.js", + "lineHits": { + "25": 0, + "37": 8, + "47": 8, + "57": 8, + "64": 8, + "78": 8, + "96": 8, + "116": 8, + "30": 0, + "33": 0, + "38": 0, + "48": 0, + "58": 0, + "65": 0, + "79": 0, + "80": 0, + "81": 0, + "84": 0, + "85": 0, + "98": 0, + "101": 0, + "103": 0, + "105": 0, + "117": 0, + "118": 0, + "120": 0, + "122": 0, + "130": 8 + }, + "branchHits": { + "80": { + "covered": 0, + "missed": 3, + "available": 3 + } + } + }, + { + "filename": "src/plugins/VttTextParser.js", + "lineHits": { + "26": 0, + "29": 8, + "37": 8, + "121": 8, + "144": 8, + "223": 8, + "260": 8, + "261": 0, + "285": 8, + "299": 8, + "315": 8, + "330": 8, + "362": 8, + "19": 8, + "20": 8, + "30": 0, + "38": 0, + "40": 0, + "41": 0, + "42": 0, + "45": 0, + "52": 0, + "60": 0, + "72": 0, + "76": 0, + "77": 0, + "78": 0, + "79": 0, + "80": 0, + "81": 0, + "84": 0, + "91": 0, + "92": 0, + "93": 0, + "95": 0, + "96": 0, + "101": 0, + "102": 0, + "103": 0, + "104": 0, + "106": 0, + "110": 0, + "122": 0, + "126": 0, + "129": 0, + "130": 0, + "132": 0, + "145": 0, + "148": 0, + "149": 0, + "154": 0, + "159": 0, + "162": 0, + "163": 0, + "165": 0, + "166": 0, + "170": 0, + "171": 0, + "172": 0, + "173": 0, + "175": 0, + "176": 0, + "183": 0, + "184": 0, + "187": 0, + "192": 0, + "195": 0, + "196": 0, + "199": 0, + "205": 0, + "206": 0, + "210": 0, + "212": 0, + "224": 0, + "225": 0, + "227": 0, + "229": 0, + "231": 0, + "237": 0, + "239": 0, + "242": 0, + "244": 0, + "247": 0, + "250": 0, + "262": 0, + "265": 0, + "270": 0, + "274": 0, + "277": 0, + "286": 0, + "288": 0, + "290": 0, + "300": 0, + "301": 0, + "302": 0, + "303": 0, + "304": 0, + "306": 0, + "316": 0, + "318": 0, + "320": 0, + "334": 0, + "335": 0, + "337": 0, + "338": 0, + "340": 0, + "343": 0, + "344": 0, + "346": 0, + "349": 0, + "352": 0, + "364": 0, + "366": 0, + "370": 0, + "371": 0, + "372": 0, + "373": 0, + "374": 0, + "375": 0, + "378": 0, + "385": 8, + "387": 8 + }, + "branchHits": { + "77": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "148": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "175": { + "covered": 0, + "missed": 3, + "available": 3 + }, + "301": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "303": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "370": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "374": { + "covered": 0, + "missed": 2, + "available": 2 + } + } + }, + { + "filename": "src/plugins/WidevineDownloader.ts", + "lineHits": { + "14": 14, + "21": 14, + "190": 12, + "34": 11, + "40": 4, + "44": 5, + "66": 4, + "69": 0, + "78": 9, + "90": 8, + "107": 11, + "137": 2, + "147": 1, + "165": 14, + "174": 8, + "2": 7, + "9": 7, + "10": 7, + "11": 7, + "12": 7, + "22": 7, + "26": 7, + "27": 7, + "28": 7, + "29": 7, + "36": 0, + "38": 4, + "41": 4, + "46": 0, + "49": 1, + "51": 0, + "59": 0, + "63": 0, + "64": 0, + "70": 0, + "80": 0, + "84": 1, + "86": 1, + "91": 1, + "92": 1, + "93": 1, + "94": 1, + "108": 4, + "111": 0, + "112": 2, + "113": 2, + "120": 1, + "121": 1, + "128": 1, + "129": 1, + "133": 0, + "136": 1, + "139": 1, + "140": 1, + "150": 0, + "152": 0, + "153": 0, + "166": 7, + "171": 0, + "172": 0, + "177": 7, + "179": 6, + "181": 3, + "182": 3, + "183": 3, + "184": 3, + "185": 3, + "187": 3, + "189": 3, + "191": 6, + "193": 3, + "198": 7, + "200": 3, + "201": 1, + "202": 1, + "203": 1, + "205": 1, + "207": 7 + }, + "branchHits": { + "59": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "80": { + "covered": 2, + "missed": 3, + "available": 5 + }, + "111": { + "covered": 4, + "missed": 6, + "available": 10 + }, + "179": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "184": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/plugins/index.ts", + "lineHits": { + "1": 8, + "2": 8, + "3": 8, + "4": 8, + "6": 8, + "7": 8, + "8": 8 + }, + "branchHits": {} + }, + { + "filename": "src/plugins/types.ts", + "lineHits": { + "19": 14, + "20": 7, + "21": 7, + "22": 7, + "23": 7, + "24": 7, + "25": 7, + "26": 7, + "27": 7, + "28": 7, + "29": 7, + "30": 7 + }, + "branchHits": { + "19": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/DefaultEventsCalculator.ts", + "lineHits": { + "34": 108, + "46": 7, + "95": 68, + "108": 17, + "116": 17, + "124": 92, + "145": 92, + "164": 41, + "168": 48, + "181": 41, + "185": 6, + "194": 41, + "198": 2, + "207": 42, + "215": 4, + "229": 41, + "233": 2, + "242": 42, + "246": 50, + "255": 44, + "259": 12, + "276": 42, + "284": 2, + "298": 41, + "302": 2, + "311": 42, + "315": 10, + "326": 42, + "334": 2, + "348": 43, + "352": 22, + "386": 42, + "398": 10, + "417": 45, + "475": 43, + "479": 83, + "483": 86, + "496": 41, + "500": 76, + "505": 86, + "522": 41, + "526": 76, + "531": 86, + "548": 39, + "1": 16, + "11": 16, + "12": 16, + "13": 16, + "37": 35, + "39": 0, + "40": 19, + "43": 0, + "51": 7, + "52": 7, + "55": 0, + "57": 0, + "58": 3, + "65": 3, + "69": 3, + "71": 3, + "78": 2, + "82": 3, + "84": 1, + "87": 1, + "89": 0, + "92": 7, + "99": 52, + "100": 52, + "109": 1, + "111": 1, + "113": 0, + "117": 1, + "119": 1, + "128": 76, + "129": 76, + "130": 0, + "132": 1, + "134": 0, + "136": 1, + "140": 1, + "142": 76, + "149": 76, + "150": 76, + "151": 0, + "152": 1, + "154": 0, + "155": 1, + "159": 1, + "161": 76, + "167": 25, + "184": 25, + "197": 25, + "210": 26, + "214": 26, + "216": 4, + "222": 0, + "232": 25, + "245": 26, + "258": 28, + "261": 0, + "262": 0, + "265": 0, + "266": 0, + "279": 26, + "283": 26, + "285": 2, + "291": 0, + "301": 25, + "314": 26, + "317": 0, + "329": 26, + "333": 26, + "335": 2, + "341": 0, + "351": 27, + "354": 5, + "365": 6, + "375": 0, + "389": 26, + "390": 26, + "397": 26, + "399": 5, + "400": 5, + "433": 86, + "435": 0, + "439": 5, + "444": 3, + "450": 9, + "451": 9, + "454": 9, + "457": 0, + "461": 4, + "466": 4, + "467": 4, + "468": 4, + "472": 29, + "478": 27, + "480": 83, + "499": 25, + "501": 76, + "507": 76, + "508": 76, + "525": 25, + "527": 76, + "533": 76, + "534": 76, + "551": 23 + }, + "branchHits": { + "39": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "55": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "57": { + "covered": 3, + "missed": 1, + "available": 4 + }, + "113": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "129": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "130": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "134": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "150": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "151": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "154": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "222": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "261": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "262": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "265": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "266": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "291": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "317": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "341": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "435": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "457": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/EventsTracker.ts", + "lineHits": { + "16": 32, + "19": 15, + "23": 17, + "40": 17, + "53": 17, + "63": 17, + "71": 17, + "86": 16, + "101": 28, + "117": 16, + "130": 21, + "145": 19, + "160": 25, + "170": 19, + "180": 21, + "195": 17, + "210": 17, + "225": 17, + "240": 17, + "248": 17, + "256": 17, + "271": 17, + "286": 17, + "301": 17, + "14": 16, + "20": 15, + "29": 1, + "44": 1, + "54": 1, + "64": 1, + "76": 1, + "91": 0, + "107": 12, + "121": 0, + "135": 5, + "150": 3, + "161": 9, + "171": 3, + "185": 5, + "200": 1, + "215": 1, + "230": 1, + "241": 1, + "249": 1, + "261": 1, + "276": 1, + "291": 1, + "302": 1, + "310": 16 + }, + "branchHits": {} + }, + { + "filename": "src/tracking/ProductStatesStreamingRulesProvider.ts", + "lineHits": { + "4": 32, + "9": 6, + "14": 2, + "17": 0, + "21": 20, + "10": 3, + "11": 3, + "12": 3, + "15": 2, + "22": 4, + "24": 16 + }, + "branchHits": {} + }, + { + "filename": "src/tracking/VideoPlaybackEvents.ts", + "lineHits": { + "1": 36, + "7": 36, + "17": 36, + "2": 18, + "3": 18, + "4": 18, + "8": 18, + "9": 18, + "10": 18, + "13": 18, + "18": 18, + "19": 18, + "20": 18, + "21": 18, + "22": 18, + "23": 18, + "24": 18, + "25": 18, + "26": 18, + "27": 18, + "28": 18, + "29": 18, + "30": 18, + "31": 18, + "32": 18, + "33": 18, + "34": 18, + "35": 18, + "36": 18, + "37": 18, + "38": 18, + "39": 18, + "40": 18, + "41": 18, + "42": 18, + "45": 18 + }, + "branchHits": { + "1": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "7": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "17": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/index.ts", + "lineHits": { + "1": 15, + "2": 15, + "3": 15, + "4": 15, + "5": 15, + "7": 15, + "8": 15, + "9": 15, + "11": 15, + "12": 15, + "13": 15, + "15": 15, + "16": 15 + }, + "branchHits": {} + }, + { + "filename": "src/tracking/types.ts", + "lineHits": { + "13": 32, + "95": 32, + "10": 16, + "14": 16, + "15": 16, + "16": 16, + "17": 16, + "18": 16, + "19": 16, + "20": 16, + "21": 16, + "22": 16, + "23": 16, + "24": 16, + "25": 16, + "26": 16, + "27": 16, + "28": 16, + "29": 16, + "30": 16, + "31": 16, + "32": 16, + "33": 16, + "34": 16, + "35": 16, + "36": 16, + "37": 16, + "38": 16, + "39": 16, + "40": 16, + "41": 16, + "42": 16, + "43": 16, + "44": 16, + "45": 16, + "46": 16, + "96": 16, + "97": 16, + "98": 16, + "99": 16, + "100": 16, + "101": 16, + "102": 16, + "103": 16, + "104": 16, + "105": 16, + "106": 16, + "107": 16, + "108": 16, + "109": 16, + "110": 16, + "111": 16, + "112": 16, + "113": 16, + "114": 16, + "115": 16, + "116": 16, + "117": 16, + "118": 16, + "119": 16, + "120": 16, + "121": 16, + "122": 16, + "123": 16, + "124": 16, + "125": 16, + "126": 16, + "127": 16, + "128": 16, + "129": 16, + "130": 16, + "131": 16, + "132": 16, + "133": 16, + "134": 16, + "135": 16, + "136": 16, + "137": 16, + "138": 16, + "139": 16, + "140": 16, + "141": 16, + "142": 16, + "143": 16, + "144": 16, + "145": 16, + "146": 16, + "147": 16, + "148": 16 + }, + "branchHits": { + "13": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "95": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/utils.ts", + "lineHits": { + "44": 64, + "109": 225, + "113": 1944, + "115": 1902, + "123": 514, + "128": 486, + "133": 91, + "138": 95, + "143": 239, + "148": 314, + "153": 167, + "158": 91, + "163": 91, + "168": 261, + "173": 167, + "178": 17, + "183": 139, + "188": 93, + "193": 475, + "198": 61, + "203": 95, + "208": 19, + "220": 1501, + "224": 484, + "228": 462, + "232": 900, + "236": 113, + "245": 96, + "250": 460, + "251": 56, + "254": 46, + "259": 158, + "261": 19, + "269": 78, + "2": 17, + "4": 17, + "7": 17, + "9": 17, + "11": 17, + "12": 17, + "13": 17, + "14": 17, + "15": 17, + "16": 17, + "17": 17, + "18": 17, + "19": 17, + "20": 17, + "21": 17, + "22": 17, + "23": 17, + "24": 17, + "26": 17, + "42": 17, + "47": 47, + "48": 47, + "53": 47, + "58": 47, + "63": 47, + "64": 47, + "69": 47, + "74": 47, + "75": 47, + "76": 47, + "77": 47, + "78": 47, + "100": 17, + "102": 17, + "104": 17, + "112": 208, + "126": 497, + "131": 469, + "136": 74, + "141": 78, + "146": 222, + "151": 297, + "156": 150, + "161": 74, + "166": 74, + "171": 244, + "176": 150, + "181": 0, + "186": 122, + "191": 76, + "196": 458, + "201": 44, + "206": 78, + "209": 2, + "211": 17, + "222": 497, + "226": 132, + "230": 110, + "234": 248, + "237": 96, + "239": 96, + "249": 79, + "258": 29, + "262": 19, + "263": 0, + "270": 0, + "271": 0, + "273": 61, + "274": 0, + "275": 0, + "277": 61 + }, + "branchHits": { + "209": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "222": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "226": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "230": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "234": { + "covered": 4, + "missed": 0, + "available": 4 + }, + "263": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "270": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "274": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/endvideo/EndVideoEventsCalculator.ts", + "lineHits": { + "39": 24, + "52": 11, + "71": 6, + "79": 14, + "88": 11, + "92": 19, + "120": 28, + "123": 36, + "145": 20, + "181": 36, + "190": 27, + "206": 25, + "223": 26, + "240": 26, + "258": 42, + "264": 48, + "272": 42, + "276": 2, + "285": 42, + "289": 2, + "298": 43, + "306": 50, + "328": 40, + "332": 46, + "341": 45, + "345": 4, + "356": 43, + "361": 50, + "371": 43, + "375": 89, + "380": 86, + "394": 43, + "398": 87, + "403": 90, + "416": 46, + "420": 91, + "425": 88, + "442": 40, + "1": 15, + "8": 15, + "9": 15, + "28": 15, + "36": 15, + "37": 15, + "41": 0, + "42": 5, + "44": 0, + "46": 0, + "48": 19, + "57": 8, + "61": 0, + "64": 0, + "66": 0, + "68": 3, + "76": 1, + "78": 5, + "81": 7, + "82": 7, + "89": 11, + "94": 11, + "95": 11, + "97": 8, + "99": 0, + "103": 0, + "105": 0, + "106": 1, + "110": 1, + "113": 3, + "114": 3, + "116": 4, + "127": 21, + "128": 0, + "129": 5, + "133": 5, + "134": 5, + "135": 5, + "140": 21, + "141": 21, + "142": 21, + "149": 5, + "151": 5, + "153": 5, + "157": 5, + "159": 0, + "160": 4, + "161": 0, + "162": 1, + "166": 1, + "167": 1, + "168": 1, + "169": 1, + "174": 0, + "175": 0, + "177": 5, + "178": 5, + "184": 21, + "191": 12, + "193": 12, + "211": 10, + "212": 10, + "215": 10, + "228": 11, + "229": 11, + "232": 11, + "241": 11, + "248": 11, + "249": 11, + "261": 27, + "265": 24, + "266": 0, + "275": 27, + "288": 27, + "301": 28, + "305": 28, + "308": 13, + "310": 0, + "312": 13, + "316": 0, + "320": 12, + "331": 25, + "344": 30, + "347": 0, + "359": 28, + "360": 28, + "363": 0, + "374": 28, + "376": 89, + "397": 28, + "399": 87, + "419": 31, + "421": 91, + "445": 25, + "446": 25, + "489": 25 + }, + "branchHits": { + "41": { + "covered": 2, + "missed": 2, + "available": 4 + }, + "105": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "128": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "159": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "161": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "174": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "266": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "310": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "316": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "347": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "363": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/endvideo/EndVideoLoggerFactory.ts", + "lineHits": { + "11": 30, + "19": 14, + "32": 29, + "9": 15, + "26": 14, + "27": 14, + "28": 14, + "29": 14, + "30": 14, + "33": 14, + "41": 15 + }, + "branchHits": {} + }, + { + "filename": "src/tracking/endvideo/EndVideoLoggerTracker.ts", + "lineHits": { + "24": 30, + "38": 14, + "54": 14, + "62": 0, + "96": 0, + "139": 24, + "140": 18, + "141": 18, + "154": 40, + "155": 40, + "156": 40, + "166": 35, + "177": 38, + "1": 15, + "4": 15, + "15": 15, + "16": 15, + "17": 15, + "18": 15, + "21": 15, + "22": 15, + "35": 14, + "45": 14, + "46": 14, + "47": 14, + "48": 14, + "49": 14, + "50": 14, + "52": 14, + "53": 14, + "56": 0, + "57": 0, + "59": 0, + "60": 0, + "61": 0, + "64": 0, + "67": 0, + "73": 15, + "79": 11, + "85": 11, + "86": 0, + "90": 3, + "91": 16, + "94": 11, + "97": 0, + "102": 15, + "107": 2, + "108": 2, + "109": 0, + "111": 4, + "114": 15, + "115": 2, + "116": 2, + "118": 4, + "121": 15, + "122": 7, + "123": 7, + "124": 14, + "127": 15, + "132": 4, + "133": 8, + "135": 3, + "143": 0, + "144": 0, + "145": 0, + "147": 9, + "148": 9, + "149": 9, + "158": 0, + "159": 0, + "161": 20, + "178": 23, + "179": 0, + "184": 15, + "187": 23, + "194": 3, + "197": 11, + "198": 18, + "201": 20, + "205": 40, + "208": 15, + "209": 19, + "218": 38, + "220": 15 + }, + "branchHits": { + "45": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "86": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "109": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "179": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/endvideo/EndVideoReasonEnd.ts", + "lineHits": { + "1": 30, + "2": 15, + "3": 15, + "4": 15, + "5": 15, + "6": 15, + "7": 15, + "8": 15, + "11": 15 + }, + "branchHits": { + "1": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/endvideo/EndVideoTracker.ts", + "lineHits": { + "24": 30, + "64": 13, + "78": 28, + "110": 26, + "118": 27, + "131": 79, + "237": 21, + "255": 44, + "287": 28, + "295": 22, + "355": 20, + "364": 28, + "417": 28, + "419": 17, + "430": 28, + "438": 24, + "458": 25, + "1": 15, + "2": 15, + "15": 15, + "20": 15, + "71": 13, + "72": 13, + "73": 13, + "74": 13, + "75": 13, + "79": 13, + "80": 13, + "81": 13, + "82": 13, + "83": 13, + "84": 13, + "85": 13, + "86": 13, + "87": 13, + "88": 13, + "89": 13, + "90": 13, + "91": 13, + "92": 13, + "93": 13, + "94": 13, + "95": 13, + "96": 13, + "97": 13, + "98": 13, + "99": 13, + "100": 13, + "101": 13, + "102": 13, + "103": 13, + "104": 13, + "105": 13, + "106": 13, + "108": 13, + "109": 13, + "112": 0, + "113": 0, + "115": 13, + "116": 13, + "117": 13, + "120": 14, + "123": 14, + "128": 13, + "133": 5, + "135": 64, + "136": 0, + "138": 0, + "139": 55, + "140": 55, + "141": 55, + "142": 55, + "143": 0, + "146": 0, + "147": 6, + "149": 0, + "150": 1, + "154": 10, + "157": 10, + "166": 64, + "167": 64, + "168": 64, + "170": 0, + "171": 7, + "174": 2, + "177": 2, + "178": 2, + "184": 3, + "185": 3, + "186": 3, + "190": 0, + "191": 0, + "193": 0, + "194": 0, + "197": 64, + "199": 21, + "201": 64, + "203": 2, + "204": 0, + "205": 1, + "209": 3, + "215": 3, + "218": 0, + "219": 10, + "226": 10, + "227": 10, + "229": 10, + "230": 0, + "231": 10, + "233": 10, + "238": 6, + "245": 6, + "247": 3, + "248": 3, + "250": 3, + "251": 3, + "262": 27, + "264": 16, + "269": 27, + "272": 17, + "274": 10, + "283": 27, + "288": 13, + "289": 13, + "290": 13, + "291": 13, + "292": 13, + "293": 13, + "297": 6, + "299": 1, + "301": 2, + "303": 13, + "304": 13, + "305": 17, + "306": 17, + "307": 17, + "310": 12, + "311": 12, + "313": 5, + "314": 5, + "317": 10, + "319": 7, + "320": 7, + "322": 17, + "324": 13, + "328": 0, + "330": 10, + "333": 4, + "335": 6, + "339": 13, + "342": 6, + "347": 13, + "357": 0, + "358": 1, + "360": 4, + "365": 13, + "366": 13, + "367": 0, + "369": 13, + "377": 0, + "405": 0, + "418": 13, + "421": 0, + "422": 0, + "425": 1, + "432": 0, + "436": 12, + "440": 0, + "441": 0, + "442": 0, + "444": 12, + "445": 12, + "446": 12, + "448": 12, + "452": 0, + "455": 1, + "460": 0, + "462": 10, + "463": 10, + "464": 10, + "466": 15 + }, + "branchHits": { + "136": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "138": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "143": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "146": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "149": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "166": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "168": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "170": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "190": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "193": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "204": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "218": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "226": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "227": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "230": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "357": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "360": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "367": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "377": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "405": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/session/PlaybackSessionTracker.ts", + "lineHits": { + "7": 32, + "9": 1, + "14": 17, + "1": 16, + "10": 1, + "11": 1, + "19": 1, + "21": 1, + "22": 1, + "25": 16 + }, + "branchHits": { + "10": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/tracking/session/VideoPlaybackSessionLogger.ts", + "lineHits": { + "6": 30, + "9": 0, + "12": 15, + "13": 0, + "3": 15, + "4": 15, + "10": 0, + "14": 0, + "15": 0, + "18": 15 + }, + "branchHits": {} + } +] diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-3.json b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-3.json new file mode 100644 index 0000000000..625dcde1a0 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-3.json @@ -0,0 +1,297 @@ +[ + { + "filename": "src/atoms/BoxShadow/box-shadow.ts", + "lineHits": { + "4": 5 + }, + "branchHits": {} + }, + { + "filename": "src/atoms/Button/button.tsx", + "lineHits": { + "17": 41, + "34": 41, + "70": 82, + "72": 82, + "74": 41, + "31": 41, + "32": 41, + "35": 0, + "36": 0, + "37": 0, + "38": 0, + "39": 0, + "40": 0, + "41": 0, + "42": 0, + "43": 0, + "47": 41, + "68": 10, + "75": 41 + }, + "branchHits": { + "35": { + "covered": 0, + "missed": 4, + "available": 4 + }, + "70": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "72": { + "covered": 3, + "missed": 0, + "available": 3 + }, + "75": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/atoms/Container/components.ts", + "lineHits": { + "5": 70, + "19": 70, + "20": 70, + "23": 70, + "4": 13, + "13": 13 + }, + "branchHits": {} + }, + { + "filename": "src/atoms/Container/container.tsx", + "lineHits": { + "12": 35, + "20": 35 + }, + "branchHits": {} + }, + { + "filename": "src/atoms/DownArrow/down-arrow.tsx", + "lineHits": { + "3": 28, + "4": 28 + }, + "branchHits": {} + }, + { + "filename": "src/molecules/Hero/components.ts", + "lineHits": { + "26": 20, + "28": 10, + "94": 10, + "103": 20, + "121": 10, + "182": 20, + "203": 5, + "218": 5, + "236": 10, + "241": 10, + "249": 8, + "254": 4, + "264": 4, + "277": 8, + "282": 4, + "294": 8, + "299": 6, + "25": 2, + "29": 10, + "37": 3, + "39": 3, + "40": 3, + "42": 3, + "43": 1, + "44": 1, + "45": 0, + "46": 0, + "48": 1, + "52": 0, + "53": 1, + "57": 0, + "59": 1, + "60": 1, + "63": 3, + "95": 10, + "112": 2, + "122": 10, + "125": 9, + "134": 0, + "151": 1, + "170": 2, + "181": 2, + "194": 2, + "204": 5, + "207": 3, + "209": 0, + "211": 1, + "213": 1, + "219": 5, + "222": 3, + "224": 0, + "226": 0, + "228": 1, + "230": 1, + "245": 2, + "255": 4, + "258": 3, + "260": 1, + "265": 4, + "268": 2, + "270": 1, + "272": 1, + "283": 4, + "286": 2, + "288": 1, + "290": 1, + "298": 2, + "304": 2, + "311": 2, + "319": 2, + "329": 2, + "361": 2, + "371": 2 + }, + "branchHits": { + "29": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "39": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "42": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "43": { + "covered": 3, + "missed": 1, + "available": 4 + }, + "45": { + "covered": 0, + "missed": 4, + "available": 4 + }, + "48": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "53": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "59": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "60": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "95": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "122": { + "covered": 2, + "missed": 2, + "available": 4 + }, + "182": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "204": { + "covered": 4, + "missed": 1, + "available": 5 + }, + "219": { + "covered": 4, + "missed": 2, + "available": 6 + }, + "236": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "241": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "249": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "255": { + "covered": 3, + "missed": 0, + "available": 3 + }, + "265": { + "covered": 4, + "missed": 0, + "available": 4 + }, + "277": { + "covered": 1, + "missed": 0, + "available": 1 + }, + "283": { + "covered": 4, + "missed": 0, + "available": 4 + }, + "294": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "299": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/molecules/Hero/hero.tsx", + "lineHits": { + "40": 10, + "72": 0, + "127": 3, + "56": 10, + "58": 10, + "73": 0, + "128": 3 + }, + "branchHits": { + "73": { + "covered": 0, + "missed": 2, + "available": 2 + } + } + } +] diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-4.json b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-4.json new file mode 100644 index 0000000000..eada26d5ce --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-4.json @@ -0,0 +1,351 @@ +[ + { + "filename": "Sources/TDSOptions.m", + "lineHits": { + "32": 0, + "33": 0, + "34": 0, + "35": 0, + "36": 0, + "37": 0, + "38": 0, + "45": 0, + "46": 0, + "47": 0, + "48": 0, + "49": 0, + "50": 0, + "51": 0, + "52": 0, + "53": 0, + "54": 0, + "55": 0, + "56": 0, + "57": 0, + "58": 0, + "61": 0, + "62": 0, + "63": 0, + "66": 0, + "67": 0, + "68": 0, + "69": 0, + "70": 0, + "71": 0, + "72": 0, + "73": 0, + "74": 0, + "75": 0, + "76": 0, + "77": 0 + }, + "branchHits": {} + }, + { + "filename": "Sources/TDSUserLock.m", + "lineHits": { + "17": 0, + "18": 0, + "19": 0, + "20": 0, + "21": 0, + "22": 0, + "23": 0, + "24": 0, + "25": 0, + "26": 0, + "27": 0, + "28": 0, + "29": 0, + "30": 0, + "31": 0, + "32": 0, + "33": 0, + "34": 0, + "35": 0, + "36": 0, + "37": 0, + "38": 0, + "39": 0, + "40": 0, + "43": 0, + "44": 0, + "45": 0, + "46": 0, + "47": 0, + "48": 0, + "49": 0, + "58": 0, + "59": 0, + "60": 0, + "61": 0, + "62": 0, + "63": 0, + "64": 0, + "65": 0, + "66": 0, + "67": 0, + "68": 0, + "69": 0, + "70": 0 + }, + "branchHits": {} + }, + { + "filename": "Sources/TDSUserManager.m", + "lineHits": { + "24": 0, + "25": 0, + "26": 0, + "27": 0, + "28": 0, + "29": 0, + "30": 0, + "31": 0, + "34": 0, + "35": 0, + "36": 0, + "37": 0, + "38": 0, + "39": 0, + "40": 0, + "49": 0, + "50": 0, + "51": 0, + "52": 0, + "53": 0, + "54": 0, + "55": 0, + "56": 0, + "57": 0, + "58": 0, + "59": 0, + "60": 0, + "61": 0, + "62": 0, + "63": 0, + "64": 0, + "65": 0, + "66": 0, + "67": 0, + "68": 0, + "69": 0, + "70": 0, + "74": 0, + "75": 0, + "76": 0, + "77": 0, + "78": 0, + "79": 0, + "80": 0, + "81": 0, + "82": 0, + "83": 0, + "84": 0, + "85": 0, + "86": 0, + "87": 0, + "88": 0, + "89": 0, + "90": 0, + "91": 0, + "92": 0, + "93": 0, + "94": 0, + "101": 0, + "102": 0, + "103": 0, + "104": 0, + "105": 0, + "106": 0, + "107": 0, + "108": 0, + "109": 0, + "110": 0, + "111": 0, + "112": 0, + "113": 0, + "114": 0, + "115": 0, + "116": 0, + "117": 0, + "118": 0, + "119": 0, + "120": 0, + "121": 0, + "122": 0, + "123": 0, + "124": 0, + "125": 0, + "126": 0, + "127": 0, + "128": 0, + "129": 0, + "130": 0, + "131": 0, + "136": 0, + "137": 0, + "138": 0, + "139": 0, + "140": 0, + "141": 0, + "142": 0, + "143": 0, + "144": 0, + "145": 0, + "146": 0, + "147": 0, + "148": 0, + "149": 0, + "150": 0, + "151": 0, + "152": 0, + "153": 0, + "158": 0, + "159": 0, + "160": 0, + "161": 0, + "162": 0, + "163": 0, + "164": 0, + "165": 0, + "166": 0, + "167": 0, + "168": 0, + "169": 0, + "170": 0, + "171": 0, + "172": 0, + "173": 0, + "174": 0, + "175": 0, + "176": 0, + "177": 0, + "178": 0, + "179": 0, + "180": 0, + "181": 0, + "182": 0, + "183": 0, + "184": 0, + "189": 0, + "190": 0, + "191": 0, + "192": 0, + "193": 0, + "194": 0, + "195": 0, + "196": 0, + "197": 0, + "198": 0, + "199": 0, + "200": 0, + "201": 0, + "202": 0, + "203": 0, + "204": 0, + "205": 0, + "206": 0, + "207": 0, + "208": 0, + "209": 0, + "210": 0, + "211": 0, + "212": 0, + "213": 0, + "214": 0, + "215": 0, + "216": 0, + "217": 0, + "218": 0, + "219": 0, + "220": 0, + "221": 0, + "222": 0, + "223": 0, + "224": 0, + "225": 0, + "226": 0, + "227": 0, + "228": 0, + "229": 0, + "230": 0, + "231": 0, + "232": 0, + "233": 0, + "234": 0, + "235": 0, + "236": 0, + "239": 0, + "240": 0, + "241": 0, + "242": 0, + "243": 0, + "244": 0, + "245": 0, + "246": 0, + "247": 0, + "248": 0, + "249": 0, + "252": 0, + "253": 0, + "254": 0, + "255": 0, + "256": 0, + "257": 0, + "258": 0, + "259": 0, + "260": 0, + "261": 0, + "262": 0, + "263": 0, + "264": 0, + "265": 0, + "268": 0, + "269": 0, + "270": 0, + "271": 0, + "272": 0, + "273": 0, + "274": 0, + "275": 0, + "276": 0, + "277": 0, + "278": 0, + "279": 0, + "280": 0, + "281": 0, + "282": 0, + "283": 0, + "284": 0, + "287": 0, + "288": 0, + "289": 0, + "290": 0, + "291": 0, + "292": 0, + "293": 0, + "294": 0, + "295": 0, + "296": 0 + }, + "branchHits": {} + }, + { + "filename": "Sources/TDSUtil.m", + "lineHits": { + "8": 0, + "9": 0, + "10": 0, + "11": 0, + "12": 0, + "13": 0, + "16": 0, + "17": 0, + "18": 0, + "19": 0, + "20": 0 + }, + "branchHits": {} + } +] diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-5.json b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-5.json new file mode 100644 index 0000000000..41ab6c084f --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-jsoncoverage-files-5.json @@ -0,0 +1,325 @@ +[ + { + "filename": "src/graphql/queries.ts", + "lineHits": { + "1": 3, + "3": 3, + "50": 3, + "65": 3, + "80": 3, + "92": 3, + "138": 3 + }, + "branchHits": {} + }, + { + "filename": "src/graphql/resolvers.ts", + "lineHits": { + "22": 17, + "28": 14, + "36": 16, + "27": 8, + "35": 8, + "43": 9, + "51": 15, + "56": 8, + "61": 8, + "50": 8, + "55": 8, + "60": 8, + "128": 7, + "139": 4, + "145": 8, + "160": 8, + "177": 7, + "185": 13, + "70": 12, + "78": 8, + "81": 8, + "84": 4, + "97": 12, + "103": 8, + "114": 8, + "144": 8, + "159": 8, + "176": 8, + "184": 8, + "1": 4, + "2": 4, + "3": 4, + "5": 4, + "6": 4, + "7": 4, + "8": 4, + "9": 4, + "10": 4, + "14": 4, + "21": 4, + "24": 17, + "32": 10, + "37": 12, + "42": 4, + "45": 9, + "47": 9, + "52": 11, + "57": 4, + "62": 4, + "67": 4, + "73": 8, + "83": 4, + "85": 4, + "86": 4, + "87": 4, + "88": 4, + "94": 4, + "95": 4, + "98": 4, + "104": 4, + "107": 4, + "115": 4, + "118": 4, + "119": 4, + "120": 0, + "124": 4, + "130": 7, + "132": 7, + "134": 7, + "136": 7, + "140": 4, + "151": 4, + "165": 4, + "166": 4, + "167": 4, + "168": 1, + "169": 4, + "178": 3, + "186": 9, + "187": 9, + "193": 2, + "194": 0 + }, + "branchHits": { + "86": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "119": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "166": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "167": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "193": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/graphql/router.ts", + "lineHits": { + "21": 1, + "22": 2, + "43": 21, + "53": 40, + "12": 3, + "14": 3, + "23": 1, + "26": 0, + "32": 1, + "33": 1, + "34": 1, + "37": 0, + "54": 11, + "55": 0, + "57": 11, + "58": 11, + "63": 11, + "64": 11, + "65": 10, + "66": 10, + "68": 1 + }, + "branchHits": { + "23": { + "covered": 3, + "missed": 0, + "available": 3 + }, + "26": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "32": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "55": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "65": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/graphql/schema.ts", + "lineHits": { + "9": 7, + "1": 3, + "2": 3, + "4": 3, + "5": 3, + "11": 0, + "13": 4, + "15": 4, + "16": 4, + "17": 4, + "19": 4 + }, + "branchHits": { + "11": { + "covered": 0, + "missed": 1, + "available": 1 + } + } + }, + { + "filename": "src/graphql/transforms.ts", + "lineHits": { + "9": 10, + "20": 5, + "13": 6, + "14": 2, + "15": 6, + "16": 1, + "17": 6, + "23": 1, + "24": 0, + "25": 1 + }, + "branchHits": { + "13": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "15": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "23": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + }, + { + "filename": "src/workers/primary-worker.js", + "lineHits": { + "16": 0, + "25": 0, + "49": 0, + "2": 0, + "3": 0, + "4": 0, + "5": 0, + "6": 0, + "8": 0, + "17": 0, + "21": 0, + "22": 0, + "23": 0, + "24": 0, + "27": 0, + "28": 0, + "31": 0, + "33": 0, + "34": 0, + "37": 0, + "38": 0, + "48": 0, + "51": 0, + "53": 0 + }, + "branchHits": { + "17": { + "covered": 0, + "missed": 1, + "available": 1 + }, + "21": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "49": { + "covered": 0, + "missed": 2, + "available": 2 + } + } + }, + { + "filename": "src/workers/secondary-worker.js", + "lineHits": { + "4": 0, + "13": 0, + "2": 0, + "5": 0, + "9": 0, + "10": 0, + "11": 0, + "12": 0, + "14": 0, + "15": 0, + "16": 0, + "18": 0, + "19": 0, + "22": 0, + "23": 0, + "24": 0, + "25": 0, + "26": 0, + "27": 0, + "29": 0 + }, + "branchHits": { + "5": { + "covered": 0, + "missed": 1, + "available": 1 + }, + "9": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "24": { + "covered": 0, + "missed": 2, + "available": 2 + } + } + } +] diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-1.txt b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-1.txt new file mode 100644 index 0000000000..bee95e0bca --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-1.txt @@ -0,0 +1,19 @@ +.dockerignore +.editorconfig +.gitattributes +.gitignore +.gitmodules +.idea/codeStyleSettings.xml +.idea/codeStyles/Project.xml +.idea/codeStyles/codeStyleConfig.xml +.idea/inspectionProfiles/Spotify.xml +.idea/inspectionProfiles/profiles_settings.xml +.mention-bot +.ownership-bot +.slack_mentioner +CONTRIBUTING.md +README.md +WORKSPACE +src/main/scala/com/example/Main.scala +src/main/scala/com/example/Other.scala +src/main/scala/com/example/utils/Util.scala diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-2.txt b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-2.txt new file mode 100644 index 0000000000..b8d13fc792 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-2.txt @@ -0,0 +1,49 @@ +.dockerignore +.editorconfig +.gitattributes +.gitignore +.gitmodules +CONTRIBUTING.md +README.md +WORKSPACE +src/index.ts +src/utils.ts +src/controller/VideoContextPlayerCoordinator.ts +src/controller/VideoContextPlayerCoordinatorFactory.ts +src/controller/index.ts +src/controller-x/VideoContextPlayerCoordinatorX.ts +src/controller-x/VideoContextPlayerCoordinatorXObserver.ts +src/controller-x/index.ts +src/events/InternalPlaybackObserver.ts +src/events/PlaybackEventsObserver.ts +src/events/TimeObservable.ts +src/events/index.ts +src/player/BetamaxPlayer.ts +src/player/BetamaxPlayerFactory.ts +src/player/PlaybackSession.ts +src/player/PlaybackSessionFactory.ts +src/player/index.ts +src/player/player.ts +src/player/shaka.ts +src/plugins/SPManifestParser.ts +src/plugins/SpotifyVideoMediaExtension.ts +src/plugins/SpotifyVideoUrl.ts +src/plugins/TextParser.js +src/plugins/VttTextParser.js +src/plugins/WidevineDownloader.ts +src/plugins/index.ts +src/plugins/types.ts +src/tracking/DefaultEventsCalculator.ts +src/tracking/EventsTracker.ts +src/tracking/ProductStatesStreamingRulesProvider.ts +src/tracking/VideoPlaybackEvents.ts +src/tracking/index.ts +src/tracking/types.ts +src/tracking/utils.ts +src/tracking/endvideo/EndVideoEventsCalculator.ts +src/tracking/endvideo/EndVideoLoggerFactory.ts +src/tracking/endvideo/EndVideoLoggerTracker.ts +src/tracking/endvideo/EndVideoReasonEnd.ts +src/tracking/endvideo/EndVideoTracker.ts +src/tracking/session/PlaybackSessionTracker.ts +src/tracking/session/VideoPlaybackSessionLogger.ts diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-3.txt b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-3.txt new file mode 100644 index 0000000000..fb2d4096ed --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-3.txt @@ -0,0 +1,29 @@ +.dockerignore +.editorconfig +.gitattributes +.gitignore +.gitmodules +.idea/codeStyleSettings.xml +.idea/codeStyles/Project.xml +.idea/codeStyles/codeStyleConfig.xml +.idea/inspectionProfiles/Spotify.xml +.idea/inspectionProfiles/profiles_settings.xml +.mention-bot +.ownership-bot +.slack_mentioner +CONTRIBUTING.md +README.md +WORKSPACE +src/index.ts +src/atoms/BoxShadow/box-shadow.ts +src/atoms/BoxShadow/index.ts +src/atoms/Button/button.tsx +src/atoms/Button/index.ts +src/atoms/Container/components.ts +src/atoms/Container/container.tsx +src/atoms/Container/index.ts +src/atoms/DownArrow/down-arrow.tsx +src/atoms/DownArrow/index.ts +src/molecules/Hero/components.ts +src/molecules/Hero/hero.tsx +src/molecules/Hero/index.ts diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-4.txt b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-4.txt new file mode 100644 index 0000000000..4e0e3699af --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-4.txt @@ -0,0 +1,20 @@ +.dockerignore +.editorconfig +.gitattributes +.gitignore +.gitmodules +.idea/codeStyleSettings.xml +.idea/codeStyles/Project.xml +.idea/codeStyles/codeStyleConfig.xml +.idea/inspectionProfiles/Spotify.xml +.idea/inspectionProfiles/profiles_settings.xml +.mention-bot +.ownership-bot +.slack_mentioner +CONTRIBUTING.md +README.md +WORKSPACE +Sources/TDSOptions.m +Sources/TDSUserLock.m +Sources/TDSUserManager.m +Sources/TDSUtil.m diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-5.txt b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-5.txt new file mode 100644 index 0000000000..d117a9885a --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-sourcefiles-5.txt @@ -0,0 +1,26 @@ +.editorconfig +.eslintignore +.eslintrc.js +.gitignore +.npmrc +.nvmrc +Dockerfile +README.md +babel.config.js +nodemon.json +package.json +prettier.config.js +service-info.yaml +src/graphql/__tests__/resolvers.test.ts +src/graphql/__tests__/transforms.test.ts +src/graphql/queries.ts +src/graphql/resolvers.ts +src/graphql/router.ts +src/graphql/schema.ts +src/graphql/transforms.ts +src/start.ts +src/sysmodel_component.ts +src/workers/primary-worker.js +src/workers/secondary-worker.js +tsconfig.json +yarn.lock diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-1.xml b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-1.xml new file mode 100644 index 0000000000..37e2c8c560 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-1.xml @@ -0,0 +1,479 @@ +<?xml version="1.0"?> +<coverage + line-rate="0.98" lines-valid="312" lines-covered="306" branches-valid="12" branches-covered="12" branch-rate="1.00" complexity="0" version="1.0" timestamp="1567499510503"> + <packages> + <package name="com.example" line-rate="0.98" branch-rate="1.00" complexity="0"> + <classes> + <class + name="com.example.Main" filename="com/example/Main.scala" line-rate="0.97" branch-rate="1.00" complexity="0"> + <methods> + <method + name="com.example/Main/methodOne" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="203" hits="1" branch="false"/> + <line number="202" hits="1" branch="false"/> + <line number="204" hits="1" branch="false"/> + <line number="203" hits="1" branch="false"/> + <line number="202" hits="1" branch="false"/> + <line number="204" hits="1" branch="false"/> + <line number="203" hits="1" branch="false"/> + </lines> + </method> + <method + name="com.example/Main/methodTwo" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="164" hits="1" branch="false"/> + <line number="169" hits="1" branch="false"/> + <line number="170" hits="1" branch="false"/> + <line number="167" hits="1" branch="false"/> + <line number="168" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="168" hits="1" branch="false"/> + <line number="169" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="170" hits="1" branch="false"/> + <line number="167" hits="1" branch="false"/> + <line number="166" hits="1" branch="false"/> + <line number="160" hits="1" branch="false"/> + <line number="168" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="169" hits="1" branch="false"/> + <line number="164" hits="1" branch="false"/> + </lines> + </method> + <method + name="com.example/Main/methodThree" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="97" hits="1" branch="false"/> + <line number="104" hits="1" branch="false"/> + <line number="99" hits="1" branch="false"/> + <line number="95" hits="1" branch="false"/> + <line number="100" hits="1" branch="false"/> + <line number="104" hits="1" branch="false"/> + <line number="97" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="97" hits="1" branch="false"/> + <line number="97" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="100" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + </lines> + </method> + <method + name="com.example/Main/&lt;none&gt;" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="30" hits="1" branch="false"/> + <line number="26" hits="1" branch="false"/> + <line number="28" hits="1" branch="false"/> + <line number="27" hits="1" branch="false"/> + <line number="30" hits="1" branch="false"/> + <line number="26" hits="1" branch="false"/> + <line number="27" hits="1" branch="false"/> + <line number="28" hits="1" branch="false"/> + </lines> + </method> + <method + name="com.example/Main/main" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="56" hits="1" branch="false"/> + <line number="73" hits="1" branch="false"/> + <line number="77" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="44" hits="1" branch="false"/> + <line number="60" hits="1" branch="false"/> + <line number="35" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="65" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="37" hits="1" branch="false"/> + <line number="77" hits="1" branch="false"/> + <line number="37" hits="1" branch="false"/> + <line number="52" hits="1" branch="false"/> + <line number="65" hits="1" branch="false"/> + <line number="42" hits="1" branch="false"/> + <line number="58" hits="1" branch="false"/> + <line number="68" hits="1" branch="false"/> + <line number="33" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="48" hits="1" branch="false"/> + <line number="64" hits="1" branch="false"/> + <line number="61" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="33" hits="1" branch="false"/> + <line number="46" hits="1" branch="false"/> + <line number="53" hits="1" branch="false"/> + <line number="36" hits="1" branch="false"/> + <line number="65" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="38" hits="1" branch="false"/> + <line number="55" hits="1" branch="false"/> + <line number="68" hits="1" branch="false"/> + </lines> + </method> + </methods> + <lines> + <line number="203" hits="1" branch="false"/> + <line number="135" hits="1" branch="false"/> + <line number="149" hits="1" branch="false"/> + <line number="126" hits="1" branch="false"/> + <line number="164" hits="1" branch="false"/> + <line number="169" hits="1" branch="false"/> + <line number="183" hits="1" branch="false"/> + <line number="56" hits="1" branch="false"/> + <line number="138" hits="1" branch="false"/> + <line number="143" hits="1" branch="false"/> + <line number="188" hits="1" branch="false"/> + <line number="170" hits="1" branch="false"/> + <line number="112" hits="1" branch="false"/> + <line number="127" hits="1" branch="false"/> + <line number="86" hits="1" branch="false"/> + <line number="97" hits="1" branch="false"/> + <line number="104" hits="1" branch="false"/> + <line number="73" hits="1" branch="false"/> + <line number="77" hits="1" branch="false"/> + <line number="167" hits="1" branch="false"/> + <line number="210" hits="1" branch="false"/> + <line number="88" hits="1" branch="false"/> + <line number="99" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="30" hits="1" branch="false"/> + <line number="84" hits="1" branch="false"/> + <line number="44" hits="1" branch="false"/> + <line number="60" hits="1" branch="false"/> + <line number="182" hits="1" branch="false"/> + <line number="124" hits="1" branch="false"/> + <line number="125" hits="1" branch="false"/> + <line number="168" hits="1" branch="false"/> + <line number="146" hits="1" branch="false"/> + <line number="114" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="35" hits="1" branch="false"/> + <line number="114" hits="1" branch="false"/> + <line number="88" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="65" hits="1" branch="false"/> + <line number="85" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="26" hits="1" branch="false"/> + <line number="95" hits="1" branch="false"/> + <line number="28" hits="1" branch="false"/> + <line number="37" hits="1" branch="false"/> + <line number="202" hits="1" branch="false"/> + <line number="210" hits="1" branch="false"/> + <line number="181" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="168" hits="1" branch="false"/> + <line number="85" hits="1" branch="false"/> + <line number="169" hits="1" branch="false"/> + <line number="183" hits="1" branch="false"/> + <line number="148" hits="1" branch="false"/> + <line number="126" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="135" hits="1" branch="false"/> + <line number="100" hits="1" branch="false"/> + <line number="88" hits="1" branch="false"/> + <line number="114" hits="1" branch="false"/> + <line number="204" hits="1" branch="false"/> + <line number="127" hits="1" branch="false"/> + <line number="140" hits="1" branch="false"/> + <line number="104" hits="1" branch="false"/> + <line number="97" hits="1" branch="false"/> + <line number="77" hits="1" branch="false"/> + <line number="86" hits="1" branch="false"/> + <line number="188" hits="1" branch="false"/> + <line number="27" hits="1" branch="false"/> + <line number="37" hits="1" branch="false"/> + <line number="170" hits="1" branch="false"/> + <line number="210" hits="1" branch="false"/> + <line number="52" hits="1" branch="false"/> + <line number="65" hits="1" branch="false"/> + <line number="115" hits="1" branch="false"/> + <line number="145" hits="1" branch="false"/> + <line number="167" hits="1" branch="false"/> + <line number="42" hits="1" branch="false"/> + <line number="136" hits="1" branch="false"/> + <line number="30" hits="1" branch="false"/> + <line number="124" hits="1" branch="false"/> + <line number="125" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="88" hits="1" branch="false"/> + <line number="84" hits="1" branch="false"/> + <line number="58" hits="1" branch="false"/> + <line number="68" hits="1" branch="false"/> + <line number="97" hits="1" branch="false"/> + <line number="33" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="26" hits="1" branch="false"/> + <line number="48" hits="1" branch="false"/> + <line number="64" hits="1" branch="false"/> + <line number="203" hits="1" branch="false"/> + <line number="187" hits="1" branch="false"/> + <line number="179" hits="1" branch="false"/> + <line number="166" hits="1" branch="false"/> + <line number="97" hits="1" branch="false"/> + <line number="127" hits="1" branch="false"/> + <line number="138" hits="1" branch="false"/> + <line number="210" hits="1" branch="false"/> + <line number="188" hits="1" branch="false"/> + <line number="202" hits="1" branch="false"/> + <line number="160" hits="1" branch="false"/> + <line number="168" hits="1" branch="false"/> + <line number="178" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="112" hits="1" branch="false"/> + <line number="135" hits="1" branch="false"/> + <line number="147" hits="1" branch="false"/> + <line number="100" hits="1" branch="false"/> + <line number="85" hits="1" branch="false"/> + <line number="88" hits="1" branch="false"/> + <line number="114" hits="1" branch="false"/> + <line number="204" hits="1" branch="false"/> + <line number="124" hits="1" branch="false"/> + <line number="183" hits="1" branch="false"/> + <line number="61" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="163" hits="1" branch="false"/> + <line number="169" hits="1" branch="false"/> + <line number="33" hits="1" branch="false"/> + <line number="46" hits="1" branch="false"/> + <line number="86" hits="1" branch="false"/> + <line number="53" hits="1" branch="false"/> + <line number="88" hits="1" branch="false"/> + <line number="27" hits="1" branch="false"/> + <line number="36" hits="1" branch="false"/> + <line number="126" hits="1" branch="false"/> + <line number="139" hits="1" branch="false"/> + <line number="150" hits="1" branch="false"/> + <line number="115" hits="1" branch="false"/> + <line number="65" hits="1" branch="false"/> + <line number="75" hits="1" branch="false"/> + <line number="164" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + <line number="38" hits="1" branch="false"/> + <line number="83" hits="1" branch="false"/> + <line number="87" hits="1" branch="false"/> + <line number="55" hits="1" branch="false"/> + <line number="68" hits="1" branch="false"/> + <line number="28" hits="1" branch="false"/> + <line number="210" hits="1" branch="false"/> + <line number="203" hits="1" branch="false"/> + </lines> + </class> + <class + name="com.example.Other" filename="com/example/Other.scala" line-rate="0.99" branch-rate="1.00" complexity="0"> + <methods> + <method + name="com.example/Other/methodOne" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="42" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="46" hits="1" branch="false"/> + <line number="52" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="44" hits="1" branch="false"/> + <line number="49" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="42" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="52" hits="1" branch="false"/> + <line number="45" hits="1" branch="false"/> + <line number="49" hits="1" branch="false"/> + </lines> + </method> + <method + name="com.example/Other/methodTwo" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="133" hits="1" branch="false"/> + <line number="133" hits="1" branch="false"/> + <line number="134" hits="1" branch="false"/> + <line number="132" hits="1" branch="false"/> + </lines> + </method> + </methods> + <lines> + <line number="91" hits="1" branch="false"/> + <line number="93" hits="1" branch="false"/> + <line number="68" hits="1" branch="false"/> + <line number="42" hits="1" branch="false"/> + <line number="79" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="117" hits="1" branch="false"/> + <line number="59" hits="1" branch="false"/> + <line number="21" hits="1" branch="false"/> + <line number="31" hits="1" branch="false"/> + <line number="111" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="61" hits="1" branch="false"/> + <line number="46" hits="1" branch="false"/> + <line number="25" hits="1" branch="false"/> + <line number="52" hits="1" branch="false"/> + <line number="32" hits="1" branch="false"/> + <line number="144" hits="1" branch="false"/> + <line number="146" hits="1" branch="false"/> + <line number="129" hits="1" branch="false"/> + <line number="147" hits="1" branch="false"/> + <line number="109" hits="1" branch="false"/> + <line number="93" hits="1" branch="false"/> + <line number="117" hits="1" branch="false"/> + <line number="104" hits="1" branch="false"/> + <line number="145" hits="1" branch="false"/> + <line number="133" hits="1" branch="false"/> + <line number="142" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="61" hits="1" branch="false"/> + <line number="129" hits="1" branch="false"/> + <line number="146" hits="1" branch="false"/> + <line number="44" hits="1" branch="false"/> + <line number="119" hits="1" branch="false"/> + <line number="74" hits="1" branch="false"/> + <line number="143" hits="1" branch="false"/> + <line number="146" hits="1" branch="false"/> + <line number="32" hits="1" branch="false"/> + <line number="111" hits="1" branch="false"/> + <line number="139" hits="1" branch="false"/> + <line number="92" hits="1" branch="false"/> + <line number="70" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="140" hits="1" branch="false"/> + <line number="115" hits="1" branch="false"/> + <line number="93" hits="1" branch="false"/> + <line number="124" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + <line number="71" hits="1" branch="false"/> + <line number="86" hits="1" branch="false"/> + <line number="27" hits="1" branch="false"/> + <line number="33" hits="1" branch="false"/> + <line number="49" hits="1" branch="false"/> + <line number="59" hits="1" branch="false"/> + <line number="64" hits="1" branch="false"/> + <line number="129" hits="1" branch="false"/> + <line number="110" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="29" hits="1" branch="false"/> + <line number="37" hits="0" branch="false"/> + <line number="66" hits="1" branch="false"/> + <line number="72" hits="1" branch="false"/> + <line number="87" hits="1" branch="false"/> + <line number="59" hits="1" branch="false"/> + <line number="20" hits="1" branch="false"/> + <line number="149" hits="1" branch="false"/> + <line number="25" hits="1" branch="false"/> + <line number="146" hits="1" branch="false"/> + <line number="140" hits="1" branch="false"/> + <line number="113" hits="1" branch="false"/> + <line number="144" hits="1" branch="false"/> + <line number="123" hits="1" branch="false"/> + <line number="129" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="59" hits="1" branch="false"/> + <line number="94" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="72" hits="1" branch="false"/> + <line number="85" hits="1" branch="false"/> + <line number="144" hits="1" branch="false"/> + <line number="147" hits="1" branch="false"/> + <line number="65" hits="1" branch="false"/> + <line number="133" hits="1" branch="false"/> + <line number="142" hits="1" branch="false"/> + <line number="116" hits="1" branch="false"/> + <line number="104" hits="1" branch="false"/> + <line number="123" hits="1" branch="false"/> + <line number="110" hits="1" branch="false"/> + <line number="143" hits="1" branch="false"/> + <line number="42" hits="1" branch="false"/> + <line number="50" hits="1" branch="false"/> + <line number="23" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + <line number="119" hits="1" branch="false"/> + <line number="129" hits="1" branch="false"/> + <line number="74" hits="1" branch="false"/> + <line number="92" hits="1" branch="false"/> + <line number="145" hits="1" branch="false"/> + <line number="31" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="111" hits="1" branch="false"/> + <line number="61" hits="1" branch="false"/> + <line number="70" hits="1" branch="false"/> + <line number="139" hits="1" branch="false"/> + <line number="52" hits="1" branch="false"/> + <line number="86" hits="1" branch="false"/> + <line number="92" hits="1" branch="false"/> + <line number="33" hits="1" branch="false"/> + <line number="45" hits="1" branch="false"/> + <line number="26" hits="1" branch="false"/> + <line number="61" hits="1" branch="false"/> + <line number="70" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + <line number="34" hits="1" branch="false"/> + <line number="29" hits="1" branch="false"/> + <line number="129" hits="1" branch="false"/> + <line number="134" hits="1" branch="false"/> + <line number="149" hits="1" branch="false"/> + <line number="142" hits="1" branch="false"/> + <line number="145" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + <line number="115" hits="1" branch="false"/> + <line number="92" hits="1" branch="false"/> + <line number="113" hits="1" branch="false"/> + <line number="144" hits="1" branch="false"/> + <line number="70" hits="1" branch="false"/> + <line number="73" hits="1" branch="false"/> + <line number="138" hits="1" branch="false"/> + <line number="143" hits="1" branch="false"/> + <line number="146" hits="1" branch="false"/> + <line number="105" hits="1" branch="false"/> + <line number="129" hits="1" branch="false"/> + <line number="49" hits="1" branch="false"/> + <line number="59" hits="1" branch="false"/> + <line number="123" hits="1" branch="false"/> + <line number="132" hits="1" branch="false"/> + <line number="34" hits="1" branch="false"/> + <line number="86" hits="1" branch="false"/> + <line number="144" hits="1" branch="false"/> + <line number="27" hits="1" branch="false"/> + <line number="110" hits="1" branch="false"/> + <line number="116" hits="1" branch="false"/> + <line number="64" hits="1" branch="false"/> + <line number="94" hits="1" branch="false"/> + <line number="71" hits="1" branch="false"/> + <line number="103" hits="1" branch="false"/> + <line number="147" hits="1" branch="false"/> + <line number="142" hits="1" branch="false"/> + </lines> + </class> + </classes> + </package> + <package name="com.example.utils" line-rate="1.00" branch-rate="1.00" complexity="0"> + <classes> + <class + name="com.example.utils.Util" filename="com/example/utils/Util.scala" line-rate="1.00" branch-rate="1.00" complexity="0"> + <methods> + <method + name="com.example.utils/DateFormatUtils/utilMethod" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="13" hits="1" branch="false"/> + </lines> + </method> + <method + name="com.example.utils/DateFormatUtils/utilFunc" signature="()V" line-rate="1.00" branch-rate="1.00" complexity="0"> + <lines> + <line number="8" hits="1" branch="false"/> + <line number="7" hits="1" branch="false"/> + <line number="8" hits="1" branch="false"/> + </lines> + </method> + </methods> + <lines> + <line number="8" hits="1" branch="false"/> + <line number="7" hits="1" branch="false"/> + <line number="13" hits="1" branch="false"/> + <line number="8" hits="1" branch="false"/> + </lines> + </class> + </classes> + </package> + </packages> +</coverage> diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-2.xml b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-2.xml new file mode 100644 index 0000000000..9e94385cbc --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-2.xml @@ -0,0 +1,5721 @@ +<?xml version="1.0" ?> +<coverage branch-rate="0.8154506437768241" branches-covered="380" branches-valid="466" complexity="0" line-rate="0.8407299875570303" lines-covered="2027" lines-valid="2411" timestamp="1575069145" version="2.0.3"> + <sources> + <source>.</source> + </sources> + <packages> + <package branch-rate="0.9" complexity="0" line-rate="0.9736842105263158" name="src"> + <classes> + <class branch-rate="0.0" complexity="0" filename="src/index.ts" line-rate="1.0" name="src.index.ts"> + <methods/> + <lines> + <line branch="false" hits="3" number="1"/> + <line branch="false" hits="3" number="3"/> + <line branch="false" hits="3" number="5"/> + <line branch="false" hits="3" number="6"/> + <line branch="false" hits="3" number="7"/> + <line branch="false" hits="3" number="8"/> + <line branch="false" hits="3" number="9"/> + <line branch="false" hits="3" number="11"/> + <line branch="false" hits="3" number="12"/> + <line branch="false" hits="3" number="14"/> + </lines> + </class> + <class branch-rate="0.9" complexity="0" filename="src/utils.ts" line-rate="0.9642857142857143" name="src.utils.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="19" number="4"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="19" number="4"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="47" number="4"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="589" number="7"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="1" number="12"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="1" number="12"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="2" number="16"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="776" number="29"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="1601" number="33"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="15" number="37"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="20" number="56"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="21" number="64"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="2" number="65"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="18" number="1"/> + <line branch="false" hits="19" number="4"/> + <line branch="false" hits="589" number="7"/> + <line branch="true" condition-coverage="100% (2/2)" hits="589" number="8"/> + <line branch="false" hits="589" number="9"/> + <line branch="false" hits="18" number="12"/> + <line branch="false" hits="1" number="15"/> + <line branch="false" hits="2" number="18"/> + <line branch="false" hits="0" number="20"/> + <line branch="false" hits="2" number="22"/> + <line branch="false" hits="18" number="28"/> + <line branch="false" hits="2329" number="29"/> + <line branch="false" hits="776" number="30"/> + <line branch="false" hits="1601" number="34"/> + <line branch="false" hits="158" number="42"/> + <line branch="false" hits="1" number="48"/> + <line branch="false" hits="15" number="53"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="57"/> + <line branch="false" hits="1" number="58"/> + <line branch="false" hits="19" number="60"/> + <line branch="false" hits="19" number="61"/> + <line branch="false" hits="19" number="63"/> + <line branch="false" hits="21" number="64"/> + <line branch="false" hits="2" number="66"/> + <line branch="false" hits="2" number="67"/> + <line branch="true" condition-coverage="100% (2/2)" hits="2" number="68"/> + <line branch="true" condition-coverage="50% (1/2)" hits="1" number="69"/> + <line branch="false" hits="1" number="70"/> + <line branch="true" condition-coverage="100% (2/2)" hits="19" number="73"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.7333333333333333" complexity="0" line-rate="0.8566037735849057" name="src.controller"> + <classes> + <class branch-rate="0.7397260273972602" complexity="0" filename="src/controller/VideoContextPlayerCoordinator.ts" line-rate="0.8516949152542372" name="src.controller.VideoContextPlayerCoordinator.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="4" number="50"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="VideoContextPlayerCoordinator" signature=""> + <lines> + <line branch="false" hits="33" number="74"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="0" number="137"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="1" number="143"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="14" number="157"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="1" number="217"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="1" number="240"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="24" number="309"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="24" number="343"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="24" number="357"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="4" number="405"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="20" number="420"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="19" number="442"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="1" number="445"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="20" number="460"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="20" number="466"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="8" number="480"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="8" number="488"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="8" number="520"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="14" number="530"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="0" number="619"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="2" number="627"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="0" number="636"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="4" number="640"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="4" number="651"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="8" number="661"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="33" number="673"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="4" number="690"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="3" number="711"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="2" number="736"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="25" number="740"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="4" number="1"/> + <line branch="false" hits="4" number="2"/> + <line branch="false" hits="4" number="31"/> + <line branch="false" hits="4" number="33"/> + <line branch="false" hits="4" number="37"/> + <line branch="false" hits="4" number="39"/> + <line branch="false" hits="4" number="41"/> + <line branch="false" hits="4" number="50"/> + <line branch="false" hits="33" number="74"/> + <line branch="false" hits="33" number="76"/> + <line branch="false" hits="33" number="77"/> + <line branch="false" hits="33" number="78"/> + <line branch="false" hits="33" number="79"/> + <line branch="false" hits="33" number="80"/> + <line branch="false" hits="33" number="81"/> + <line branch="false" hits="33" number="82"/> + <line branch="false" hits="33" number="83"/> + <line branch="false" hits="33" number="84"/> + <line branch="false" hits="33" number="85"/> + <line branch="false" hits="33" number="86"/> + <line branch="false" hits="33" number="87"/> + <line branch="false" hits="33" number="90"/> + <line branch="false" hits="33" number="91"/> + <line branch="false" hits="33" number="92"/> + <line branch="false" hits="33" number="93"/> + <line branch="false" hits="33" number="94"/> + <line branch="false" hits="33" number="95"/> + <line branch="false" hits="33" number="96"/> + <line branch="false" hits="33" number="100"/> + <line branch="false" hits="33" number="103"/> + <line branch="false" hits="33" number="106"/> + <line branch="false" hits="33" number="107"/> + <line branch="false" hits="33" number="110"/> + <line branch="false" hits="33" number="111"/> + <line branch="false" hits="33" number="112"/> + <line branch="false" hits="33" number="113"/> + <line branch="false" hits="33" number="115"/> + <line branch="false" hits="33" number="116"/> + <line branch="false" hits="33" number="118"/> + <line branch="false" hits="33" number="120"/> + <line branch="false" hits="33" number="121"/> + <line branch="true" condition-coverage="0% (0/1)" hits="0" number="122"/> + <line branch="false" hits="33" number="128"/> + <line branch="false" hits="33" number="131"/> + <line branch="false" hits="33" number="137"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="138"/> + <line branch="false" hits="0" number="139"/> + <line branch="false" hits="4" number="143"/> + <line branch="false" hits="1" number="147"/> + <line branch="false" hits="1" number="148"/> + <line branch="false" hits="1" number="149"/> + <line branch="false" hits="1" number="150"/> + <line branch="false" hits="4" number="157"/> + <line branch="false" hits="2" number="159"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="162"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="164"/> + <line branch="false" hits="1" number="167"/> + <line branch="false" hits="1" number="171"/> + <line branch="false" hits="1" number="174"/> + <line branch="false" hits="1" number="176"/> + <line branch="false" hits="1" number="180"/> + <line branch="false" hits="7" number="183"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="185"/> + <line branch="false" hits="7" number="186"/> + <line branch="false" hits="7" number="188"/> + <line branch="false" hits="7" number="189"/> + <line branch="false" hits="0" number="194"/> + <line branch="false" hits="0" number="196"/> + <line branch="true" condition-coverage="100% (7/7)" hits="0" number="200"/> + <line branch="false" hits="1" number="201"/> + <line branch="false" hits="1" number="203"/> + <line branch="false" hits="1" number="205"/> + <line branch="false" hits="1" number="207"/> + <line branch="false" hits="1" number="209"/> + <line branch="false" hits="1" number="211"/> + <line branch="false" hits="1" number="213"/> + <line branch="false" hits="4" number="217"/> + <line branch="false" hits="1" number="225"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="233"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="234"/> + <line branch="false" hits="4" number="240"/> + <line branch="false" hits="1" number="245"/> + <line branch="false" hits="0" number="247"/> + <line branch="false" hits="0" number="250"/> + <line branch="false" hits="1" number="253"/> + <line branch="false" hits="1" number="254"/> + <line branch="true" condition-coverage="100% (3/3)" hits="0" number="255"/> + <line branch="false" hits="0" number="258"/> + <line branch="false" hits="1" number="263"/> + <line branch="false" hits="0" number="276"/> + <line branch="false" hits="1" number="278"/> + <line branch="true" condition-coverage="50% (1/2)" hits="1" number="283"/> + <line branch="false" hits="1" number="285"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="286"/> + <line branch="false" hits="1" number="288"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="289"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="291"/> + <line branch="true" condition-coverage="50% (2/4)" hits="0" number="293"/> + <line branch="false" hits="1" number="301"/> + <line branch="false" hits="24" number="309"/> + <line branch="false" hits="24" number="315"/> + <line branch="false" hits="24" number="316"/> + <line branch="false" hits="24" number="318"/> + <line branch="false" hits="24" number="319"/> + <line branch="false" hits="10" number="322"/> + <line branch="true" condition-coverage="50% (1/2)" hits="10" number="323"/> + <line branch="false" hits="0" number="325"/> + <line branch="false" hits="0" number="328"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="332"/> + <line branch="false" hits="0" number="333"/> + <line branch="false" hits="0" number="337"/> + <line branch="false" hits="0" number="338"/> + <line branch="false" hits="24" number="341"/> + <line branch="false" hits="24" number="343"/> + <line branch="false" hits="24" number="346"/> + <line branch="false" hits="24" number="347"/> + <line branch="true" condition-coverage="100% (2/2)" hits="24" number="351"/> + <line branch="false" hits="24" number="352"/> + <line branch="false" hits="24" number="354"/> + <line branch="false" hits="24" number="357"/> + <line branch="true" condition-coverage="100% (2/2)" hits="24" number="359"/> + <line branch="true" condition-coverage="100% (2/2)" hits="24" number="361"/> + <line branch="false" hits="24" number="362"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="363"/> + <line branch="false" hits="24" number="366"/> + <line branch="false" hits="24" number="377"/> + <line branch="false" hits="24" number="378"/> + <line branch="false" hits="24" number="379"/> + <line branch="false" hits="24" number="380"/> + <line branch="false" hits="24" number="381"/> + <line branch="false" hits="24" number="383"/> + <line branch="false" hits="24" number="384"/> + <line branch="true" condition-coverage="100% (2/2)" hits="24" number="386"/> + <line branch="false" hits="24" number="396"/> + <line branch="false" hits="24" number="397"/> + <line branch="false" hits="4" number="405"/> + <line branch="false" hits="4" number="406"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="408"/> + <line branch="false" hits="4" number="413"/> + <line branch="false" hits="20" number="418"/> + <line branch="false" hits="0" number="429"/> + <line branch="false" hits="0" number="433"/> + <line branch="false" hits="0" number="434"/> + <line branch="false" hits="0" number="435"/> + <line branch="false" hits="20" number="440"/> + <line branch="false" hits="19" number="443"/> + <line branch="false" hits="1" number="450"/> + <line branch="false" hits="1" number="451"/> + <line branch="false" hits="1" number="452"/> + <line branch="false" hits="0" number="462"/> + <line branch="false" hits="20" number="464"/> + <line branch="false" hits="20" number="468"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="470"/> + <line branch="false" hits="8" number="480"/> + <line branch="false" hits="8" number="485"/> + <line branch="false" hits="0" number="490"/> + <line branch="false" hits="0" number="491"/> + <line branch="false" hits="8" number="493"/> + <line branch="false" hits="0" number="496"/> + <line branch="false" hits="0" number="497"/> + <line branch="false" hits="8" number="500"/> + <line branch="false" hits="8" number="502"/> + <line branch="false" hits="8" number="507"/> + <line branch="false" hits="8" number="520"/> + <line branch="false" hits="8" number="525"/> + <line branch="false" hits="8" number="527"/> + <line branch="false" hits="8" number="528"/> + <line branch="true" condition-coverage="50% (1/2)" hits="14" number="531"/> + <line branch="false" hits="0" number="534"/> + <line branch="false" hits="0" number="535"/> + <line branch="false" hits="14" number="538"/> + <line branch="false" hits="14" number="539"/> + <line branch="false" hits="8" number="543"/> + <line branch="false" hits="8" number="544"/> + <line branch="false" hits="8" number="549"/> + <line branch="true" condition-coverage="62% (5/8)" hits="0" number="552"/> + <line branch="false" hits="1" number="553"/> + <line branch="false" hits="1" number="554"/> + <line branch="false" hits="1" number="555"/> + <line branch="false" hits="1" number="559"/> + <line branch="false" hits="1" number="561"/> + <line branch="false" hits="1" number="562"/> + <line branch="false" hits="2" number="567"/> + <line branch="false" hits="1" number="570"/> + <line branch="false" hits="2" number="572"/> + <line branch="false" hits="2" number="574"/> + <line branch="false" hits="2" number="575"/> + <line branch="true" condition-coverage="50% (1/2)" hits="1" number="579"/> + <line branch="false" hits="1" number="580"/> + <line branch="false" hits="1" number="582"/> + <line branch="false" hits="1" number="583"/> + <line branch="false" hits="1" number="588"/> + <line branch="false" hits="1" number="589"/> + <line branch="false" hits="1" number="592"/> + <line branch="false" hits="1" number="594"/> + <line branch="false" hits="1" number="595"/> + <line branch="false" hits="0" number="599"/> + <line branch="false" hits="0" number="600"/> + <line branch="false" hits="0" number="605"/> + <line branch="false" hits="0" number="606"/> + <line branch="false" hits="0" number="610"/> + <line branch="false" hits="0" number="615"/> + <line branch="false" hits="0" number="616"/> + <line branch="false" hits="0" number="620"/> + <line branch="false" hits="0" number="621"/> + <line branch="false" hits="8" number="625"/> + <line branch="false" hits="2" number="628"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="629"/> + <line branch="false" hits="2" number="630"/> + <line branch="false" hits="1" number="632"/> + <line branch="false" hits="4" number="640"/> + <line branch="false" hits="4" number="647"/> + <line branch="false" hits="4" number="651"/> + <line branch="false" hits="4" number="653"/> + <line branch="false" hits="4" number="654"/> + <line branch="false" hits="4" number="656"/> + <line branch="false" hits="4" number="661"/> + <line branch="false" hits="8" number="662"/> + <line branch="false" hits="8" number="663"/> + <line branch="false" hits="0" number="665"/> + <line branch="false" hits="0" number="666"/> + <line branch="false" hits="0" number="667"/> + <line branch="false" hits="4" number="673"/> + <line branch="false" hits="8" number="675"/> + <line branch="false" hits="8" number="676"/> + <line branch="false" hits="8" number="679"/> + <line branch="false" hits="8" number="680"/> + <line branch="false" hits="33" number="682"/> + <line branch="false" hits="33" number="683"/> + <line branch="false" hits="33" number="684"/> + <line branch="false" hits="33" number="685"/> + <line branch="false" hits="33" number="687"/> + <line branch="false" hits="4" number="690"/> + <line branch="false" hits="4" number="694"/> + <line branch="false" hits="4" number="695"/> + <line branch="false" hits="4" number="697"/> + <line branch="false" hits="4" number="698"/> + <line branch="false" hits="4" number="699"/> + <line branch="false" hits="4" number="700"/> + <line branch="false" hits="4" number="711"/> + <line branch="false" hits="1" number="720"/> + <line branch="false" hits="1" number="721"/> + <line branch="false" hits="1" number="722"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="726"/> + <line branch="false" hits="1" number="727"/> + <line branch="false" hits="1" number="732"/> + <line branch="false" hits="2" number="734"/> + <line branch="false" hits="2" number="736"/> + <line branch="false" hits="2" number="737"/> + <line branch="false" hits="4" number="740"/> + <line branch="false" hits="1" number="745"/> + <line branch="false" hits="1" number="746"/> + <line branch="true" condition-coverage="100% (2/2)" hits="1" number="749"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="750"/> + <line branch="false" hits="1" number="752"/> + <line branch="false" hits="24" number="754"/> + <line branch="false" hits="4" number="756"/> + </lines> + </class> + <class branch-rate="0.5" complexity="0" filename="src/controller/VideoContextPlayerCoordinatorFactory.ts" line-rate="0.88" name="src.controller.VideoContextPlayerCoordinatorFactory.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="4" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="VideoContextPlayerCoordinatorFactory" signature=""> + <lines> + <line branch="false" hits="33" number="11"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="33" number="14"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="4" number="2"/> + <line branch="false" hits="4" number="3"/> + <line branch="false" hits="4" number="4"/> + <line branch="false" hits="4" number="5"/> + <line branch="false" hits="4" number="6"/> + <line branch="false" hits="4" number="9"/> + <line branch="false" hits="33" number="12"/> + <line branch="false" hits="33" number="14"/> + <line branch="false" hits="33" number="15"/> + <line branch="false" hits="33" number="16"/> + <line branch="false" hits="33" number="17"/> + <line branch="false" hits="33" number="18"/> + <line branch="false" hits="33" number="19"/> + <line branch="false" hits="33" number="20"/> + <line branch="false" hits="33" number="22"/> + <line branch="true" condition-coverage="50% (1/2)" hits="33" number="24"/> + <line branch="false" hits="33" number="25"/> + <line branch="false" hits="0" number="28"/> + <line branch="false" hits="0" number="29"/> + <line branch="false" hits="33" number="32"/> + <line branch="false" hits="33" number="36"/> + <line branch="false" hits="0" number="42"/> + <line branch="false" hits="33" number="47"/> + <line branch="false" hits="33" number="52"/> + <line branch="false" hits="4" number="62"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/controller/index.ts" line-rate="1.0" name="src.controller.index.ts"> + <methods/> + <lines> + <line branch="false" hits="3" number="1"/> + <line branch="false" hits="3" number="2"/> + <line branch="false" hits="3" number="4"/> + <line branch="false" hits="3" number="5"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.8478260869565217" complexity="0" line-rate="0.8625592417061612" name="src.controller-x"> + <classes> + <class branch-rate="0.8478260869565217" complexity="0" filename="src/controller-x/VideoContextPlayerCoordinatorX.ts" line-rate="0.8313953488372093" name="src.controller-x.VideoContextPlayerCoordinatorX.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="3" number="43"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="VideoContextPlayerCoordinatorX" signature=""> + <lines> + <line branch="false" hits="30" number="59"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="21" number="99"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="0" number="126"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="0" number="132"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="1" number="219"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="13" number="233"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="0" number="290"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_36)" signature=""> + <lines> + <line branch="false" hits="17" number="338"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_37)" signature=""> + <lines> + <line branch="false" hits="17" number="341"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_38)" signature=""> + <lines> + <line branch="false" hits="17" number="362"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_39)" signature=""> + <lines> + <line branch="false" hits="0" number="363"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_40)" signature=""> + <lines> + <line branch="false" hits="7" number="422"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_41)" signature=""> + <lines> + <line branch="false" hits="5" number="435"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_42)" signature=""> + <lines> + <line branch="false" hits="30" number="444"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_43)" signature=""> + <lines> + <line branch="false" hits="3" number="458"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_44)" signature=""> + <lines> + <line branch="false" hits="1" number="466"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_45)" signature=""> + <lines> + <line branch="false" hits="1" number="477"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_46)" signature=""> + <lines> + <line branch="false" hits="0" number="507"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="3" number="1"/> + <line branch="false" hits="3" number="2"/> + <line branch="false" hits="3" number="25"/> + <line branch="false" hits="3" number="26"/> + <line branch="false" hits="3" number="27"/> + <line branch="false" hits="3" number="28"/> + <line branch="false" hits="3" number="29"/> + <line branch="false" hits="3" number="31"/> + <line branch="false" hits="3" number="34"/> + <line branch="false" hits="3" number="43"/> + <line branch="false" hits="30" number="57"/> + <line branch="false" hits="30" number="59"/> + <line branch="false" hits="30" number="60"/> + <line branch="false" hits="30" number="61"/> + <line branch="false" hits="30" number="62"/> + <line branch="false" hits="30" number="68"/> + <line branch="false" hits="30" number="73"/> + <line branch="false" hits="0" number="74"/> + <line branch="false" hits="0" number="75"/> + <line branch="false" hits="0" number="79"/> + <line branch="false" hits="30" number="81"/> + <line branch="false" hits="30" number="83"/> + <line branch="false" hits="30" number="85"/> + <line branch="false" hits="30" number="86"/> + <line branch="false" hits="30" number="89"/> + <line branch="false" hits="30" number="90"/> + <line branch="false" hits="30" number="92"/> + <line branch="false" hits="3" number="99"/> + <line branch="false" hits="21" number="100"/> + <line branch="false" hits="21" number="104"/> + <line branch="false" hits="21" number="109"/> + <line branch="true" condition-coverage="100% (1/1)" hits="0" number="110"/> + <line branch="false" hits="21" number="117"/> + <line branch="false" hits="21" number="121"/> + <line branch="false" hits="21" number="123"/> + <line branch="false" hits="21" number="129"/> + <line branch="false" hits="3" number="136"/> + <line branch="true" condition-coverage="50% (1/2)" hits="11" number="139"/> + <line branch="false" hits="11" number="141"/> + <line branch="false" hits="0" number="142"/> + <line branch="false" hits="0" number="143"/> + <line branch="false" hits="5" number="146"/> + <line branch="false" hits="5" number="147"/> + <line branch="false" hits="10" number="148"/> + <line branch="false" hits="5" number="150"/> + <line branch="false" hits="5" number="155"/> + <line branch="false" hits="1" number="158"/> + <line branch="false" hits="1" number="159"/> + <line branch="false" hits="1" number="160"/> + <line branch="false" hits="1" number="162"/> + <line branch="false" hits="1" number="164"/> + <line branch="false" hits="1" number="166"/> + <line branch="false" hits="2" number="168"/> + <line branch="false" hits="2" number="170"/> + <line branch="false" hits="1" number="174"/> + <line branch="false" hits="2" number="176"/> + <line branch="false" hits="2" number="178"/> + <line branch="false" hits="1" number="180"/> + <line branch="true" condition-coverage="50% (1/2)" hits="1" number="182"/> + <line branch="false" hits="1" number="183"/> + <line branch="false" hits="1" number="185"/> + <line branch="false" hits="1" number="187"/> + <line branch="false" hits="1" number="189"/> + <line branch="false" hits="0" number="191"/> + <line branch="false" hits="0" number="193"/> + <line branch="false" hits="0" number="195"/> + <line branch="false" hits="0" number="198"/> + <line branch="false" hits="0" number="201"/> + <line branch="false" hits="6" number="203"/> + <line branch="false" hits="3" number="206"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="209"/> + <line branch="false" hits="2" number="210"/> + <line branch="false" hits="2" number="212"/> + <line branch="false" hits="2" number="214"/> + <line branch="false" hits="0" number="216"/> + <line branch="false" hits="3" number="219"/> + <line branch="false" hits="1" number="223"/> + <line branch="false" hits="1" number="224"/> + <line branch="false" hits="1" number="225"/> + <line branch="false" hits="1" number="226"/> + <line branch="false" hits="3" number="233"/> + <line branch="false" hits="1" number="235"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="238"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="240"/> + <line branch="false" hits="1" number="243"/> + <line branch="false" hits="1" number="247"/> + <line branch="false" hits="1" number="250"/> + <line branch="false" hits="1" number="252"/> + <line branch="false" hits="1" number="256"/> + <line branch="false" hits="7" number="259"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="261"/> + <line branch="false" hits="7" number="262"/> + <line branch="false" hits="7" number="264"/> + <line branch="false" hits="7" number="265"/> + <line branch="false" hits="0" number="269"/> + <line branch="true" condition-coverage="100% (7/7)" hits="0" number="273"/> + <line branch="false" hits="1" number="274"/> + <line branch="false" hits="1" number="276"/> + <line branch="false" hits="1" number="278"/> + <line branch="false" hits="1" number="280"/> + <line branch="false" hits="1" number="282"/> + <line branch="false" hits="1" number="284"/> + <line branch="false" hits="1" number="286"/> + <line branch="false" hits="3" number="290"/> + <line branch="false" hits="0" number="291"/> + <line branch="false" hits="0" number="293"/> + <line branch="false" hits="3" number="299"/> + <line branch="false" hits="21" number="303"/> + <line branch="false" hits="21" number="306"/> + <line branch="false" hits="21" number="307"/> + <line branch="false" hits="7" number="310"/> + <line branch="true" condition-coverage="50% (1/2)" hits="7" number="311"/> + <line branch="false" hits="0" number="313"/> + <line branch="false" hits="0" number="316"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="320"/> + <line branch="false" hits="0" number="321"/> + <line branch="false" hits="0" number="325"/> + <line branch="false" hits="21" number="328"/> + <line branch="false" hits="21" number="333"/> + <line branch="false" hits="21" number="334"/> + <line branch="false" hits="21" number="335"/> + <line branch="false" hits="4" number="337"/> + <line branch="false" hits="17" number="338"/> + <line branch="false" hits="17" number="339"/> + <line branch="false" hits="0" number="350"/> + <line branch="false" hits="0" number="354"/> + <line branch="false" hits="0" number="355"/> + <line branch="false" hits="0" number="356"/> + <line branch="false" hits="17" number="360"/> + <line branch="false" hits="17" number="362"/> + <line branch="false" hits="0" number="363"/> + <line branch="false" hits="4" number="368"/> + <line branch="false" hits="21" number="371"/> + <line branch="true" condition-coverage="100% (2/2)" hits="21" number="373"/> + <line branch="false" hits="21" number="374"/> + <line branch="true" condition-coverage="100% (2/2)" hits="21" number="376"/> + <line branch="false" hits="21" number="379"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="386"/> + <line branch="false" hits="21" number="390"/> + <line branch="false" hits="21" number="391"/> + <line branch="false" hits="21" number="392"/> + <line branch="false" hits="21" number="393"/> + <line branch="false" hits="21" number="394"/> + <line branch="false" hits="21" number="397"/> + <line branch="false" hits="21" number="398"/> + <line branch="true" condition-coverage="100% (2/2)" hits="21" number="400"/> + <line branch="false" hits="21" number="402"/> + <line branch="false" hits="0" number="412"/> + <line branch="false" hits="21" number="415"/> + <line branch="false" hits="21" number="416"/> + <line branch="false" hits="3" number="422"/> + <line branch="false" hits="7" number="424"/> + <line branch="false" hits="7" number="428"/> + <line branch="false" hits="7" number="430"/> + <line branch="false" hits="3" number="435"/> + <line branch="false" hits="5" number="436"/> + <line branch="false" hits="5" number="438"/> + <line branch="false" hits="3" number="444"/> + <line branch="false" hits="0" number="446"/> + <line branch="false" hits="0" number="447"/> + <line branch="false" hits="0" number="450"/> + <line branch="false" hits="0" number="451"/> + <line branch="false" hits="30" number="453"/> + <line branch="false" hits="30" number="454"/> + <line branch="false" hits="30" number="455"/> + <line branch="false" hits="3" number="458"/> + <line branch="false" hits="3" number="459"/> + <line branch="false" hits="2" number="461"/> + <line branch="false" hits="2" number="462"/> + <line branch="false" hits="3" number="466"/> + <line branch="false" hits="1" number="467"/> + <line branch="false" hits="1" number="471"/> + <line branch="false" hits="3" number="477"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="478"/> + <line branch="false" hits="1" number="479"/> + <line branch="false" hits="1" number="482"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="483"/> + <line branch="false" hits="1" number="486"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="487"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="491"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="493"/> + <line branch="true" condition-coverage="75% (3/4)" hits="0" number="495"/> + <line branch="false" hits="1" number="499"/> + <line branch="false" hits="3" number="507"/> + <line branch="false" hits="0" number="508"/> + <line branch="false" hits="3" number="510"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/controller-x/VideoContextPlayerCoordinatorXObserver.ts" line-rate="1.0" name="src.controller-x.VideoContextPlayerCoordinatorXObserver.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="3" number="5"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="VideoContextPlayerCoordinatorXObserver" signature=""> + <lines> + <line branch="false" hits="3" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="1" number="13"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="4" number="17"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="0" number="24"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="1" number="26"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="30"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="0" number="32"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="1" number="34"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="0" number="38"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="0" number="40"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="0" number="42"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="1" number="44"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="0" number="48"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="0" number="50"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="0" number="52"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="1" number="54"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="1" number="58"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="1" number="62"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="1" number="66"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="1" number="70"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="0" number="74"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="0" number="76"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="0" number="78"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="3" number="2"/> + <line branch="false" hits="3" number="5"/> + <line branch="false" hits="3" number="10"/> + <line branch="false" hits="3" number="13"/> + <line branch="false" hits="1" number="14"/> + <line branch="false" hits="3" number="17"/> + <line branch="false" hits="4" number="18"/> + <line branch="false" hits="2" number="20"/> + <line branch="false" hits="3" number="24"/> + <line branch="false" hits="3" number="26"/> + <line branch="false" hits="1" number="27"/> + <line branch="false" hits="3" number="30"/> + <line branch="false" hits="3" number="32"/> + <line branch="false" hits="3" number="34"/> + <line branch="false" hits="1" number="35"/> + <line branch="false" hits="3" number="38"/> + <line branch="false" hits="3" number="40"/> + <line branch="false" hits="3" number="42"/> + <line branch="false" hits="3" number="44"/> + <line branch="false" hits="1" number="45"/> + <line branch="false" hits="3" number="48"/> + <line branch="false" hits="3" number="50"/> + <line branch="false" hits="3" number="52"/> + <line branch="false" hits="3" number="54"/> + <line branch="false" hits="1" number="55"/> + <line branch="false" hits="3" number="58"/> + <line branch="false" hits="1" number="59"/> + <line branch="false" hits="3" number="62"/> + <line branch="false" hits="1" number="63"/> + <line branch="false" hits="3" number="66"/> + <line branch="false" hits="1" number="67"/> + <line branch="false" hits="3" number="70"/> + <line branch="false" hits="1" number="71"/> + <line branch="false" hits="3" number="74"/> + <line branch="false" hits="3" number="76"/> + <line branch="false" hits="3" number="78"/> + <line branch="false" hits="3" number="79"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/controller-x/index.ts" line-rate="1.0" name="src.controller-x.index.ts"> + <methods/> + <lines> + <line branch="false" hits="3" number="1"/> + <line branch="false" hits="3" number="2"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.0" complexity="0" line-rate="0.7894736842105263" name="src.events"> + <classes> + <class branch-rate="0.0" complexity="0" filename="src/events/InternalPlaybackObserver.ts" line-rate="0.7291666666666666" name="src.events.InternalPlaybackObserver.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="11" number="17"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="InternalPlaybackObserver" signature=""> + <lines> + <line branch="false" hits="107" number="21"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="89" number="26"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="0" number="32"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="0" number="39"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="89" number="42"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="48"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="0" number="57"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="0" number="59"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="89" number="63"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="0" number="65"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="27" number="69"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="0" number="71"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="5" number="75"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="0" number="77"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="1" number="81"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="0" number="83"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="2" number="87"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="0" number="89"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="7" number="93"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="0" number="95"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="1" number="99"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="0" number="101"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="2" number="106"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="0" number="108"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="2" number="113"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="0" number="115"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="98" number="120"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="0" number="122"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="4" number="126"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="0" number="128"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="4" number="132"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="0" number="134"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="93" number="138"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_34)" signature=""> + <lines> + <line branch="false" hits="0" number="144"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_35)" signature=""> + <lines> + <line branch="false" hits="1" number="149"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_36)" signature=""> + <lines> + <line branch="false" hits="0" number="151"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_37)" signature=""> + <lines> + <line branch="false" hits="1" number="156"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_38)" signature=""> + <lines> + <line branch="false" hits="0" number="158"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_39)" signature=""> + <lines> + <line branch="false" hits="1" number="163"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_40)" signature=""> + <lines> + <line branch="false" hits="0" number="165"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_41)" signature=""> + <lines> + <line branch="false" hits="1" number="170"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_42)" signature=""> + <lines> + <line branch="false" hits="0" number="172"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_43)" signature=""> + <lines> + <line branch="false" hits="4" number="177"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_44)" signature=""> + <lines> + <line branch="false" hits="0" number="179"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_45)" signature=""> + <lines> + <line branch="false" hits="8" number="184"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_46)" signature=""> + <lines> + <line branch="false" hits="0" number="186"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_47)" signature=""> + <lines> + <line branch="false" hits="3" number="191"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_48)" signature=""> + <lines> + <line branch="false" hits="0" number="193"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="11" number="17"/> + <line branch="false" hits="107" number="22"/> + <line branch="false" hits="107" number="23"/> + <line branch="false" hits="11" number="26"/> + <line branch="false" hits="89" number="31"/> + <line branch="false" hits="0" number="33"/> + <line branch="false" hits="0" number="39"/> + <line branch="false" hits="11" number="42"/> + <line branch="false" hits="89" number="47"/> + <line branch="false" hits="89" number="48"/> + <line branch="false" hits="0" number="49"/> + <line branch="false" hits="11" number="57"/> + <line branch="false" hits="0" number="58"/> + <line branch="false" hits="0" number="59"/> + <line branch="false" hits="0" number="60"/> + <line branch="false" hits="11" number="63"/> + <line branch="false" hits="89" number="64"/> + <line branch="false" hits="89" number="65"/> + <line branch="false" hits="0" number="66"/> + <line branch="false" hits="11" number="69"/> + <line branch="false" hits="27" number="70"/> + <line branch="false" hits="27" number="71"/> + <line branch="false" hits="0" number="72"/> + <line branch="false" hits="11" number="75"/> + <line branch="false" hits="5" number="76"/> + <line branch="false" hits="5" number="77"/> + <line branch="false" hits="0" number="78"/> + <line branch="false" hits="11" number="81"/> + <line branch="false" hits="1" number="82"/> + <line branch="false" hits="1" number="83"/> + <line branch="false" hits="0" number="84"/> + <line branch="false" hits="11" number="87"/> + <line branch="false" hits="2" number="88"/> + <line branch="false" hits="2" number="89"/> + <line branch="false" hits="0" number="90"/> + <line branch="false" hits="11" number="93"/> + <line branch="false" hits="7" number="94"/> + <line branch="false" hits="7" number="95"/> + <line branch="false" hits="0" number="96"/> + <line branch="false" hits="11" number="99"/> + <line branch="false" hits="1" number="100"/> + <line branch="false" hits="1" number="101"/> + <line branch="false" hits="0" number="102"/> + <line branch="false" hits="11" number="106"/> + <line branch="false" hits="2" number="107"/> + <line branch="false" hits="2" number="108"/> + <line branch="false" hits="0" number="109"/> + <line branch="false" hits="11" number="113"/> + <line branch="false" hits="2" number="114"/> + <line branch="false" hits="2" number="115"/> + <line branch="false" hits="0" number="116"/> + <line branch="false" hits="11" number="120"/> + <line branch="false" hits="98" number="121"/> + <line branch="false" hits="98" number="122"/> + <line branch="false" hits="0" number="123"/> + <line branch="false" hits="11" number="126"/> + <line branch="false" hits="4" number="127"/> + <line branch="false" hits="4" number="128"/> + <line branch="false" hits="0" number="129"/> + <line branch="false" hits="11" number="132"/> + <line branch="false" hits="4" number="133"/> + <line branch="false" hits="4" number="134"/> + <line branch="false" hits="0" number="135"/> + <line branch="false" hits="11" number="138"/> + <line branch="false" hits="93" number="143"/> + <line branch="false" hits="93" number="144"/> + <line branch="false" hits="0" number="145"/> + <line branch="false" hits="11" number="149"/> + <line branch="false" hits="1" number="150"/> + <line branch="false" hits="1" number="151"/> + <line branch="false" hits="0" number="152"/> + <line branch="false" hits="11" number="156"/> + <line branch="false" hits="1" number="157"/> + <line branch="false" hits="1" number="158"/> + <line branch="false" hits="0" number="159"/> + <line branch="false" hits="11" number="163"/> + <line branch="false" hits="1" number="164"/> + <line branch="false" hits="1" number="165"/> + <line branch="false" hits="0" number="166"/> + <line branch="false" hits="11" number="170"/> + <line branch="false" hits="1" number="171"/> + <line branch="false" hits="1" number="172"/> + <line branch="false" hits="0" number="173"/> + <line branch="false" hits="11" number="177"/> + <line branch="false" hits="4" number="178"/> + <line branch="false" hits="4" number="179"/> + <line branch="false" hits="0" number="180"/> + <line branch="false" hits="11" number="184"/> + <line branch="false" hits="8" number="185"/> + <line branch="false" hits="8" number="186"/> + <line branch="false" hits="0" number="187"/> + <line branch="false" hits="11" number="191"/> + <line branch="false" hits="3" number="192"/> + <line branch="false" hits="3" number="193"/> + <line branch="false" hits="0" number="194"/> + <line branch="false" hits="11" number="197"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/events/PlaybackEventsObserver.ts" line-rate="0.9878048780487805" name="src.events.PlaybackEventsObserver.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="11" number="24"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="PlaybackEventsObserver" signature=""> + <lines> + <line branch="false" hits="90" number="28"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="89" number="36"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="12" number="48"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="6" number="52"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="89" number="56"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="71"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="89" number="75"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="27" number="88"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="4" number="97"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="1" number="101"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="1" number="105"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="2" number="112"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="7" number="116"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="1" number="124"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="2" number="129"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="2" number="134"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="98" number="142"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="4" number="150"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="4" number="157"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="93" number="165"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="1" number="177"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="1" number="184"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="1" number="191"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="1" number="196"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="4" number="204"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="8" number="211"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="3" number="219"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="461" number="227"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="11" number="13"/> + <line branch="false" hits="11" number="24"/> + <line branch="false" hits="90" number="32"/> + <line branch="false" hits="90" number="33"/> + <line branch="false" hits="11" number="36"/> + <line branch="false" hits="89" number="41"/> + <line branch="false" hits="11" number="48"/> + <line branch="false" hits="12" number="49"/> + <line branch="false" hits="11" number="52"/> + <line branch="false" hits="6" number="53"/> + <line branch="false" hits="11" number="56"/> + <line branch="false" hits="89" number="61"/> + <line branch="false" hits="89" number="66"/> + <line branch="false" hits="11" number="71"/> + <line branch="false" hits="0" number="72"/> + <line branch="false" hits="11" number="75"/> + <line branch="false" hits="89" number="80"/> + <line branch="false" hits="89" number="81"/> + <line branch="false" hits="11" number="88"/> + <line branch="false" hits="27" number="89"/> + <line branch="false" hits="27" number="90"/> + <line branch="false" hits="11" number="97"/> + <line branch="false" hits="4" number="98"/> + <line branch="false" hits="4" number="99"/> + <line branch="false" hits="11" number="101"/> + <line branch="false" hits="1" number="102"/> + <line branch="false" hits="1" number="103"/> + <line branch="false" hits="11" number="105"/> + <line branch="false" hits="1" number="106"/> + <line branch="false" hits="1" number="107"/> + <line branch="false" hits="11" number="112"/> + <line branch="false" hits="2" number="113"/> + <line branch="false" hits="2" number="114"/> + <line branch="false" hits="11" number="116"/> + <line branch="false" hits="7" number="117"/> + <line branch="false" hits="7" number="118"/> + <line branch="false" hits="11" number="124"/> + <line branch="false" hits="1" number="125"/> + <line branch="false" hits="1" number="126"/> + <line branch="false" hits="11" number="129"/> + <line branch="false" hits="2" number="130"/> + <line branch="false" hits="2" number="131"/> + <line branch="false" hits="11" number="134"/> + <line branch="false" hits="2" number="135"/> + <line branch="false" hits="2" number="136"/> + <line branch="false" hits="11" number="142"/> + <line branch="false" hits="98" number="143"/> + <line branch="false" hits="98" number="144"/> + <line branch="false" hits="11" number="150"/> + <line branch="false" hits="4" number="151"/> + <line branch="false" hits="4" number="152"/> + <line branch="false" hits="11" number="157"/> + <line branch="false" hits="4" number="158"/> + <line branch="false" hits="4" number="159"/> + <line branch="false" hits="11" number="165"/> + <line branch="false" hits="93" number="170"/> + <line branch="false" hits="93" number="171"/> + <line branch="false" hits="11" number="177"/> + <line branch="false" hits="1" number="178"/> + <line branch="false" hits="1" number="179"/> + <line branch="false" hits="11" number="184"/> + <line branch="false" hits="1" number="185"/> + <line branch="false" hits="1" number="186"/> + <line branch="false" hits="11" number="191"/> + <line branch="false" hits="1" number="192"/> + <line branch="false" hits="1" number="193"/> + <line branch="false" hits="11" number="196"/> + <line branch="false" hits="1" number="197"/> + <line branch="false" hits="1" number="198"/> + <line branch="false" hits="11" number="204"/> + <line branch="false" hits="4" number="205"/> + <line branch="false" hits="4" number="206"/> + <line branch="false" hits="11" number="211"/> + <line branch="false" hits="8" number="212"/> + <line branch="false" hits="8" number="213"/> + <line branch="false" hits="11" number="219"/> + <line branch="false" hits="3" number="220"/> + <line branch="false" hits="3" number="221"/> + <line branch="false" hits="11" number="227"/> + <line branch="false" hits="461" number="228"/> + <line branch="false" hits="461" number="229"/> + <line branch="false" hits="11" number="231"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/events/TimeObservable.ts" line-rate="0.37037037037037035" name="src.events.TimeObservable.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="13" number="4"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="TimeObservable" signature=""> + <lines> + <line branch="false" hits="101" number="8"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="0" number="13"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="0" number="14"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="0" number="17"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="22"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="0" number="27"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="0" number="31"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="11" number="41"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="0" number="46"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="13" number="4"/> + <line branch="false" hits="101" number="8"/> + <line branch="false" hits="101" number="9"/> + <line branch="false" hits="101" number="10"/> + <line branch="false" hits="101" number="13"/> + <line branch="false" hits="0" number="14"/> + <line branch="false" hits="0" number="15"/> + <line branch="false" hits="0" number="17"/> + <line branch="false" hits="0" number="18"/> + <line branch="false" hits="13" number="22"/> + <line branch="false" hits="0" number="26"/> + <line branch="false" hits="0" number="27"/> + <line branch="false" hits="0" number="28"/> + <line branch="false" hits="0" number="29"/> + <line branch="false" hits="0" number="30"/> + <line branch="false" hits="0" number="31"/> + <line branch="false" hits="0" number="33"/> + <line branch="false" hits="0" number="34"/> + <line branch="false" hits="0" number="36"/> + <line branch="false" hits="13" number="41"/> + <line branch="false" hits="11" number="45"/> + <line branch="false" hits="11" number="46"/> + <line branch="false" hits="0" number="47"/> + <line branch="false" hits="0" number="48"/> + <line branch="false" hits="0" number="52"/> + <line branch="false" hits="0" number="53"/> + <line branch="false" hits="13" number="57"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/events/index.ts" line-rate="1.0" name="src.events.index.ts"> + <methods/> + <lines> + <line branch="false" hits="11" number="1"/> + <line branch="false" hits="11" number="2"/> + <line branch="false" hits="11" number="4"/> + <line branch="false" hits="11" number="5"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.9067796610169492" complexity="0" line-rate="0.834319526627219" name="src.player"> + <classes> + <class branch-rate="0.8" complexity="0" filename="src/player/BetamaxPlayer.ts" line-rate="0.6951219512195121" name="src.player.BetamaxPlayer.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="10" number="25"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="BetamaxPlayer" signature=""> + <lines> + <line branch="false" hits="14" number="31"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="6" number="277"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="442" number="283"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="6" number="283"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="442" number="288"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="16" number="47"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="17" number="58"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="17" number="74"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="0" number="76"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="0" number="87"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="0" number="95"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="0" number="108"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="1" number="121"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="0" number="134"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="0" number="146"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="1" number="154"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="0" number="162"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="0" number="168"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="0" number="179"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="0" number="191"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="0" number="203"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="0" number="216"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="0" number="228"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="17" number="232"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_34)" signature=""> + <lines> + <line branch="false" hits="3" number="244"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_35)" signature=""> + <lines> + <line branch="false" hits="1" number="252"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_36)" signature=""> + <lines> + <line branch="false" hits="17" number="256"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_37)" signature=""> + <lines> + <line branch="false" hits="442" number="266"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="10" number="8"/> + <line branch="false" hits="10" number="9"/> + <line branch="false" hits="10" number="15"/> + <line branch="false" hits="10" number="17"/> + <line branch="false" hits="10" number="25"/> + <line branch="true" condition-coverage="100% (2/2)" hits="14" number="35"/> + <line branch="false" hits="14" number="36"/> + <line branch="false" hits="14" number="37"/> + <line branch="false" hits="14" number="38"/> + <line branch="false" hits="10" number="47"/> + <line branch="false" hits="16" number="48"/> + <line branch="false" hits="17" number="58"/> + <line branch="false" hits="17" number="62"/> + <line branch="false" hits="17" number="64"/> + <line branch="false" hits="17" number="69"/> + <line branch="false" hits="17" number="74"/> + <line branch="false" hits="0" number="76"/> + <line branch="false" hits="0" number="77"/> + <line branch="false" hits="10" number="87"/> + <line branch="false" hits="0" number="89"/> + <line branch="false" hits="0" number="91"/> + <line branch="false" hits="10" number="95"/> + <line branch="false" hits="0" number="97"/> + <line branch="false" hits="0" number="99"/> + <line branch="false" hits="10" number="108"/> + <line branch="false" hits="0" number="110"/> + <line branch="false" hits="0" number="112"/> + <line branch="false" hits="10" number="121"/> + <line branch="false" hits="1" number="122"/> + <line branch="false" hits="0" number="124"/> + <line branch="false" hits="1" number="126"/> + <line branch="false" hits="10" number="134"/> + <line branch="false" hits="0" number="136"/> + <line branch="false" hits="0" number="138"/> + <line branch="false" hits="10" number="146"/> + <line branch="false" hits="0" number="148"/> + <line branch="false" hits="0" number="150"/> + <line branch="false" hits="10" number="154"/> + <line branch="false" hits="1" number="156"/> + <line branch="false" hits="1" number="157"/> + <line branch="false" hits="1" number="158"/> + <line branch="false" hits="10" number="162"/> + <line branch="false" hits="0" number="164"/> + <line branch="false" hits="10" number="168"/> + <line branch="false" hits="0" number="170"/> + <line branch="false" hits="10" number="179"/> + <line branch="false" hits="0" number="181"/> + <line branch="false" hits="0" number="183"/> + <line branch="false" hits="0" number="193"/> + <line branch="false" hits="0" number="195"/> + <line branch="false" hits="0" number="205"/> + <line branch="false" hits="0" number="207"/> + <line branch="false" hits="0" number="218"/> + <line branch="false" hits="0" number="220"/> + <line branch="false" hits="10" number="228"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="229"/> + <line branch="false" hits="10" number="232"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="233"/> + <line branch="false" hits="2" number="234"/> + <line branch="true" condition-coverage="100% (2/2)" hits="2" number="238"/> + <line branch="false" hits="2" number="239"/> + <line branch="false" hits="2" number="240"/> + <line branch="false" hits="10" number="244"/> + <line branch="false" hits="3" number="246"/> + <line branch="false" hits="3" number="247"/> + <line branch="false" hits="3" number="248"/> + <line branch="false" hits="10" number="252"/> + <line branch="false" hits="1" number="253"/> + <line branch="false" hits="17" number="256"/> + <line branch="false" hits="17" number="261"/> + <line branch="false" hits="17" number="266"/> + <line branch="false" hits="442" number="267"/> + <line branch="false" hits="17" number="270"/> + <line branch="false" hits="17" number="271"/> + <line branch="false" hits="0" number="273"/> + <line branch="false" hits="18" number="277"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="278"/> + <line branch="false" hits="1" number="279"/> + <line branch="false" hits="442" number="283"/> + <line branch="false" hits="6" number="284"/> + <line branch="false" hits="6" number="285"/> + <line branch="false" hits="14" number="288"/> + <line branch="false" hits="442" number="293"/> + <line branch="false" hits="10" number="295"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/player/BetamaxPlayerFactory.ts" line-rate="1.0" name="src.player.BetamaxPlayerFactory.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="10" number="6"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="BetamaxPlayerFactory" signature=""> + <lines> + <line branch="false" hits="68" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="68" number="15"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="10" number="2"/> + <line branch="false" hits="10" number="3"/> + <line branch="false" hits="10" number="6"/> + <line branch="false" hits="68" number="12"/> + <line branch="false" hits="10" number="15"/> + <line branch="false" hits="68" number="16"/> + <line branch="false" hits="68" number="19"/> + <line branch="false" hits="10" number="21"/> + </lines> + </class> + <class branch-rate="0.9393939393939394" complexity="0" filename="src/player/PlaybackSession.ts" line-rate="0.8888888888888888" name="src.player.PlaybackSession.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="10" number="50"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="PlaybackSession" signature=""> + <lines> + <line branch="false" hits="90" number="71"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="92" number="165"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="2" number="170"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="89" number="177"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="13" number="179"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="1" number="90"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="90" number="136"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="93" number="146"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="89" number="185"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="89" number="189"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_34)" signature=""> + <lines> + <line branch="false" hits="0" number="301"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_35)" signature=""> + <lines> + <line branch="false" hits="0" number="310"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_36)" signature=""> + <lines> + <line branch="false" hits="89" number="324"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_37)" signature=""> + <lines> + <line branch="false" hits="89" number="334"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_38)" signature=""> + <lines> + <line branch="false" hits="890" number="339"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_39)" signature=""> + <lines> + <line branch="false" hits="356" number="343"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_40)" signature=""> + <lines> + <line branch="false" hits="4" number="349"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_41)" signature=""> + <lines> + <line branch="false" hits="40" number="351"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_42)" signature=""> + <lines> + <line branch="false" hits="16" number="355"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_43)" signature=""> + <lines> + <line branch="false" hits="0" number="361"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_44)" signature=""> + <lines> + <line branch="false" hits="5" number="365"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_45)" signature=""> + <lines> + <line branch="false" hits="89" number="392"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_49)" signature=""> + <lines> + <line branch="false" hits="0" number="443"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_50)" signature=""> + <lines> + <line branch="false" hits="4" number="458"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_51)" signature=""> + <lines> + <line branch="false" hits="89" number="485"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_52)" signature=""> + <lines> + <line branch="false" hits="1" number="501"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_53)" signature=""> + <lines> + <line branch="false" hits="4" number="514"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_54)" signature=""> + <lines> + <line branch="false" hits="1" number="525"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_55)" signature=""> + <lines> + <line branch="false" hits="13" number="529"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_56)" signature=""> + <lines> + <line branch="false" hits="19" number="558"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_57)" signature=""> + <lines> + <line branch="false" hits="12" number="567"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_58)" signature=""> + <lines> + <line branch="false" hits="14" number="571"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_59)" signature=""> + <lines> + <line branch="false" hits="5" number="581"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_60)" signature=""> + <lines> + <line branch="false" hits="4" number="596"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_61)" signature=""> + <lines> + <line branch="false" hits="27" number="608"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_62)" signature=""> + <lines> + <line branch="false" hits="0" number="619"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_63)" signature=""> + <lines> + <line branch="false" hits="100" number="623"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_64)" signature=""> + <lines> + <line branch="false" hits="8" number="714"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_65)" signature=""> + <lines> + <line branch="false" hits="8" number="719"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_66)" signature=""> + <lines> + <line branch="false" hits="1" number="762"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_67)" signature=""> + <lines> + <line branch="false" hits="2" number="768"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_68)" signature=""> + <lines> + <line branch="false" hits="3" number="782"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_69)" signature=""> + <lines> + <line branch="false" hits="185" number="803"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_70)" signature=""> + <lines> + <line branch="false" hits="1" number="840"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_71)" signature=""> + <lines> + <line branch="false" hits="90" number="844"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_72)" signature=""> + <lines> + <line branch="false" hits="90" number="849"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_73)" signature=""> + <lines> + <line branch="false" hits="6" number="860"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_74)" signature=""> + <lines> + <line branch="false" hits="211" number="869"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_75)" signature=""> + <lines> + <line branch="false" hits="8" number="875"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_76)" signature=""> + <lines> + <line branch="false" hits="2" number="879"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_77)" signature=""> + <lines> + <line branch="false" hits="8" number="885"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_78)" signature=""> + <lines> + <line branch="false" hits="3" number="922"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_79)" signature=""> + <lines> + <line branch="false" hits="1" number="939"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_80)" signature=""> + <lines> + <line branch="false" hits="91" number="952"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_81)" signature=""> + <lines> + <line branch="false" hits="1562" number="965"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_82)" signature=""> + <lines> + <line branch="false" hits="774" number="969"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_83)" signature=""> + <lines> + <line branch="false" hits="1" number="983"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_84)" signature=""> + <lines> + <line branch="false" hits="1" number="987"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_85)" signature=""> + <lines> + <line branch="false" hits="9" number="991"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_86)" signature=""> + <lines> + <line branch="false" hits="96" number="1026"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_87)" signature=""> + <lines> + <line branch="false" hits="6" number="1035"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_88)" signature=""> + <lines> + <line branch="false" hits="8" number="1040"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_89)" signature=""> + <lines> + <line branch="false" hits="0" number="1076"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_93)" signature=""> + <lines> + <line branch="false" hits="6" number="1123"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_94)" signature=""> + <lines> + <line branch="false" hits="1" number="1134"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_95)" signature=""> + <lines> + <line branch="false" hits="90" number="1138"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_96)" signature=""> + <lines> + <line branch="false" hits="0" number="1142"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_97)" signature=""> + <lines> + <line branch="false" hits="0" number="1146"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_98)" signature=""> + <lines> + <line branch="false" hits="0" number="1150"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_99)" signature=""> + <lines> + <line branch="false" hits="2" number="1154"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_100)" signature=""> + <lines> + <line branch="false" hits="0" number="1158"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="10" number="1"/> + <line branch="false" hits="10" number="7"/> + <line branch="false" hits="10" number="8"/> + <line branch="false" hits="10" number="9"/> + <line branch="false" hits="10" number="10"/> + <line branch="false" hits="10" number="11"/> + <line branch="false" hits="10" number="33"/> + <line branch="false" hits="10" number="34"/> + <line branch="false" hits="10" number="42"/> + <line branch="false" hits="10" number="44"/> + <line branch="false" hits="10" number="45"/> + <line branch="false" hits="10" number="48"/> + <line branch="false" hits="10" number="50"/> + <line branch="true" condition-coverage="100% (2/2)" hits="90" number="75"/> + <line branch="false" hits="90" number="76"/> + <line branch="false" hits="90" number="77"/> + <line branch="false" hits="90" number="78"/> + <line branch="false" hits="1" number="83"/> + <line branch="false" hits="1" number="87"/> + <line branch="false" hits="90" number="90"/> + <line branch="false" hits="1" number="92"/> + <line branch="false" hits="1" number="96"/> + <line branch="false" hits="1" number="97"/> + <line branch="false" hits="90" number="101"/> + <line branch="false" hits="90" number="111"/> + <line branch="false" hits="90" number="116"/> + <line branch="false" hits="90" number="128"/> + <line branch="false" hits="10" number="136"/> + <line branch="false" hits="90" number="143"/> + <line branch="false" hits="10" number="146"/> + <line branch="false" hits="1" number="150"/> + <line branch="false" hits="1" number="153"/> + <line branch="false" hits="1" number="156"/> + <line branch="false" hits="1" number="159"/> + <line branch="false" hits="89" number="162"/> + <line branch="false" hits="90" number="165"/> + <line branch="true" condition-coverage="100% (2/2)" hits="182" number="167"/> + <line branch="false" hits="92" number="169"/> + <line branch="false" hits="2" number="171"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="172"/> + <line branch="false" hits="90" number="177"/> + <line branch="false" hits="89" number="179"/> + <line branch="false" hits="0" number="181"/> + <line branch="false" hits="89" number="185"/> + <line branch="false" hits="89" number="189"/> + <line branch="false" hits="89" number="191"/> + <line branch="false" hits="89" number="195"/> + <line branch="false" hits="89" number="199"/> + <line branch="false" hits="89" number="201"/> + <line branch="false" hits="89" number="204"/> + <line branch="false" hits="89" number="208"/> + <line branch="false" hits="89" number="212"/> + <line branch="false" hits="1" number="216"/> + <line branch="false" hits="1" number="220"/> + <line branch="false" hits="1" number="222"/> + <line branch="false" hits="1" number="229"/> + <line branch="false" hits="89" number="232"/> + <line branch="false" hits="89" number="233"/> + <line branch="false" hits="89" number="235"/> + <line branch="false" hits="89" number="236"/> + <line branch="false" hits="89" number="241"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="243"/> + <line branch="false" hits="89" number="245"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="247"/> + <line branch="false" hits="0" number="253"/> + <line branch="false" hits="89" number="259"/> + <line branch="false" hits="89" number="266"/> + <line branch="false" hits="89" number="267"/> + <line branch="false" hits="89" number="268"/> + <line branch="false" hits="89" number="269"/> + <line branch="false" hits="89" number="271"/> + <line branch="false" hits="89" number="273"/> + <line branch="false" hits="89" number="276"/> + <line branch="false" hits="89" number="283"/> + <line branch="false" hits="89" number="286"/> + <line branch="false" hits="89" number="290"/> + <line branch="false" hits="89" number="295"/> + <line branch="false" hits="89" number="300"/> + <line branch="false" hits="0" number="302"/> + <line branch="false" hits="0" number="308"/> + <line branch="false" hits="0" number="310"/> + <line branch="false" hits="0" number="312"/> + <line branch="false" hits="0" number="313"/> + <line branch="false" hits="0" number="314"/> + <line branch="false" hits="0" number="316"/> + <line branch="false" hits="89" number="325"/> + <line branch="false" hits="89" number="328"/> + <line branch="false" hits="89" number="329"/> + <line branch="false" hits="89" number="330"/> + <line branch="false" hits="89" number="334"/> + <line branch="false" hits="89" number="335"/> + <line branch="false" hits="89" number="339"/> + <line branch="false" hits="890" number="340"/> + <line branch="false" hits="89" number="343"/> + <line branch="false" hits="356" number="344"/> + <line branch="false" hits="10" number="349"/> + <line branch="false" hits="4" number="350"/> + <line branch="false" hits="4" number="351"/> + <line branch="false" hits="40" number="352"/> + <line branch="false" hits="4" number="355"/> + <line branch="false" hits="16" number="356"/> + <line branch="false" hits="10" number="361"/> + <line branch="false" hits="0" number="362"/> + <line branch="false" hits="10" number="365"/> + <line branch="false" hits="3" number="368"/> + <line branch="false" hits="3" number="369"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="370"/> + <line branch="false" hits="2" number="374"/> + <line branch="false" hits="2" number="375"/> + <line branch="false" hits="1" number="383"/> + <line branch="false" hits="1" number="384"/> + <line branch="false" hits="89" number="392"/> + <line branch="false" hits="89" number="393"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="409"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="410"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="411"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="413"/> + <line branch="false" hits="10" number="426"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="428"/> + <line branch="false" hits="0" number="431"/> + <line branch="false" hits="3" number="434"/> + <line branch="false" hits="3" number="436"/> + <line branch="false" hits="0" number="437"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="440"/> + <line branch="false" hits="0" number="441"/> + <line branch="false" hits="0" number="442"/> + <line branch="false" hits="0" number="444"/> + <line branch="false" hits="0" number="445"/> + <line branch="false" hits="0" number="449"/> + <line branch="false" hits="2" number="451"/> + <line branch="false" hits="1" number="454"/> + <line branch="false" hits="10" number="458"/> + <line branch="true" condition-coverage="100% (4/4)" hits="0" number="460"/> + <line branch="false" hits="1" number="465"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="471"/> + <line branch="false" hits="2" number="476"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="477"/> + <line branch="false" hits="2" number="479"/> + <line branch="false" hits="2" number="480"/> + <line branch="false" hits="10" number="485"/> + <line branch="false" hits="89" number="486"/> + <line branch="false" hits="89" number="487"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="488"/> + <line branch="false" hits="1" number="489"/> + <line branch="false" hits="1" number="492"/> + <line branch="false" hits="89" number="494"/> + <line branch="false" hits="10" number="501"/> + <line branch="false" hits="1" number="502"/> + <line branch="false" hits="1" number="505"/> + <line branch="false" hits="1" number="507"/> + <line branch="false" hits="10" number="514"/> + <line branch="false" hits="4" number="515"/> + <line branch="false" hits="4" number="516"/> + <line branch="false" hits="4" number="517"/> + <line branch="false" hits="4" number="522"/> + <line branch="false" hits="10" number="525"/> + <line branch="false" hits="1" number="526"/> + <line branch="false" hits="10" number="529"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="530"/> + <line branch="false" hits="1" number="532"/> + <line branch="true" condition-coverage="100% (3/3)" hits="12" number="535"/> + <line branch="false" hits="12" number="537"/> + <line branch="false" hits="12" number="538"/> + <line branch="false" hits="12" number="540"/> + <line branch="false" hits="12" number="549"/> + <line branch="false" hits="12" number="550"/> + <line branch="false" hits="2" number="553"/> + <line branch="false" hits="2" number="554"/> + <line branch="false" hits="10" number="558"/> + <line branch="false" hits="19" number="559"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="560"/> + <line branch="false" hits="16" number="561"/> + <line branch="false" hits="16" number="562"/> + <line branch="false" hits="19" number="564"/> + <line branch="false" hits="12" number="567"/> + <line branch="false" hits="11" number="571"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="572"/> + <line branch="false" hits="6" number="574"/> + <line branch="false" hits="10" number="581"/> + <line branch="false" hits="5" number="582"/> + <line branch="false" hits="5" number="583"/> + <line branch="false" hits="4" number="590"/> + <line branch="false" hits="1" number="592"/> + <line branch="false" hits="10" number="596"/> + <line branch="false" hits="4" number="597"/> + <line branch="false" hits="4" number="601"/> + <line branch="false" hits="4" number="602"/> + <line branch="false" hits="2" number="604"/> + <line branch="false" hits="10" number="608"/> + <line branch="true" condition-coverage="100% (2/2)" hits="27" number="609"/> + <line branch="true" condition-coverage="100% (2/2)" hits="27" number="610"/> + <line branch="false" hits="27" number="611"/> + <line branch="false" hits="27" number="612"/> + <line branch="false" hits="10" number="619"/> + <line branch="false" hits="0" number="620"/> + <line branch="false" hits="10" number="623"/> + <line branch="false" hits="99" number="625"/> + <line branch="false" hits="100" number="639"/> + <line branch="false" hits="100" number="640"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="642"/> + <line branch="false" hits="6" number="643"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="646"/> + <line branch="false" hits="6" number="647"/> + <line branch="false" hits="100" number="650"/> + <line branch="false" hits="100" number="652"/> + <line branch="false" hits="100" number="653"/> + <line branch="false" hits="100" number="654"/> + <line branch="true" condition-coverage="100% (3/3)" hits="0" number="657"/> + <line branch="false" hits="2" number="663"/> + <line branch="false" hits="2" number="664"/> + <line branch="false" hits="2" number="665"/> + <line branch="false" hits="100" number="668"/> + <line branch="true" condition-coverage="100% (5/5)" hits="0" number="671"/> + <line branch="false" hits="2" number="677"/> + <line branch="false" hits="100" number="680"/> + <line branch="true" condition-coverage="100% (2/2)" hits="100" number="683"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="684"/> + <line branch="false" hits="2" number="693"/> + <line branch="false" hits="98" number="695"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="698"/> + <line branch="false" hits="84" number="699"/> + <line branch="false" hits="100" number="701"/> + <line branch="false" hits="100" number="711"/> + <line branch="false" hits="10" number="714"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="715"/> + <line branch="false" hits="0" number="716"/> + <line branch="false" hits="8" number="719"/> + <line branch="false" hits="1" number="721"/> + <line branch="false" hits="7" number="723"/> + <line branch="false" hits="2" number="726"/> + <line branch="false" hits="4" number="742"/> + <line branch="false" hits="4" number="749"/> + <line branch="false" hits="5" number="755"/> + <line branch="false" hits="10" number="762"/> + <line branch="false" hits="1" number="763"/> + <line branch="false" hits="10" number="768"/> + <line branch="false" hits="1" number="771"/> + <line branch="false" hits="1" number="774"/> + <line branch="false" hits="1" number="775"/> + <line branch="false" hits="10" number="782"/> + <line branch="false" hits="3" number="784"/> + <line branch="false" hits="3" number="787"/> + <line branch="false" hits="3" number="793"/> + <line branch="false" hits="10" number="803"/> + <line branch="false" hits="93" number="806"/> + <line branch="true" condition-coverage="100% (2/2)" hits="6" number="808"/> + <line branch="false" hits="93" number="810"/> + <line branch="false" hits="93" number="816"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="823"/> + <line branch="false" hits="4" number="827"/> + <line branch="false" hits="92" number="833"/> + <line branch="false" hits="10" number="840"/> + <line branch="false" hits="1" number="841"/> + <line branch="false" hits="90" number="844"/> + <line branch="false" hits="0" number="846"/> + <line branch="false" hits="90" number="849"/> + <line branch="false" hits="90" number="850"/> + <line branch="false" hits="90" number="851"/> + <line branch="false" hits="90" number="853"/> + <line branch="false" hits="90" number="854"/> + <line branch="false" hits="10" number="860"/> + <line branch="false" hits="6" number="861"/> + <line branch="false" hits="6" number="862"/> + <line branch="false" hits="6" number="863"/> + <line branch="false" hits="6" number="864"/> + <line branch="false" hits="6" number="865"/> + <line branch="false" hits="6" number="866"/> + <line branch="false" hits="10" number="869"/> + <line branch="true" condition-coverage="100% (2/2)" hits="211" number="870"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="871"/> + <line branch="false" hits="10" number="875"/> + <line branch="false" hits="2" number="877"/> + <line branch="false" hits="2" number="879"/> + <line branch="true" condition-coverage="50% (1/2)" hits="2" number="880"/> + <line branch="false" hits="6" number="882"/> + <line branch="false" hits="10" number="885"/> + <line branch="false" hits="8" number="887"/> + <line branch="false" hits="8" number="888"/> + <line branch="false" hits="1" number="892"/> + <line branch="false" hits="7" number="895"/> + <line branch="false" hits="7" number="896"/> + <line branch="false" hits="7" number="897"/> + <line branch="false" hits="4" number="899"/> + <line branch="false" hits="4" number="900"/> + <line branch="false" hits="2" number="909"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="912"/> + <line branch="false" hits="0" number="915"/> + <line branch="false" hits="7" number="919"/> + <line branch="false" hits="10" number="922"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="927"/> + <line branch="false" hits="3" number="929"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="930"/> + <line branch="false" hits="3" number="933"/> + <line branch="false" hits="0" number="936"/> + <line branch="false" hits="10" number="939"/> + <line branch="true" condition-coverage="100% (4/4)" hits="0" number="941"/> + <line branch="false" hits="1" number="946"/> + <line branch="false" hits="0" number="949"/> + <line branch="false" hits="10" number="952"/> + <line branch="false" hits="1" number="954"/> + <line branch="false" hits="1" number="955"/> + <line branch="false" hits="90" number="957"/> + <line branch="false" hits="90" number="958"/> + <line branch="false" hits="91" number="960"/> + <line branch="false" hits="91" number="961"/> + <line branch="false" hits="91" number="962"/> + <line branch="false" hits="10" number="965"/> + <line branch="true" condition-coverage="100% (2/2)" hits="1562" number="966"/> + <line branch="false" hits="10" number="969"/> + <line branch="false" hits="774" number="970"/> + <line branch="false" hits="774" number="971"/> + <line branch="false" hits="774" number="972"/> + <line branch="false" hits="563" number="975"/> + <line branch="false" hits="774" number="978"/> + <line branch="false" hits="10" number="983"/> + <line branch="false" hits="1" number="984"/> + <line branch="false" hits="10" number="987"/> + <line branch="false" hits="1" number="988"/> + <line branch="false" hits="10" number="991"/> + <line branch="false" hits="9" number="992"/> + <line branch="false" hits="0" number="995"/> + <line branch="true" condition-coverage="100% (2/2)" hits="9" number="997"/> + <line branch="false" hits="2" number="999"/> + <line branch="false" hits="1" number="1005"/> + <line branch="false" hits="9" number="1008"/> + <line branch="false" hits="9" number="1013"/> + <line branch="false" hits="9" number="1014"/> + <line branch="false" hits="9" number="1021"/> + <line branch="false" hits="9" number="1023"/> + <line branch="false" hits="10" number="1026"/> + <line branch="false" hits="96" number="1029"/> + <line branch="false" hits="96" number="1030"/> + <line branch="false" hits="96" number="1031"/> + <line branch="false" hits="96" number="1032"/> + <line branch="false" hits="10" number="1035"/> + <line branch="false" hits="6" number="1036"/> + <line branch="false" hits="6" number="1037"/> + <line branch="false" hits="10" number="1040"/> + <line branch="false" hits="8" number="1041"/> + <line branch="false" hits="8" number="1042"/> + <line branch="false" hits="8" number="1046"/> + <line branch="false" hits="8" number="1048"/> + <line branch="false" hits="8" number="1052"/> + <line branch="false" hits="0" number="1054"/> + <line branch="false" hits="0" number="1055"/> + <line branch="false" hits="0" number="1056"/> + <line branch="false" hits="0" number="1058"/> + <line branch="false" hits="8" number="1064"/> + <line branch="false" hits="0" number="1069"/> + <line branch="false" hits="8" number="1073"/> + <line branch="false" hits="10" number="1076"/> + <line branch="false" hits="0" number="1078"/> + <line branch="false" hits="10" number="1084"/> + <line branch="false" hits="4" number="1085"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="1086"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="1087"/> + <line branch="false" hits="4" number="1089"/> + <line branch="false" hits="4" number="1091"/> + <line branch="false" hits="4" number="1093"/> + <line branch="false" hits="4" number="1094"/> + <line branch="false" hits="4" number="1099"/> + <line branch="false" hits="0" number="1100"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="1101"/> + <line branch="false" hits="0" number="1102"/> + <line branch="false" hits="8" number="1105"/> + <line branch="false" hits="0" number="1106"/> + <line branch="false" hits="0" number="1108"/> + <line branch="false" hits="0" number="1112"/> + <line branch="false" hits="4" number="1115"/> + <line branch="false" hits="4" number="1117"/> + <line branch="false" hits="4" number="1118"/> + <line branch="false" hits="4" number="1119"/> + <line branch="false" hits="10" number="1123"/> + <line branch="false" hits="6" number="1125"/> + <line branch="false" hits="10" number="1134"/> + <line branch="false" hits="1" number="1135"/> + <line branch="false" hits="10" number="1138"/> + <line branch="false" hits="90" number="1139"/> + <line branch="false" hits="0" number="1143"/> + <line branch="false" hits="0" number="1147"/> + <line branch="false" hits="0" number="1151"/> + <line branch="false" hits="2" number="1155"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="1159"/> + <line branch="false" hits="10" number="1161"/> + </lines> + </class> + <class branch-rate="0.6666666666666666" complexity="0" filename="src/player/PlaybackSessionFactory.ts" line-rate="0.5" name="src.player.PlaybackSessionFactory.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="10" number="10"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="PlaybackSessionFactory" signature=""> + <lines> + <line branch="false" hits="68" number="13"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="17" number="19"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="70"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="10" number="2"/> + <line branch="false" hits="10" number="3"/> + <line branch="false" hits="10" number="4"/> + <line branch="false" hits="10" number="10"/> + <line branch="false" hits="68" number="16"/> + <line branch="false" hits="10" number="19"/> + <line branch="true" condition-coverage="100% (2/2)" hits="17" number="23"/> + <line branch="false" hits="0" number="25"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="33"/> + <line branch="false" hits="0" number="34"/> + <line branch="false" hits="0" number="35"/> + <line branch="false" hits="0" number="36"/> + <line branch="false" hits="0" number="37"/> + <line branch="false" hits="0" number="38"/> + <line branch="false" hits="0" number="39"/> + <line branch="false" hits="0" number="42"/> + <line branch="false" hits="0" number="53"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="62"/> + <line branch="false" hits="0" number="63"/> + <line branch="false" hits="17" number="68"/> + <line branch="false" hits="17" number="70"/> + <line branch="false" hits="0" number="71"/> + <line branch="false" hits="17" number="72"/> + <line branch="false" hits="10" number="78"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/player/index.ts" line-rate="1.0" name="src.player.index.ts"> + <methods/> + <lines> + <line branch="false" hits="10" number="1"/> + <line branch="false" hits="10" number="2"/> + <line branch="false" hits="10" number="3"/> + <line branch="false" hits="10" number="4"/> + <line branch="false" hits="10" number="5"/> + <line branch="false" hits="10" number="6"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/player/player.ts" line-rate="0.7647058823529411" name="src.player.player.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="12" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="Player" signature=""> + <lines> + <line branch="false" hits="89" number="12"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="89" number="16"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="0" number="18"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="186" number="25"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="89" number="29"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="0" number="37"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="0" number="41"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="0" number="45"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="0" number="49"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="26" number="53"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="356" number="57"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="16" number="61"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="0" number="65"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="0" number="69"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="0" number="73"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="12" number="1"/> + <line branch="false" hits="12" number="4"/> + <line branch="false" hits="12" number="5"/> + <line branch="false" hits="12" number="9"/> + <line branch="false" hits="89" number="13"/> + <line branch="false" hits="12" number="16"/> + <line branch="false" hits="89" number="18"/> + <line branch="false" hits="0" number="19"/> + <line branch="false" hits="89" number="22"/> + <line branch="false" hits="12" number="25"/> + <line branch="false" hits="186" number="26"/> + <line branch="false" hits="12" number="29"/> + <line branch="false" hits="89" number="34"/> + <line branch="false" hits="12" number="37"/> + <line branch="false" hits="0" number="38"/> + <line branch="false" hits="12" number="41"/> + <line branch="false" hits="0" number="42"/> + <line branch="false" hits="12" number="45"/> + <line branch="false" hits="0" number="46"/> + <line branch="false" hits="12" number="49"/> + <line branch="false" hits="0" number="50"/> + <line branch="false" hits="12" number="53"/> + <line branch="false" hits="26" number="54"/> + <line branch="false" hits="12" number="57"/> + <line branch="false" hits="356" number="58"/> + <line branch="false" hits="12" number="61"/> + <line branch="false" hits="16" number="62"/> + <line branch="false" hits="12" number="65"/> + <line branch="false" hits="0" number="66"/> + <line branch="false" hits="12" number="69"/> + <line branch="false" hits="0" number="70"/> + <line branch="false" hits="12" number="73"/> + <line branch="false" hits="0" number="74"/> + <line branch="false" hits="12" number="76"/> + </lines> + </class> + <class branch-rate="0.6666666666666666" complexity="0" filename="src/player/shaka.ts" line-rate="0.75" name="src.player.shaka.ts"> + <methods/> + <lines> + <line branch="false" hits="13" number="2"/> + <line branch="false" hits="13" number="5"/> + <line branch="true" condition-coverage="66% (2/3)" hits="0" number="6"/> + <line branch="false" hits="0" number="7"/> + <line branch="false" hits="13" number="10"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.5135135135135135" complexity="0" line-rate="0.6158038147138964" name="src.plugins"> + <classes> + <class branch-rate="0.7878787878787878" complexity="0" filename="src/plugins/SPManifestParser.ts" line-rate="0.9026548672566371" name="src.plugins.SPManifestParser.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="ManifestParser" signature=""> + <lines> + <line branch="false" hits="5" number="26"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="5" number="40"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="5" number="45"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="5" number="60"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="0" number="67"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="70"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="0" number="75"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="5" number="87"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="5" number="94"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="5" number="113"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="5" number="152"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="13" number="159"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="5" number="173"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="22" number="175"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="5" number="186"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="18" number="191"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="0" number="211"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="0" number="218"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="13" number="226"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="13" number="227"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="13" number="242"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="5" number="281"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="8" number="289"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="8" number="298"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="34" number="313"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="0" number="332"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="26" number="366"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="2" number="367"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="4" number="368"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="34" number="388"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="2" number="399"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="2" number="405"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="3972" number="461"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_34)" signature=""> + <lines> + <line branch="false" hits="2" number="467"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_35)" signature=""> + <lines> + <line branch="false" hits="4" number="468"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="9" number="18"/> + <line branch="false" hits="5" number="27"/> + <line branch="false" hits="5" number="28"/> + <line branch="false" hits="5" number="29"/> + <line branch="false" hits="5" number="30"/> + <line branch="false" hits="5" number="31"/> + <line branch="false" hits="5" number="32"/> + <line branch="false" hits="5" number="33"/> + <line branch="false" hits="5" number="34"/> + <line branch="false" hits="5" number="35"/> + <line branch="false" hits="5" number="36"/> + <line branch="false" hits="9" number="40"/> + <line branch="false" hits="5" number="41"/> + <line branch="false" hits="9" number="45"/> + <line branch="false" hits="0" number="47"/> + <line branch="false" hits="5" number="50"/> + <line branch="false" hits="5" number="59"/> + <line branch="false" hits="5" number="60"/> + <line branch="false" hits="5" number="61"/> + <line branch="false" hits="5" number="62"/> + <line branch="false" hits="9" number="67"/> + <line branch="false" hits="9" number="70"/> + <line branch="false" hits="9" number="75"/> + <line branch="false" hits="9" number="87"/> + <line branch="false" hits="5" number="88"/> + <line branch="false" hits="5" number="91"/> + <line branch="false" hits="5" number="92"/> + <line branch="false" hits="5" number="94"/> + <line branch="false" hits="5" number="95"/> + <line branch="false" hits="5" number="98"/> + <line branch="false" hits="9" number="113"/> + <line branch="false" hits="5" number="114"/> + <line branch="false" hits="0" number="117"/> + <line branch="false" hits="0" number="120"/> + <line branch="false" hits="0" number="122"/> + <line branch="false" hits="5" number="130"/> + <line branch="false" hits="0" number="134"/> + <line branch="false" hits="5" number="141"/> + <line branch="false" hits="9" number="152"/> + <line branch="false" hits="5" number="153"/> + <line branch="false" hits="5" number="154"/> + <line branch="false" hits="5" number="156"/> + <line branch="false" hits="13" number="160"/> + <line branch="false" hits="9" number="173"/> + <line branch="false" hits="5" number="174"/> + <line branch="false" hits="22" number="175"/> + <line branch="false" hits="9" number="186"/> + <line branch="false" hits="5" number="188"/> + <line branch="false" hits="5" number="189"/> + <line branch="false" hits="5" number="191"/> + <line branch="false" hits="18" number="192"/> + <line branch="true" condition-coverage="66% (2/3)" hits="0" number="194"/> + <line branch="false" hits="13" number="195"/> + <line branch="false" hits="13" number="196"/> + <line branch="false" hits="5" number="198"/> + <line branch="false" hits="5" number="199"/> + <line branch="false" hits="0" number="201"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="206"/> + <line branch="false" hits="0" number="207"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="210"/> + <line branch="false" hits="0" number="211"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="217"/> + <line branch="false" hits="0" number="218"/> + <line branch="false" hits="5" number="225"/> + <line branch="false" hits="5" number="226"/> + <line branch="false" hits="13" number="227"/> + <line branch="false" hits="13" number="228"/> + <line branch="false" hits="5" number="231"/> + <line branch="false" hits="9" number="242"/> + <line branch="true" condition-coverage="100% (2/2)" hits="13" number="247"/> + <line branch="true" condition-coverage="50% (1/2)" hits="13" number="249"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="250"/> + <line branch="false" hits="13" number="252"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="257"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="260"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="265"/> + <line branch="false" hits="9" number="281"/> + <line branch="false" hits="5" number="284"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="286"/> + <line branch="false" hits="8" number="289"/> + <line branch="false" hits="5" number="298"/> + <line branch="false" hits="8" number="299"/> + <line branch="false" hits="9" number="313"/> + <line branch="false" hits="34" number="319"/> + <line branch="false" hits="34" number="322"/> + <line branch="false" hits="13" number="324"/> + <line branch="false" hits="13" number="327"/> + <line branch="false" hits="34" number="330"/> + <line branch="false" hits="0" number="333"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="338"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="343"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="344"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="345"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="348"/> + <line branch="false" hits="26" number="366"/> + <line branch="false" hits="26" number="367"/> + <line branch="false" hits="2" number="368"/> + <line branch="false" hits="4" number="369"/> + <line branch="false" hits="2" number="373"/> + <line branch="false" hits="26" number="376"/> + <line branch="false" hits="34" number="388"/> + <line branch="false" hits="34" number="393"/> + <line branch="false" hits="34" number="395"/> + <line branch="false" hits="34" number="396"/> + <line branch="false" hits="8" number="399"/> + <line branch="false" hits="2" number="400"/> + <line branch="false" hits="0" number="402"/> + <line branch="false" hits="2" number="405"/> + <line branch="false" hits="2" number="406"/> + <line branch="false" hits="2" number="412"/> + <line branch="false" hits="8" number="417"/> + <line branch="false" hits="26" number="428"/> + <line branch="false" hits="26" number="430"/> + <line branch="false" hits="26" number="431"/> + <line branch="false" hits="3972" number="433"/> + <line branch="false" hits="3972" number="439"/> + <line branch="false" hits="3972" number="440"/> + <line branch="false" hits="3972" number="441"/> + <line branch="false" hits="34" number="446"/> + <line branch="false" hits="34" number="448"/> + <line branch="false" hits="3972" number="461"/> + <line branch="false" hits="3972" number="467"/> + <line branch="false" hits="2" number="468"/> + <line branch="false" hits="4" number="469"/> + <line branch="false" hits="2" number="474"/> + <line branch="false" hits="3972" number="477"/> + <line branch="false" hits="9" number="487"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/plugins/SpotifyVideoMediaExtension.ts" line-rate="1.0" name="src.plugins.SpotifyVideoMediaExtension.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="8" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="SpotifyVideoMediaExtension" signature=""> + <lines> + <line branch="false" hits="59" number="12"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="2" number="29"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="4" number="34"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="2" number="38"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="8" number="2"/> + <line branch="false" hits="8" number="3"/> + <line branch="false" hits="8" number="9"/> + <line branch="false" hits="59" number="13"/> + <line branch="false" hits="59" number="14"/> + <line branch="false" hits="59" number="18"/> + <line branch="false" hits="59" number="22"/> + <line branch="false" hits="59" number="23"/> + <line branch="false" hits="8" number="29"/> + <line branch="false" hits="2" number="30"/> + <line branch="false" hits="2" number="31"/> + <line branch="false" hits="8" number="34"/> + <line branch="false" hits="4" number="35"/> + <line branch="false" hits="8" number="38"/> + <line branch="false" hits="2" number="42"/> + <line branch="false" hits="8" number="46"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/plugins/SpotifyVideoUrl.ts" line-rate="1.0" name="src.plugins.SpotifyVideoUrl.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="8" number="7"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="31" number="8"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="8" number="1"/> + <line branch="false" hits="8" number="7"/> + <line branch="false" hits="8" number="8"/> + <line branch="false" hits="31" number="9"/> + <line branch="false" hits="8" number="11"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/plugins/TextParser.js" line-rate="0.3076923076923077" name="src.plugins.TextParser.js"> + <methods> + <method branch-rate="0.0" line-rate="0.0" name="TextParser" signature=""> + <lines> + <line branch="false" hits="0" number="25"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="0" number="37"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="0" number="47"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="0" number="57"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="0" number="64"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="0" number="78"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="96"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="0" number="116"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="0" number="30"/> + <line branch="false" hits="0" number="33"/> + <line branch="false" hits="8" number="37"/> + <line branch="false" hits="0" number="38"/> + <line branch="false" hits="8" number="47"/> + <line branch="false" hits="0" number="48"/> + <line branch="false" hits="8" number="57"/> + <line branch="false" hits="0" number="58"/> + <line branch="false" hits="8" number="64"/> + <line branch="false" hits="0" number="65"/> + <line branch="false" hits="8" number="78"/> + <line branch="false" hits="0" number="79"/> + <line branch="true" condition-coverage="0% (0/3)" hits="0" number="80"/> + <line branch="false" hits="0" number="81"/> + <line branch="false" hits="0" number="84"/> + <line branch="false" hits="0" number="85"/> + <line branch="false" hits="8" number="96"/> + <line branch="false" hits="0" number="98"/> + <line branch="false" hits="0" number="101"/> + <line branch="false" hits="0" number="103"/> + <line branch="false" hits="0" number="105"/> + <line branch="false" hits="8" number="116"/> + <line branch="false" hits="0" number="117"/> + <line branch="false" hits="0" number="118"/> + <line branch="false" hits="0" number="120"/> + <line branch="false" hits="0" number="122"/> + <line branch="false" hits="8" number="130"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/plugins/VttTextParser.js" line-rate="0.13043478260869565" name="src.plugins.VttTextParser.js"> + <methods> + <method branch-rate="0.0" line-rate="0.0" name="VttTextParser" signature=""> + <lines> + <line branch="false" hits="0" number="26"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="0" number="29"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="0" number="37"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="0" number="121"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="0" number="144"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="0" number="223"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="0" number="260"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="0" number="261"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="0" number="285"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="0" number="299"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="0" number="315"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="0" number="330"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="0" number="362"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="8" number="19"/> + <line branch="false" hits="8" number="20"/> + <line branch="false" hits="8" number="29"/> + <line branch="false" hits="0" number="30"/> + <line branch="false" hits="8" number="37"/> + <line branch="false" hits="0" number="38"/> + <line branch="false" hits="0" number="40"/> + <line branch="false" hits="0" number="41"/> + <line branch="false" hits="0" number="42"/> + <line branch="false" hits="0" number="45"/> + <line branch="false" hits="0" number="52"/> + <line branch="false" hits="0" number="60"/> + <line branch="false" hits="0" number="72"/> + <line branch="false" hits="0" number="76"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="77"/> + <line branch="false" hits="0" number="78"/> + <line branch="false" hits="0" number="79"/> + <line branch="false" hits="0" number="80"/> + <line branch="false" hits="0" number="81"/> + <line branch="false" hits="0" number="84"/> + <line branch="false" hits="0" number="91"/> + <line branch="false" hits="0" number="92"/> + <line branch="false" hits="0" number="93"/> + <line branch="false" hits="0" number="95"/> + <line branch="false" hits="0" number="96"/> + <line branch="false" hits="0" number="101"/> + <line branch="false" hits="0" number="102"/> + <line branch="false" hits="0" number="103"/> + <line branch="false" hits="0" number="104"/> + <line branch="false" hits="0" number="106"/> + <line branch="false" hits="0" number="110"/> + <line branch="false" hits="8" number="121"/> + <line branch="false" hits="0" number="122"/> + <line branch="false" hits="0" number="126"/> + <line branch="false" hits="0" number="129"/> + <line branch="false" hits="0" number="130"/> + <line branch="false" hits="0" number="132"/> + <line branch="false" hits="8" number="144"/> + <line branch="false" hits="0" number="145"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="148"/> + <line branch="false" hits="0" number="149"/> + <line branch="false" hits="0" number="154"/> + <line branch="false" hits="0" number="159"/> + <line branch="false" hits="0" number="162"/> + <line branch="false" hits="0" number="163"/> + <line branch="false" hits="0" number="165"/> + <line branch="false" hits="0" number="166"/> + <line branch="false" hits="0" number="170"/> + <line branch="false" hits="0" number="171"/> + <line branch="false" hits="0" number="172"/> + <line branch="false" hits="0" number="173"/> + <line branch="true" condition-coverage="0% (0/3)" hits="0" number="175"/> + <line branch="false" hits="0" number="176"/> + <line branch="false" hits="0" number="183"/> + <line branch="false" hits="0" number="184"/> + <line branch="false" hits="0" number="187"/> + <line branch="false" hits="0" number="192"/> + <line branch="false" hits="0" number="195"/> + <line branch="false" hits="0" number="196"/> + <line branch="false" hits="0" number="199"/> + <line branch="false" hits="0" number="205"/> + <line branch="false" hits="0" number="206"/> + <line branch="false" hits="0" number="210"/> + <line branch="false" hits="0" number="212"/> + <line branch="false" hits="8" number="223"/> + <line branch="false" hits="0" number="224"/> + <line branch="false" hits="0" number="225"/> + <line branch="false" hits="0" number="227"/> + <line branch="false" hits="0" number="229"/> + <line branch="false" hits="0" number="231"/> + <line branch="false" hits="0" number="237"/> + <line branch="false" hits="0" number="239"/> + <line branch="false" hits="0" number="242"/> + <line branch="false" hits="0" number="244"/> + <line branch="false" hits="0" number="247"/> + <line branch="false" hits="0" number="250"/> + <line branch="false" hits="8" number="260"/> + <line branch="false" hits="0" number="261"/> + <line branch="false" hits="0" number="262"/> + <line branch="false" hits="0" number="265"/> + <line branch="false" hits="0" number="270"/> + <line branch="false" hits="0" number="274"/> + <line branch="false" hits="0" number="277"/> + <line branch="false" hits="8" number="285"/> + <line branch="false" hits="0" number="286"/> + <line branch="false" hits="0" number="288"/> + <line branch="false" hits="0" number="290"/> + <line branch="false" hits="8" number="299"/> + <line branch="false" hits="0" number="300"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="301"/> + <line branch="false" hits="0" number="302"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="303"/> + <line branch="false" hits="0" number="304"/> + <line branch="false" hits="0" number="306"/> + <line branch="false" hits="8" number="315"/> + <line branch="false" hits="0" number="316"/> + <line branch="false" hits="0" number="318"/> + <line branch="false" hits="0" number="320"/> + <line branch="false" hits="8" number="330"/> + <line branch="false" hits="0" number="334"/> + <line branch="false" hits="0" number="335"/> + <line branch="false" hits="0" number="337"/> + <line branch="false" hits="0" number="338"/> + <line branch="false" hits="0" number="340"/> + <line branch="false" hits="0" number="343"/> + <line branch="false" hits="0" number="344"/> + <line branch="false" hits="0" number="346"/> + <line branch="false" hits="0" number="349"/> + <line branch="false" hits="0" number="352"/> + <line branch="false" hits="8" number="362"/> + <line branch="false" hits="0" number="364"/> + <line branch="false" hits="0" number="366"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="370"/> + <line branch="false" hits="0" number="371"/> + <line branch="false" hits="0" number="372"/> + <line branch="false" hits="0" number="373"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="374"/> + <line branch="false" hits="0" number="375"/> + <line branch="false" hits="0" number="378"/> + <line branch="false" hits="8" number="385"/> + <line branch="false" hits="8" number="387"/> + </lines> + </class> + <class branch-rate="0.47619047619047616" complexity="0" filename="src/plugins/WidevineDownloader.ts" line-rate="0.8356164383561644" name="src.plugins.WidevineDownloader.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="7" number="14"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="WidevineDownloader" signature=""> + <lines> + <line branch="false" hits="7" number="21"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="6" number="190"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="4" number="34"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="4" number="40"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="1" number="44"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="1" number="66"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="0" number="69"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="2" number="78"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="1" number="90"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="4" number="107"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="1" number="137"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="0" number="147"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="7" number="165"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="1" number="174"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="7" number="2"/> + <line branch="false" hits="7" number="9"/> + <line branch="false" hits="7" number="10"/> + <line branch="false" hits="7" number="11"/> + <line branch="false" hits="7" number="12"/> + <line branch="false" hits="7" number="14"/> + <line branch="false" hits="7" number="21"/> + <line branch="false" hits="7" number="22"/> + <line branch="false" hits="7" number="26"/> + <line branch="false" hits="7" number="27"/> + <line branch="false" hits="7" number="28"/> + <line branch="false" hits="7" number="29"/> + <line branch="false" hits="7" number="34"/> + <line branch="false" hits="0" number="36"/> + <line branch="false" hits="4" number="38"/> + <line branch="false" hits="4" number="41"/> + <line branch="false" hits="4" number="44"/> + <line branch="false" hits="0" number="46"/> + <line branch="false" hits="1" number="49"/> + <line branch="false" hits="0" number="51"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="59"/> + <line branch="false" hits="0" number="63"/> + <line branch="false" hits="0" number="64"/> + <line branch="false" hits="3" number="66"/> + <line branch="false" hits="0" number="70"/> + <line branch="false" hits="7" number="78"/> + <line branch="true" condition-coverage="40% (2/5)" hits="0" number="80"/> + <line branch="false" hits="1" number="84"/> + <line branch="false" hits="1" number="86"/> + <line branch="false" hits="7" number="90"/> + <line branch="false" hits="1" number="91"/> + <line branch="false" hits="1" number="92"/> + <line branch="false" hits="1" number="93"/> + <line branch="false" hits="1" number="94"/> + <line branch="false" hits="7" number="107"/> + <line branch="false" hits="4" number="108"/> + <line branch="true" condition-coverage="40% (4/10)" hits="0" number="111"/> + <line branch="false" hits="2" number="112"/> + <line branch="false" hits="2" number="113"/> + <line branch="false" hits="1" number="120"/> + <line branch="false" hits="1" number="121"/> + <line branch="false" hits="1" number="128"/> + <line branch="false" hits="1" number="129"/> + <line branch="false" hits="0" number="133"/> + <line branch="false" hits="1" number="136"/> + <line branch="false" hits="1" number="137"/> + <line branch="false" hits="1" number="139"/> + <line branch="false" hits="1" number="140"/> + <line branch="false" hits="1" number="147"/> + <line branch="false" hits="0" number="150"/> + <line branch="false" hits="0" number="152"/> + <line branch="false" hits="0" number="153"/> + <line branch="false" hits="7" number="165"/> + <line branch="false" hits="7" number="166"/> + <line branch="false" hits="0" number="171"/> + <line branch="false" hits="0" number="172"/> + <line branch="false" hits="7" number="174"/> + <line branch="false" hits="7" number="177"/> + <line branch="true" condition-coverage="50% (1/2)" hits="6" number="179"/> + <line branch="false" hits="3" number="181"/> + <line branch="false" hits="3" number="182"/> + <line branch="false" hits="3" number="183"/> + <line branch="true" condition-coverage="50% (1/2)" hits="3" number="184"/> + <line branch="false" hits="3" number="185"/> + <line branch="false" hits="3" number="187"/> + <line branch="false" hits="3" number="189"/> + <line branch="false" hits="6" number="190"/> + <line branch="false" hits="6" number="191"/> + <line branch="false" hits="3" number="193"/> + <line branch="false" hits="7" number="198"/> + <line branch="false" hits="3" number="200"/> + <line branch="false" hits="1" number="201"/> + <line branch="false" hits="1" number="202"/> + <line branch="false" hits="1" number="203"/> + <line branch="false" hits="1" number="205"/> + <line branch="false" hits="7" number="207"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/plugins/index.ts" line-rate="1.0" name="src.plugins.index.ts"> + <methods/> + <lines> + <line branch="false" hits="8" number="1"/> + <line branch="false" hits="8" number="2"/> + <line branch="false" hits="8" number="3"/> + <line branch="false" hits="8" number="4"/> + <line branch="false" hits="8" number="6"/> + <line branch="false" hits="8" number="7"/> + <line branch="false" hits="8" number="8"/> + </lines> + </class> + <class branch-rate="1.0" complexity="0" filename="src/plugins/types.ts" line-rate="1.0" name="src.plugins.types.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="7" number="19"/> + </lines> + </method> + </methods> + <lines> + <line branch="true" condition-coverage="100% (2/2)" hits="7" number="19"/> + <line branch="false" hits="7" number="20"/> + <line branch="false" hits="7" number="21"/> + <line branch="false" hits="7" number="22"/> + <line branch="false" hits="7" number="23"/> + <line branch="false" hits="7" number="24"/> + <line branch="false" hits="7" number="25"/> + <line branch="false" hits="7" number="26"/> + <line branch="false" hits="7" number="27"/> + <line branch="false" hits="7" number="28"/> + <line branch="false" hits="7" number="29"/> + <line branch="false" hits="7" number="30"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.9701492537313433" complexity="0" line-rate="0.9808612440191388" name="src.tracking"> + <classes> + <class branch-rate="0.9743589743589743" complexity="0" filename="src/tracking/DefaultEventsCalculator.ts" line-rate="0.9754098360655737" name="src.tracking.DefaultEventsCalculator.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="getEventPosition" signature=""> + <lines> + <line branch="false" hits="54" number="34"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="registerBufferingEnd" signature=""> + <lines> + <line branch="false" hits="7" number="46"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="52" number="95"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="1" number="108"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="1" number="116"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="76" number="124"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="76" number="145"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processIdentityFields" signature=""> + <lines> + <line branch="false" hits="25" number="164"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="24" number="168"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processMsStartPosition" signature=""> + <lines> + <line branch="false" hits="25" number="181"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="3" number="185"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processMsDuration" signature=""> + <lines> + <line branch="false" hits="25" number="194"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="1" number="198"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processStartTime" signature=""> + <lines> + <line branch="false" hits="26" number="207"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="4" number="215"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processDroppedFrames" signature=""> + <lines> + <line branch="false" hits="25" number="229"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="1" number="233"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processEndFields" signature=""> + <lines> + <line branch="false" hits="26" number="242"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="25" number="246"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processVideoFormatChangedFields" signature=""> + <lines> + <line branch="false" hits="28" number="255"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="6" number="259"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processMsEncryptionLoadTime" signature=""> + <lines> + <line branch="false" hits="26" number="276"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="2" number="284"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processEncryptionType" signature=""> + <lines> + <line branch="false" hits="25" number="298"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="1" number="302"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processLasUsedSubtitle" signature=""> + <lines> + <line branch="false" hits="26" number="311"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="5" number="315"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processManifestLoadTime" signature=""> + <lines> + <line branch="false" hits="26" number="326"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="2" number="334"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processSeekFields" signature=""> + <lines> + <line branch="false" hits="27" number="348"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="11" number="352"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processBandwidthFields" signature=""> + <lines> + <line branch="false" hits="26" number="386"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_35)" signature=""> + <lines> + <line branch="false" hits="5" number="398"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processBufferingFields" signature=""> + <lines> + <line branch="false" hits="29" number="417"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processMsPlayed" signature=""> + <lines> + <line branch="false" hits="27" number="475"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_38)" signature=""> + <lines> + <line branch="false" hits="83" number="479"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_39)" signature=""> + <lines> + <line branch="false" hits="43" number="483"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processMsSubtitlesPlayed" signature=""> + <lines> + <line branch="false" hits="25" number="496"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_41)" signature=""> + <lines> + <line branch="false" hits="76" number="500"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_42)" signature=""> + <lines> + <line branch="false" hits="43" number="505"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processMsFullscreenPlayed" signature=""> + <lines> + <line branch="false" hits="25" number="522"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_44)" signature=""> + <lines> + <line branch="false" hits="76" number="526"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_45)" signature=""> + <lines> + <line branch="false" hits="43" number="531"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="generatePlaybackSessionMessage" signature=""> + <lines> + <line branch="false" hits="23" number="548"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="16" number="1"/> + <line branch="false" hits="16" number="11"/> + <line branch="false" hits="16" number="12"/> + <line branch="false" hits="16" number="13"/> + <line branch="false" hits="54" number="34"/> + <line branch="false" hits="35" number="37"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="39"/> + <line branch="false" hits="19" number="40"/> + <line branch="false" hits="0" number="43"/> + <line branch="false" hits="7" number="51"/> + <line branch="false" hits="7" number="52"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="55"/> + <line branch="true" condition-coverage="75% (3/4)" hits="0" number="57"/> + <line branch="false" hits="3" number="58"/> + <line branch="false" hits="3" number="65"/> + <line branch="false" hits="3" number="69"/> + <line branch="false" hits="3" number="71"/> + <line branch="false" hits="2" number="78"/> + <line branch="false" hits="3" number="82"/> + <line branch="false" hits="1" number="84"/> + <line branch="false" hits="1" number="87"/> + <line branch="false" hits="0" number="89"/> + <line branch="false" hits="7" number="92"/> + <line branch="false" hits="16" number="95"/> + <line branch="false" hits="52" number="99"/> + <line branch="false" hits="52" number="100"/> + <line branch="false" hits="16" number="108"/> + <line branch="false" hits="1" number="109"/> + <line branch="false" hits="1" number="111"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="113"/> + <line branch="false" hits="16" number="116"/> + <line branch="false" hits="1" number="117"/> + <line branch="false" hits="1" number="119"/> + <line branch="false" hits="16" number="124"/> + <line branch="false" hits="76" number="128"/> + <line branch="true" condition-coverage="100% (2/2)" hits="76" number="129"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="130"/> + <line branch="false" hits="1" number="132"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="134"/> + <line branch="false" hits="1" number="136"/> + <line branch="false" hits="1" number="140"/> + <line branch="false" hits="76" number="142"/> + <line branch="false" hits="16" number="145"/> + <line branch="false" hits="76" number="149"/> + <line branch="true" condition-coverage="100% (2/2)" hits="76" number="150"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="151"/> + <line branch="false" hits="1" number="152"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="154"/> + <line branch="false" hits="1" number="155"/> + <line branch="false" hits="1" number="159"/> + <line branch="false" hits="76" number="161"/> + <line branch="false" hits="16" number="164"/> + <line branch="false" hits="25" number="167"/> + <line branch="false" hits="24" number="168"/> + <line branch="false" hits="16" number="181"/> + <line branch="false" hits="25" number="184"/> + <line branch="false" hits="3" number="185"/> + <line branch="false" hits="16" number="194"/> + <line branch="false" hits="25" number="197"/> + <line branch="false" hits="1" number="198"/> + <line branch="false" hits="16" number="207"/> + <line branch="false" hits="26" number="210"/> + <line branch="false" hits="26" number="214"/> + <line branch="false" hits="4" number="216"/> + <line branch="true" condition-coverage="100% (1/1)" hits="0" number="222"/> + <line branch="false" hits="16" number="229"/> + <line branch="false" hits="25" number="232"/> + <line branch="false" hits="1" number="233"/> + <line branch="false" hits="16" number="242"/> + <line branch="false" hits="26" number="245"/> + <line branch="false" hits="25" number="246"/> + <line branch="false" hits="16" number="255"/> + <line branch="false" hits="28" number="258"/> + <line branch="false" hits="6" number="259"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="261"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="262"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="265"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="266"/> + <line branch="false" hits="16" number="276"/> + <line branch="false" hits="26" number="279"/> + <line branch="false" hits="26" number="283"/> + <line branch="false" hits="2" number="285"/> + <line branch="true" condition-coverage="100% (1/1)" hits="0" number="291"/> + <line branch="false" hits="16" number="298"/> + <line branch="false" hits="25" number="301"/> + <line branch="false" hits="1" number="302"/> + <line branch="false" hits="16" number="311"/> + <line branch="false" hits="26" number="314"/> + <line branch="false" hits="5" number="315"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="317"/> + <line branch="false" hits="16" number="326"/> + <line branch="false" hits="26" number="329"/> + <line branch="false" hits="26" number="333"/> + <line branch="false" hits="2" number="335"/> + <line branch="true" condition-coverage="100% (1/1)" hits="0" number="341"/> + <line branch="false" hits="16" number="348"/> + <line branch="false" hits="27" number="351"/> + <line branch="false" hits="11" number="352"/> + <line branch="false" hits="5" number="354"/> + <line branch="false" hits="6" number="365"/> + <line branch="false" hits="0" number="375"/> + <line branch="false" hits="16" number="386"/> + <line branch="false" hits="26" number="389"/> + <line branch="false" hits="26" number="390"/> + <line branch="false" hits="26" number="397"/> + <line branch="false" hits="5" number="398"/> + <line branch="false" hits="5" number="399"/> + <line branch="false" hits="5" number="400"/> + <line branch="false" hits="16" number="417"/> + <line branch="false" hits="86" number="433"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="435"/> + <line branch="false" hits="5" number="439"/> + <line branch="false" hits="3" number="444"/> + <line branch="false" hits="9" number="450"/> + <line branch="false" hits="9" number="451"/> + <line branch="false" hits="9" number="454"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="457"/> + <line branch="false" hits="4" number="461"/> + <line branch="false" hits="4" number="466"/> + <line branch="false" hits="4" number="467"/> + <line branch="false" hits="4" number="468"/> + <line branch="false" hits="29" number="472"/> + <line branch="false" hits="16" number="475"/> + <line branch="false" hits="27" number="478"/> + <line branch="false" hits="83" number="480"/> + <line branch="false" hits="43" number="483"/> + <line branch="false" hits="16" number="496"/> + <line branch="false" hits="25" number="499"/> + <line branch="false" hits="76" number="501"/> + <line branch="false" hits="43" number="505"/> + <line branch="false" hits="76" number="507"/> + <line branch="false" hits="76" number="508"/> + <line branch="false" hits="16" number="522"/> + <line branch="false" hits="25" number="525"/> + <line branch="false" hits="76" number="527"/> + <line branch="false" hits="43" number="531"/> + <line branch="false" hits="76" number="533"/> + <line branch="false" hits="76" number="534"/> + <line branch="false" hits="16" number="548"/> + <line branch="false" hits="23" number="551"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/tracking/EventsTracker.ts" line-rate="0.9583333333333334" name="src.tracking.EventsTracker.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="16" number="16"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="EventsTracker" signature=""> + <lines> + <line branch="false" hits="15" number="19"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="1" number="23"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="1" number="40"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="1" number="53"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="1" number="63"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="1" number="71"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="0" number="86"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="12" number="101"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="0" number="117"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="5" number="130"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="3" number="145"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="9" number="160"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="3" number="170"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="5" number="180"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="1" number="195"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="1" number="210"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="1" number="225"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="1" number="240"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="1" number="248"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="1" number="256"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="1" number="271"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="1" number="286"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="1" number="301"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="16" number="14"/> + <line branch="false" hits="16" number="16"/> + <line branch="false" hits="15" number="20"/> + <line branch="false" hits="16" number="23"/> + <line branch="false" hits="1" number="29"/> + <line branch="false" hits="16" number="40"/> + <line branch="false" hits="1" number="44"/> + <line branch="false" hits="16" number="53"/> + <line branch="false" hits="1" number="54"/> + <line branch="false" hits="16" number="63"/> + <line branch="false" hits="1" number="64"/> + <line branch="false" hits="16" number="71"/> + <line branch="false" hits="1" number="76"/> + <line branch="false" hits="16" number="86"/> + <line branch="false" hits="0" number="91"/> + <line branch="false" hits="16" number="101"/> + <line branch="false" hits="12" number="107"/> + <line branch="false" hits="16" number="117"/> + <line branch="false" hits="0" number="121"/> + <line branch="false" hits="16" number="130"/> + <line branch="false" hits="5" number="135"/> + <line branch="false" hits="16" number="145"/> + <line branch="false" hits="3" number="150"/> + <line branch="false" hits="16" number="160"/> + <line branch="false" hits="9" number="161"/> + <line branch="false" hits="16" number="170"/> + <line branch="false" hits="3" number="171"/> + <line branch="false" hits="16" number="180"/> + <line branch="false" hits="5" number="185"/> + <line branch="false" hits="16" number="195"/> + <line branch="false" hits="1" number="200"/> + <line branch="false" hits="16" number="210"/> + <line branch="false" hits="1" number="215"/> + <line branch="false" hits="16" number="225"/> + <line branch="false" hits="1" number="230"/> + <line branch="false" hits="16" number="240"/> + <line branch="false" hits="1" number="241"/> + <line branch="false" hits="16" number="248"/> + <line branch="false" hits="1" number="249"/> + <line branch="false" hits="16" number="256"/> + <line branch="false" hits="1" number="261"/> + <line branch="false" hits="16" number="271"/> + <line branch="false" hits="1" number="276"/> + <line branch="false" hits="16" number="286"/> + <line branch="false" hits="1" number="291"/> + <line branch="false" hits="16" number="301"/> + <line branch="false" hits="1" number="302"/> + <line branch="false" hits="16" number="310"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/tracking/ProductStatesStreamingRulesProvider.ts" line-rate="1.0" name="src.tracking.ProductStatesStreamingRulesProvider.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="16" number="4"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="ProductStatesStreamingRulesProvider" signature=""> + <lines> + <line branch="false" hits="3" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="2" number="14"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="0" number="17"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="4" number="21"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="16" number="4"/> + <line branch="false" hits="3" number="9"/> + <line branch="false" hits="3" number="10"/> + <line branch="false" hits="3" number="11"/> + <line branch="false" hits="3" number="12"/> + <line branch="false" hits="2" number="15"/> + <line branch="false" hits="16" number="21"/> + <line branch="false" hits="4" number="22"/> + <line branch="false" hits="16" number="24"/> + </lines> + </class> + <class branch-rate="1.0" complexity="0" filename="src/tracking/VideoPlaybackEvents.ts" line-rate="1.0" name="src.tracking.VideoPlaybackEvents.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="18" number="1"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="18" number="7"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="18" number="17"/> + </lines> + </method> + </methods> + <lines> + <line branch="true" condition-coverage="100% (2/2)" hits="18" number="1"/> + <line branch="false" hits="18" number="2"/> + <line branch="false" hits="18" number="3"/> + <line branch="false" hits="18" number="4"/> + <line branch="true" condition-coverage="100% (2/2)" hits="18" number="7"/> + <line branch="false" hits="18" number="8"/> + <line branch="false" hits="18" number="9"/> + <line branch="false" hits="18" number="10"/> + <line branch="false" hits="18" number="13"/> + <line branch="true" condition-coverage="100% (2/2)" hits="18" number="17"/> + <line branch="false" hits="18" number="18"/> + <line branch="false" hits="18" number="19"/> + <line branch="false" hits="18" number="20"/> + <line branch="false" hits="18" number="21"/> + <line branch="false" hits="18" number="22"/> + <line branch="false" hits="18" number="23"/> + <line branch="false" hits="18" number="24"/> + <line branch="false" hits="18" number="25"/> + <line branch="false" hits="18" number="26"/> + <line branch="false" hits="18" number="27"/> + <line branch="false" hits="18" number="28"/> + <line branch="false" hits="18" number="29"/> + <line branch="false" hits="18" number="30"/> + <line branch="false" hits="18" number="31"/> + <line branch="false" hits="18" number="32"/> + <line branch="false" hits="18" number="33"/> + <line branch="false" hits="18" number="34"/> + <line branch="false" hits="18" number="35"/> + <line branch="false" hits="18" number="36"/> + <line branch="false" hits="18" number="37"/> + <line branch="false" hits="18" number="38"/> + <line branch="false" hits="18" number="39"/> + <line branch="false" hits="18" number="40"/> + <line branch="false" hits="18" number="41"/> + <line branch="false" hits="18" number="42"/> + <line branch="false" hits="18" number="45"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/tracking/index.ts" line-rate="1.0" name="src.tracking.index.ts"> + <methods/> + <lines> + <line branch="false" hits="15" number="1"/> + <line branch="false" hits="15" number="2"/> + <line branch="false" hits="15" number="3"/> + <line branch="false" hits="15" number="4"/> + <line branch="false" hits="15" number="5"/> + <line branch="false" hits="15" number="7"/> + <line branch="false" hits="15" number="8"/> + <line branch="false" hits="15" number="9"/> + <line branch="false" hits="15" number="11"/> + <line branch="false" hits="15" number="12"/> + <line branch="false" hits="15" number="13"/> + <line branch="false" hits="15" number="15"/> + <line branch="false" hits="15" number="16"/> + </lines> + </class> + <class branch-rate="1.0" complexity="0" filename="src/tracking/types.ts" line-rate="1.0" name="src.tracking.types.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="16" number="13"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_2)" signature=""> + <lines> + <line branch="false" hits="16" number="95"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="16" number="10"/> + <line branch="true" condition-coverage="100% (2/2)" hits="16" number="13"/> + <line branch="false" hits="16" number="14"/> + <line branch="false" hits="16" number="15"/> + <line branch="false" hits="16" number="16"/> + <line branch="false" hits="16" number="17"/> + <line branch="false" hits="16" number="18"/> + <line branch="false" hits="16" number="19"/> + <line branch="false" hits="16" number="20"/> + <line branch="false" hits="16" number="21"/> + <line branch="false" hits="16" number="22"/> + <line branch="false" hits="16" number="23"/> + <line branch="false" hits="16" number="24"/> + <line branch="false" hits="16" number="25"/> + <line branch="false" hits="16" number="26"/> + <line branch="false" hits="16" number="27"/> + <line branch="false" hits="16" number="28"/> + <line branch="false" hits="16" number="29"/> + <line branch="false" hits="16" number="30"/> + <line branch="false" hits="16" number="31"/> + <line branch="false" hits="16" number="32"/> + <line branch="false" hits="16" number="33"/> + <line branch="false" hits="16" number="34"/> + <line branch="false" hits="16" number="35"/> + <line branch="false" hits="16" number="36"/> + <line branch="false" hits="16" number="37"/> + <line branch="false" hits="16" number="38"/> + <line branch="false" hits="16" number="39"/> + <line branch="false" hits="16" number="40"/> + <line branch="false" hits="16" number="41"/> + <line branch="false" hits="16" number="42"/> + <line branch="false" hits="16" number="43"/> + <line branch="false" hits="16" number="44"/> + <line branch="false" hits="16" number="45"/> + <line branch="false" hits="16" number="46"/> + <line branch="true" condition-coverage="100% (2/2)" hits="16" number="95"/> + <line branch="false" hits="16" number="96"/> + <line branch="false" hits="16" number="97"/> + <line branch="false" hits="16" number="98"/> + <line branch="false" hits="16" number="99"/> + <line branch="false" hits="16" number="100"/> + <line branch="false" hits="16" number="101"/> + <line branch="false" hits="16" number="102"/> + <line branch="false" hits="16" number="103"/> + <line branch="false" hits="16" number="104"/> + <line branch="false" hits="16" number="105"/> + <line branch="false" hits="16" number="106"/> + <line branch="false" hits="16" number="107"/> + <line branch="false" hits="16" number="108"/> + <line branch="false" hits="16" number="109"/> + <line branch="false" hits="16" number="110"/> + <line branch="false" hits="16" number="111"/> + <line branch="false" hits="16" number="112"/> + <line branch="false" hits="16" number="113"/> + <line branch="false" hits="16" number="114"/> + <line branch="false" hits="16" number="115"/> + <line branch="false" hits="16" number="116"/> + <line branch="false" hits="16" number="117"/> + <line branch="false" hits="16" number="118"/> + <line branch="false" hits="16" number="119"/> + <line branch="false" hits="16" number="120"/> + <line branch="false" hits="16" number="121"/> + <line branch="false" hits="16" number="122"/> + <line branch="false" hits="16" number="123"/> + <line branch="false" hits="16" number="124"/> + <line branch="false" hits="16" number="125"/> + <line branch="false" hits="16" number="126"/> + <line branch="false" hits="16" number="127"/> + <line branch="false" hits="16" number="128"/> + <line branch="false" hits="16" number="129"/> + <line branch="false" hits="16" number="130"/> + <line branch="false" hits="16" number="131"/> + <line branch="false" hits="16" number="132"/> + <line branch="false" hits="16" number="133"/> + <line branch="false" hits="16" number="134"/> + <line branch="false" hits="16" number="135"/> + <line branch="false" hits="16" number="136"/> + <line branch="false" hits="16" number="137"/> + <line branch="false" hits="16" number="138"/> + <line branch="false" hits="16" number="139"/> + <line branch="false" hits="16" number="140"/> + <line branch="false" hits="16" number="141"/> + <line branch="false" hits="16" number="142"/> + <line branch="false" hits="16" number="143"/> + <line branch="false" hits="16" number="144"/> + <line branch="false" hits="16" number="145"/> + <line branch="false" hits="16" number="146"/> + <line branch="false" hits="16" number="147"/> + <line branch="false" hits="16" number="148"/> + </lines> + </class> + <class branch-rate="0.9444444444444444" complexity="0" filename="src/tracking/utils.ts" line-rate="0.9702970297029703" name="src.tracking.utils.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="createPlaybackMetadata" signature=""> + <lines> + <line branch="false" hits="47" number="44"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="retrieveEndvideoMetadata" signature=""> + <lines> + <line branch="false" hits="208" number="109"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="972" number="113"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="951" number="115"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="497" number="123"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="469" number="128"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="74" number="133"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="78" number="138"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="222" number="143"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="297" number="148"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="150" number="153"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="74" number="158"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="74" number="163"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="244" number="168"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="150" number="173"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="0" number="178"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="122" number="183"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="76" number="188"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="458" number="193"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="44" number="198"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="78" number="203"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="2" number="208"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="502" number="220"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="497" number="220"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="176" number="224"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="132" number="224"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="176" number="228"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="110" number="228"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="326" number="232"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="248" number="232"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="96" number="236"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="getLastTimestamp" signature=""> + <lines> + <line branch="false" hits="79" number="245"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_35)" signature=""> + <lines> + <line branch="false" hits="230" number="250"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_36)" signature=""> + <lines> + <line branch="false" hits="28" number="251"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="getFirstTimestamp" signature=""> + <lines> + <line branch="false" hits="29" number="254"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_38)" signature=""> + <lines> + <line branch="false" hits="79" number="259"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_39)" signature=""> + <lines> + <line branch="false" hits="19" number="261"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="computeRange" signature=""> + <lines> + <line branch="false" hits="61" number="269"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="17" number="2"/> + <line branch="false" hits="17" number="4"/> + <line branch="false" hits="17" number="7"/> + <line branch="false" hits="17" number="9"/> + <line branch="false" hits="17" number="11"/> + <line branch="false" hits="17" number="12"/> + <line branch="false" hits="17" number="13"/> + <line branch="false" hits="17" number="14"/> + <line branch="false" hits="17" number="15"/> + <line branch="false" hits="17" number="16"/> + <line branch="false" hits="17" number="17"/> + <line branch="false" hits="17" number="18"/> + <line branch="false" hits="17" number="19"/> + <line branch="false" hits="17" number="20"/> + <line branch="false" hits="17" number="21"/> + <line branch="false" hits="17" number="22"/> + <line branch="false" hits="17" number="23"/> + <line branch="false" hits="17" number="24"/> + <line branch="false" hits="17" number="26"/> + <line branch="false" hits="17" number="42"/> + <line branch="false" hits="17" number="44"/> + <line branch="false" hits="47" number="47"/> + <line branch="false" hits="47" number="48"/> + <line branch="false" hits="47" number="53"/> + <line branch="false" hits="47" number="58"/> + <line branch="false" hits="47" number="63"/> + <line branch="false" hits="47" number="64"/> + <line branch="false" hits="47" number="69"/> + <line branch="false" hits="47" number="74"/> + <line branch="false" hits="47" number="75"/> + <line branch="false" hits="47" number="76"/> + <line branch="false" hits="47" number="77"/> + <line branch="false" hits="47" number="78"/> + <line branch="false" hits="17" number="100"/> + <line branch="false" hits="17" number="102"/> + <line branch="false" hits="17" number="104"/> + <line branch="false" hits="17" number="109"/> + <line branch="false" hits="208" number="112"/> + <line branch="false" hits="972" number="113"/> + <line branch="false" hits="951" number="115"/> + <line branch="false" hits="17" number="123"/> + <line branch="false" hits="497" number="126"/> + <line branch="false" hits="17" number="128"/> + <line branch="false" hits="469" number="131"/> + <line branch="false" hits="17" number="133"/> + <line branch="false" hits="74" number="136"/> + <line branch="false" hits="17" number="138"/> + <line branch="false" hits="78" number="141"/> + <line branch="false" hits="17" number="143"/> + <line branch="false" hits="222" number="146"/> + <line branch="false" hits="17" number="148"/> + <line branch="false" hits="297" number="151"/> + <line branch="false" hits="17" number="153"/> + <line branch="false" hits="150" number="156"/> + <line branch="false" hits="17" number="158"/> + <line branch="false" hits="74" number="161"/> + <line branch="false" hits="17" number="163"/> + <line branch="false" hits="74" number="166"/> + <line branch="false" hits="17" number="168"/> + <line branch="false" hits="244" number="171"/> + <line branch="false" hits="17" number="173"/> + <line branch="false" hits="150" number="176"/> + <line branch="false" hits="17" number="178"/> + <line branch="false" hits="0" number="181"/> + <line branch="false" hits="17" number="183"/> + <line branch="false" hits="122" number="186"/> + <line branch="false" hits="17" number="188"/> + <line branch="false" hits="76" number="191"/> + <line branch="false" hits="17" number="193"/> + <line branch="false" hits="458" number="196"/> + <line branch="false" hits="17" number="198"/> + <line branch="false" hits="44" number="201"/> + <line branch="false" hits="17" number="203"/> + <line branch="false" hits="78" number="206"/> + <line branch="false" hits="17" number="208"/> + <line branch="true" condition-coverage="50% (1/2)" hits="2" number="209"/> + <line branch="false" hits="17" number="211"/> + <line branch="false" hits="502" number="220"/> + <line branch="true" condition-coverage="100% (2/2)" hits="497" number="222"/> + <line branch="false" hits="176" number="224"/> + <line branch="true" condition-coverage="100% (2/2)" hits="132" number="226"/> + <line branch="false" hits="176" number="228"/> + <line branch="true" condition-coverage="100% (2/2)" hits="110" number="230"/> + <line branch="false" hits="326" number="232"/> + <line branch="true" condition-coverage="100% (4/4)" hits="248" number="234"/> + <line branch="false" hits="17" number="236"/> + <line branch="false" hits="96" number="237"/> + <line branch="false" hits="96" number="239"/> + <line branch="false" hits="17" number="245"/> + <line branch="false" hits="79" number="249"/> + <line branch="false" hits="230" number="250"/> + <line branch="false" hits="28" number="251"/> + <line branch="false" hits="17" number="254"/> + <line branch="false" hits="29" number="258"/> + <line branch="false" hits="79" number="259"/> + <line branch="false" hits="19" number="262"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="263"/> + <line branch="false" hits="17" number="269"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="270"/> + <line branch="false" hits="0" number="271"/> + <line branch="false" hits="61" number="273"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="274"/> + <line branch="false" hits="0" number="275"/> + <line branch="false" hits="61" number="277"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.8783783783783784" complexity="0" line-rate="0.9074074074074074" name="src.tracking.endvideo"> + <classes> + <class branch-rate="0.8333333333333334" complexity="0" filename="src/tracking/endvideo/EndVideoEventsCalculator.ts" line-rate="0.9304347826086956" name="src.tracking.endvideo.EndVideoEventsCalculator.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="convertReasonEnd" signature=""> + <lines> + <line branch="false" hits="24" number="39"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="sortRange" signature=""> + <lines> + <line branch="false" hits="11" number="52"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="calculateTimeWeightedBitrate" signature=""> + <lines> + <line branch="false" hits="6" number="71"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="7" number="79"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="calculateUnionPlayed" signature=""> + <lines> + <line branch="false" hits="11" number="88"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="19" number="92"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="14" number="120"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="21" number="123"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="5" number="145"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="21" number="181"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="12" number="190"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="10" number="206"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="11" number="223"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="11" number="240"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processEndVideoMetadata" signature=""> + <lines> + <line branch="false" hits="27" number="258"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="24" number="264"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processAudioCodec" signature=""> + <lines> + <line branch="false" hits="27" number="272"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="1" number="276"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processVideoCodec" signature=""> + <lines> + <line branch="false" hits="27" number="285"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="1" number="289"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processUiLatency" signature=""> + <lines> + <line branch="false" hits="28" number="298"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="25" number="306"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processLocalTime" signature=""> + <lines> + <line branch="false" hits="25" number="328"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_27)" signature=""> + <lines> + <line branch="false" hits="23" number="332"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processNewSessionLoaded" signature=""> + <lines> + <line branch="false" hits="30" number="341"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_29)" signature=""> + <lines> + <line branch="false" hits="2" number="345"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processReasonEnd" signature=""> + <lines> + <line branch="false" hits="28" number="356"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="25" number="361"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processUnionPlayed" signature=""> + <lines> + <line branch="false" hits="28" number="371"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="89" number="375"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_34)" signature=""> + <lines> + <line branch="false" hits="43" number="380"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processMaxContinousPlayed" signature=""> + <lines> + <line branch="false" hits="28" number="394"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_36)" signature=""> + <lines> + <line branch="false" hits="87" number="398"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_37)" signature=""> + <lines> + <line branch="false" hits="45" number="403"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="processTimeWeightedBitrate" signature=""> + <lines> + <line branch="false" hits="31" number="416"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_39)" signature=""> + <lines> + <line branch="false" hits="91" number="420"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_40)" signature=""> + <lines> + <line branch="false" hits="44" number="425"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="generateEndVideoMessage" signature=""> + <lines> + <line branch="false" hits="25" number="442"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="15" number="1"/> + <line branch="false" hits="15" number="8"/> + <line branch="false" hits="15" number="9"/> + <line branch="false" hits="15" number="28"/> + <line branch="false" hits="15" number="36"/> + <line branch="false" hits="15" number="37"/> + <line branch="true" condition-coverage="50% (2/4)" hits="0" number="41"/> + <line branch="false" hits="5" number="42"/> + <line branch="false" hits="0" number="44"/> + <line branch="false" hits="0" number="46"/> + <line branch="false" hits="19" number="48"/> + <line branch="false" hits="8" number="57"/> + <line branch="false" hits="0" number="61"/> + <line branch="false" hits="0" number="64"/> + <line branch="false" hits="0" number="66"/> + <line branch="false" hits="3" number="68"/> + <line branch="false" hits="1" number="76"/> + <line branch="false" hits="5" number="78"/> + <line branch="false" hits="7" number="79"/> + <line branch="false" hits="7" number="81"/> + <line branch="false" hits="7" number="82"/> + <line branch="false" hits="11" number="89"/> + <line branch="false" hits="11" number="94"/> + <line branch="false" hits="11" number="95"/> + <line branch="false" hits="8" number="97"/> + <line branch="false" hits="0" number="99"/> + <line branch="false" hits="0" number="103"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="105"/> + <line branch="false" hits="1" number="106"/> + <line branch="false" hits="1" number="110"/> + <line branch="false" hits="3" number="113"/> + <line branch="false" hits="3" number="114"/> + <line branch="false" hits="4" number="116"/> + <line branch="false" hits="14" number="120"/> + <line branch="false" hits="15" number="123"/> + <line branch="false" hits="21" number="127"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="128"/> + <line branch="false" hits="5" number="129"/> + <line branch="false" hits="5" number="133"/> + <line branch="false" hits="5" number="134"/> + <line branch="false" hits="5" number="135"/> + <line branch="false" hits="21" number="140"/> + <line branch="false" hits="21" number="141"/> + <line branch="false" hits="21" number="142"/> + <line branch="false" hits="15" number="145"/> + <line branch="false" hits="5" number="149"/> + <line branch="false" hits="5" number="151"/> + <line branch="false" hits="5" number="153"/> + <line branch="false" hits="5" number="157"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="159"/> + <line branch="false" hits="4" number="160"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="161"/> + <line branch="false" hits="1" number="162"/> + <line branch="false" hits="1" number="166"/> + <line branch="false" hits="1" number="167"/> + <line branch="false" hits="1" number="168"/> + <line branch="false" hits="1" number="169"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="174"/> + <line branch="false" hits="0" number="175"/> + <line branch="false" hits="5" number="177"/> + <line branch="false" hits="5" number="178"/> + <line branch="false" hits="15" number="181"/> + <line branch="false" hits="21" number="184"/> + <line branch="false" hits="15" number="190"/> + <line branch="false" hits="12" number="191"/> + <line branch="false" hits="12" number="193"/> + <line branch="false" hits="15" number="206"/> + <line branch="false" hits="10" number="211"/> + <line branch="false" hits="10" number="212"/> + <line branch="false" hits="10" number="215"/> + <line branch="false" hits="15" number="223"/> + <line branch="false" hits="11" number="228"/> + <line branch="false" hits="11" number="229"/> + <line branch="false" hits="11" number="232"/> + <line branch="false" hits="15" number="240"/> + <line branch="false" hits="11" number="241"/> + <line branch="false" hits="11" number="248"/> + <line branch="false" hits="11" number="249"/> + <line branch="false" hits="15" number="258"/> + <line branch="false" hits="27" number="261"/> + <line branch="false" hits="24" number="264"/> + <line branch="false" hits="24" number="265"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="266"/> + <line branch="false" hits="15" number="272"/> + <line branch="false" hits="27" number="275"/> + <line branch="false" hits="1" number="276"/> + <line branch="false" hits="15" number="285"/> + <line branch="false" hits="27" number="288"/> + <line branch="false" hits="1" number="289"/> + <line branch="false" hits="15" number="298"/> + <line branch="false" hits="28" number="301"/> + <line branch="false" hits="28" number="305"/> + <line branch="false" hits="25" number="306"/> + <line branch="false" hits="13" number="308"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="310"/> + <line branch="false" hits="13" number="312"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="316"/> + <line branch="false" hits="12" number="320"/> + <line branch="false" hits="15" number="328"/> + <line branch="false" hits="25" number="331"/> + <line branch="false" hits="23" number="332"/> + <line branch="false" hits="15" number="341"/> + <line branch="false" hits="30" number="344"/> + <line branch="false" hits="2" number="345"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="347"/> + <line branch="false" hits="15" number="356"/> + <line branch="false" hits="28" number="359"/> + <line branch="false" hits="28" number="360"/> + <line branch="false" hits="25" number="361"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="363"/> + <line branch="false" hits="15" number="371"/> + <line branch="false" hits="28" number="374"/> + <line branch="false" hits="89" number="376"/> + <line branch="false" hits="43" number="380"/> + <line branch="false" hits="15" number="394"/> + <line branch="false" hits="28" number="397"/> + <line branch="false" hits="87" number="399"/> + <line branch="false" hits="45" number="403"/> + <line branch="false" hits="15" number="416"/> + <line branch="false" hits="31" number="419"/> + <line branch="false" hits="91" number="421"/> + <line branch="false" hits="44" number="425"/> + <line branch="false" hits="15" number="442"/> + <line branch="false" hits="25" number="445"/> + <line branch="false" hits="25" number="446"/> + <line branch="false" hits="25" number="489"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/tracking/endvideo/EndVideoLoggerFactory.ts" line-rate="1.0" name="src.tracking.endvideo.EndVideoLoggerFactory.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="15" number="11"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="EndVideoLoggerFactory" signature=""> + <lines> + <line branch="false" hits="14" number="19"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="14" number="32"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="15" number="9"/> + <line branch="false" hits="15" number="11"/> + <line branch="false" hits="14" number="26"/> + <line branch="false" hits="14" number="27"/> + <line branch="false" hits="14" number="28"/> + <line branch="false" hits="14" number="29"/> + <line branch="false" hits="14" number="30"/> + <line branch="false" hits="15" number="32"/> + <line branch="false" hits="14" number="33"/> + <line branch="false" hits="15" number="41"/> + </lines> + </class> + <class branch-rate="1.0" complexity="0" filename="src/tracking/endvideo/EndVideoLoggerTracker.ts" line-rate="0.8227848101265823" name="src.tracking.endvideo.EndVideoLoggerTracker.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="15" number="24"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="EndVideoLoggerTracker" signature=""> + <lines> + <line branch="false" hits="14" number="38"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="0" number="54"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="0" number="62"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="0" number="96"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_43)" signature=""> + <lines> + <line branch="false" hits="9" number="139"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_44)" signature=""> + <lines> + <line branch="false" hits="9" number="140"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_45)" signature=""> + <lines> + <line branch="false" hits="9" number="141"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_46)" signature=""> + <lines> + <line branch="false" hits="20" number="154"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_47)" signature=""> + <lines> + <line branch="false" hits="20" number="155"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_48)" signature=""> + <lines> + <line branch="false" hits="20" number="156"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_49)" signature=""> + <lines> + <line branch="false" hits="20" number="166"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_50)" signature=""> + <lines> + <line branch="false" hits="23" number="177"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="15" number="1"/> + <line branch="false" hits="15" number="4"/> + <line branch="false" hits="15" number="15"/> + <line branch="false" hits="15" number="16"/> + <line branch="false" hits="15" number="17"/> + <line branch="false" hits="15" number="18"/> + <line branch="false" hits="15" number="21"/> + <line branch="false" hits="15" number="22"/> + <line branch="false" hits="15" number="24"/> + <line branch="false" hits="14" number="35"/> + <line branch="true" condition-coverage="100% (2/2)" hits="14" number="45"/> + <line branch="false" hits="14" number="46"/> + <line branch="false" hits="14" number="47"/> + <line branch="false" hits="14" number="48"/> + <line branch="false" hits="14" number="49"/> + <line branch="false" hits="14" number="50"/> + <line branch="false" hits="14" number="52"/> + <line branch="false" hits="14" number="53"/> + <line branch="false" hits="14" number="54"/> + <line branch="false" hits="0" number="56"/> + <line branch="false" hits="0" number="57"/> + <line branch="false" hits="0" number="59"/> + <line branch="false" hits="0" number="60"/> + <line branch="false" hits="0" number="61"/> + <line branch="false" hits="0" number="62"/> + <line branch="false" hits="0" number="64"/> + <line branch="false" hits="0" number="67"/> + <line branch="false" hits="15" number="73"/> + <line branch="false" hits="11" number="79"/> + <line branch="false" hits="11" number="85"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="86"/> + <line branch="false" hits="3" number="90"/> + <line branch="false" hits="16" number="91"/> + <line branch="false" hits="11" number="94"/> + <line branch="false" hits="0" number="97"/> + <line branch="false" hits="15" number="102"/> + <line branch="false" hits="2" number="107"/> + <line branch="false" hits="2" number="108"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="109"/> + <line branch="false" hits="4" number="111"/> + <line branch="false" hits="15" number="114"/> + <line branch="false" hits="2" number="115"/> + <line branch="false" hits="2" number="116"/> + <line branch="false" hits="4" number="118"/> + <line branch="false" hits="15" number="121"/> + <line branch="false" hits="7" number="122"/> + <line branch="false" hits="7" number="123"/> + <line branch="false" hits="14" number="124"/> + <line branch="false" hits="15" number="127"/> + <line branch="false" hits="4" number="132"/> + <line branch="false" hits="8" number="133"/> + <line branch="false" hits="3" number="135"/> + <line branch="false" hits="15" number="139"/> + <line branch="false" hits="9" number="140"/> + <line branch="false" hits="9" number="141"/> + <line branch="false" hits="0" number="143"/> + <line branch="false" hits="0" number="144"/> + <line branch="false" hits="0" number="145"/> + <line branch="false" hits="9" number="147"/> + <line branch="false" hits="9" number="148"/> + <line branch="false" hits="9" number="149"/> + <line branch="false" hits="20" number="154"/> + <line branch="false" hits="20" number="155"/> + <line branch="false" hits="20" number="156"/> + <line branch="false" hits="0" number="158"/> + <line branch="false" hits="0" number="159"/> + <line branch="false" hits="20" number="161"/> + <line branch="false" hits="15" number="166"/> + <line branch="false" hits="15" number="177"/> + <line branch="false" hits="23" number="178"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="179"/> + <line branch="false" hits="15" number="184"/> + <line branch="false" hits="23" number="187"/> + <line branch="false" hits="3" number="194"/> + <line branch="false" hits="11" number="197"/> + <line branch="false" hits="18" number="198"/> + <line branch="false" hits="20" number="201"/> + <line branch="false" hits="40" number="205"/> + <line branch="false" hits="15" number="208"/> + <line branch="false" hits="19" number="209"/> + <line branch="false" hits="38" number="218"/> + <line branch="false" hits="15" number="220"/> + </lines> + </class> + <class branch-rate="1.0" complexity="0" filename="src/tracking/endvideo/EndVideoReasonEnd.ts" line-rate="1.0" name="src.tracking.endvideo.EndVideoReasonEnd.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="15" number="1"/> + </lines> + </method> + </methods> + <lines> + <line branch="true" condition-coverage="100% (2/2)" hits="15" number="1"/> + <line branch="false" hits="15" number="2"/> + <line branch="false" hits="15" number="3"/> + <line branch="false" hits="15" number="4"/> + <line branch="false" hits="15" number="5"/> + <line branch="false" hits="15" number="6"/> + <line branch="false" hits="15" number="7"/> + <line branch="false" hits="15" number="8"/> + <line branch="false" hits="15" number="11"/> + </lines> + </class> + <class branch-rate="0.875" complexity="0" filename="src/tracking/endvideo/EndVideoTracker.ts" line-rate="0.9212121212121213" name="src.tracking.endvideo.EndVideoTracker.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="15" number="24"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="EndVideoTracker" signature=""> + <lines> + <line branch="false" hits="13" number="64"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_5)" signature=""> + <lines> + <line branch="false" hits="13" number="78"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_6)" signature=""> + <lines> + <line branch="false" hits="13" number="110"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="14" number="118"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="64" number="131"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="6" number="237"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="29" number="255"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="13" number="287"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="9" number="295"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="5" number="355"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="13" number="364"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="13" number="417"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="4" number="419"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="13" number="430"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="12" number="438"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="10" number="458"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="15" number="1"/> + <line branch="false" hits="15" number="2"/> + <line branch="false" hits="15" number="15"/> + <line branch="false" hits="15" number="20"/> + <line branch="false" hits="15" number="24"/> + <line branch="false" hits="13" number="71"/> + <line branch="false" hits="13" number="72"/> + <line branch="false" hits="13" number="73"/> + <line branch="false" hits="13" number="74"/> + <line branch="false" hits="13" number="75"/> + <line branch="false" hits="15" number="78"/> + <line branch="false" hits="13" number="79"/> + <line branch="false" hits="13" number="80"/> + <line branch="false" hits="13" number="81"/> + <line branch="false" hits="13" number="82"/> + <line branch="false" hits="13" number="83"/> + <line branch="false" hits="13" number="84"/> + <line branch="false" hits="13" number="85"/> + <line branch="false" hits="13" number="86"/> + <line branch="false" hits="13" number="87"/> + <line branch="false" hits="13" number="88"/> + <line branch="false" hits="13" number="89"/> + <line branch="false" hits="13" number="90"/> + <line branch="false" hits="13" number="91"/> + <line branch="false" hits="13" number="92"/> + <line branch="false" hits="13" number="93"/> + <line branch="false" hits="13" number="94"/> + <line branch="false" hits="13" number="95"/> + <line branch="false" hits="13" number="96"/> + <line branch="false" hits="13" number="97"/> + <line branch="false" hits="13" number="98"/> + <line branch="false" hits="13" number="99"/> + <line branch="false" hits="13" number="100"/> + <line branch="false" hits="13" number="101"/> + <line branch="false" hits="13" number="102"/> + <line branch="false" hits="13" number="103"/> + <line branch="false" hits="13" number="104"/> + <line branch="false" hits="13" number="105"/> + <line branch="false" hits="13" number="106"/> + <line branch="false" hits="13" number="108"/> + <line branch="false" hits="13" number="109"/> + <line branch="false" hits="13" number="110"/> + <line branch="false" hits="0" number="112"/> + <line branch="false" hits="0" number="113"/> + <line branch="false" hits="13" number="115"/> + <line branch="false" hits="13" number="116"/> + <line branch="false" hits="13" number="117"/> + <line branch="false" hits="13" number="118"/> + <line branch="false" hits="14" number="120"/> + <line branch="false" hits="14" number="123"/> + <line branch="false" hits="13" number="128"/> + <line branch="false" hits="15" number="131"/> + <line branch="false" hits="5" number="133"/> + <line branch="false" hits="64" number="135"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="136"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="138"/> + <line branch="false" hits="55" number="139"/> + <line branch="false" hits="55" number="140"/> + <line branch="false" hits="55" number="141"/> + <line branch="false" hits="55" number="142"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="143"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="146"/> + <line branch="false" hits="6" number="147"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="149"/> + <line branch="false" hits="1" number="150"/> + <line branch="false" hits="10" number="154"/> + <line branch="false" hits="10" number="157"/> + <line branch="true" condition-coverage="100% (2/2)" hits="64" number="166"/> + <line branch="false" hits="64" number="167"/> + <line branch="true" condition-coverage="100% (2/2)" hits="64" number="168"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="170"/> + <line branch="false" hits="7" number="171"/> + <line branch="false" hits="2" number="174"/> + <line branch="false" hits="2" number="177"/> + <line branch="false" hits="2" number="178"/> + <line branch="false" hits="3" number="184"/> + <line branch="false" hits="3" number="185"/> + <line branch="false" hits="3" number="186"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="190"/> + <line branch="false" hits="0" number="191"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="193"/> + <line branch="false" hits="0" number="194"/> + <line branch="false" hits="64" number="197"/> + <line branch="false" hits="21" number="199"/> + <line branch="false" hits="64" number="201"/> + <line branch="false" hits="2" number="203"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="204"/> + <line branch="false" hits="1" number="205"/> + <line branch="false" hits="3" number="209"/> + <line branch="false" hits="3" number="215"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="218"/> + <line branch="false" hits="10" number="219"/> + <line branch="true" condition-coverage="100% (2/2)" hits="10" number="226"/> + <line branch="true" condition-coverage="100% (2/2)" hits="10" number="227"/> + <line branch="false" hits="10" number="229"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="230"/> + <line branch="false" hits="10" number="231"/> + <line branch="false" hits="10" number="233"/> + <line branch="false" hits="15" number="237"/> + <line branch="false" hits="6" number="238"/> + <line branch="false" hits="6" number="245"/> + <line branch="false" hits="3" number="247"/> + <line branch="false" hits="3" number="248"/> + <line branch="false" hits="3" number="250"/> + <line branch="false" hits="3" number="251"/> + <line branch="false" hits="15" number="255"/> + <line branch="false" hits="27" number="262"/> + <line branch="false" hits="16" number="264"/> + <line branch="false" hits="27" number="269"/> + <line branch="false" hits="17" number="272"/> + <line branch="false" hits="10" number="274"/> + <line branch="false" hits="27" number="283"/> + <line branch="false" hits="15" number="287"/> + <line branch="false" hits="13" number="288"/> + <line branch="false" hits="13" number="289"/> + <line branch="false" hits="13" number="290"/> + <line branch="false" hits="13" number="291"/> + <line branch="false" hits="13" number="292"/> + <line branch="false" hits="13" number="293"/> + <line branch="false" hits="13" number="295"/> + <line branch="false" hits="6" number="297"/> + <line branch="false" hits="1" number="299"/> + <line branch="false" hits="2" number="301"/> + <line branch="false" hits="13" number="303"/> + <line branch="false" hits="13" number="304"/> + <line branch="false" hits="17" number="305"/> + <line branch="false" hits="17" number="306"/> + <line branch="false" hits="17" number="307"/> + <line branch="false" hits="12" number="310"/> + <line branch="false" hits="12" number="311"/> + <line branch="false" hits="5" number="313"/> + <line branch="false" hits="5" number="314"/> + <line branch="false" hits="10" number="317"/> + <line branch="false" hits="7" number="319"/> + <line branch="false" hits="7" number="320"/> + <line branch="false" hits="17" number="322"/> + <line branch="false" hits="13" number="324"/> + <line branch="false" hits="0" number="328"/> + <line branch="false" hits="10" number="330"/> + <line branch="false" hits="4" number="333"/> + <line branch="false" hits="6" number="335"/> + <line branch="false" hits="13" number="339"/> + <line branch="false" hits="6" number="342"/> + <line branch="false" hits="13" number="347"/> + <line branch="false" hits="15" number="355"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="357"/> + <line branch="false" hits="1" number="358"/> + <line branch="true" condition-coverage="100% (2/2)" hits="4" number="360"/> + <line branch="false" hits="15" number="364"/> + <line branch="false" hits="13" number="365"/> + <line branch="false" hits="13" number="366"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="367"/> + <line branch="false" hits="13" number="369"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="377"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="405"/> + <line branch="false" hits="15" number="417"/> + <line branch="false" hits="13" number="418"/> + <line branch="false" hits="13" number="419"/> + <line branch="false" hits="0" number="421"/> + <line branch="false" hits="0" number="422"/> + <line branch="false" hits="1" number="425"/> + <line branch="false" hits="15" number="430"/> + <line branch="false" hits="0" number="432"/> + <line branch="false" hits="12" number="436"/> + <line branch="false" hits="12" number="438"/> + <line branch="false" hits="0" number="440"/> + <line branch="false" hits="0" number="441"/> + <line branch="false" hits="0" number="442"/> + <line branch="false" hits="12" number="444"/> + <line branch="false" hits="12" number="445"/> + <line branch="false" hits="12" number="446"/> + <line branch="false" hits="12" number="448"/> + <line branch="false" hits="0" number="452"/> + <line branch="false" hits="1" number="455"/> + <line branch="false" hits="15" number="458"/> + <line branch="false" hits="0" number="460"/> + <line branch="false" hits="10" number="462"/> + <line branch="false" hits="10" number="463"/> + <line branch="false" hits="10" number="464"/> + <line branch="false" hits="15" number="466"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="1.0" complexity="0" line-rate="0.7777777777777778" name="src.tracking.session"> + <classes> + <class branch-rate="1.0" complexity="0" filename="src/tracking/session/PlaybackSessionTracker.ts" line-rate="1.0" name="src.tracking.session.PlaybackSessionTracker.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_7)" signature=""> + <lines> + <line branch="false" hits="16" number="7"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="PlaybackSessionTracker" signature=""> + <lines> + <line branch="false" hits="1" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="1" number="14"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="16" number="1"/> + <line branch="false" hits="16" number="7"/> + <line branch="true" condition-coverage="100% (2/2)" hits="1" number="10"/> + <line branch="false" hits="1" number="11"/> + <line branch="false" hits="16" number="14"/> + <line branch="false" hits="1" number="19"/> + <line branch="false" hits="1" number="21"/> + <line branch="false" hits="1" number="22"/> + <line branch="false" hits="16" number="25"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/tracking/session/VideoPlaybackSessionLogger.ts" line-rate="0.5555555555555556" name="src.tracking.session.VideoPlaybackSessionLogger.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="15" number="6"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="VideoPlaybackSessionLogger" signature=""> + <lines> + <line branch="false" hits="0" number="9"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_3)" signature=""> + <lines> + <line branch="false" hits="0" number="12"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_4)" signature=""> + <lines> + <line branch="false" hits="0" number="13"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="15" number="3"/> + <line branch="false" hits="15" number="4"/> + <line branch="false" hits="15" number="6"/> + <line branch="false" hits="0" number="10"/> + <line branch="false" hits="15" number="12"/> + <line branch="false" hits="0" number="13"/> + <line branch="false" hits="0" number="14"/> + <line branch="false" hits="0" number="15"/> + <line branch="false" hits="15" number="18"/> + </lines> + </class> + </classes> + </package> + </packages> +</coverage> diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-3.xml b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-3.xml new file mode 100644 index 0000000000..176152791b --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-3.xml @@ -0,0 +1,357 @@ +<?xml version="1.0" ?> +<coverage lines-valid="524" lines-covered="455" line-rate="0.8683" branches-valid="653" branches-covered="465" branch-rate="0.7121" timestamp="1575309673957" complexity="0" version="0.1"> + <packages> + <package name="src" line-rate="1" branch-rate="1"> + <classes> + <class name="index.ts" filename="src/index.ts" line-rate="1" branch-rate="1"> + <methods> + </methods> + <lines> + </lines> + </class> + </classes> + </package> + <package name="src.atoms.BoxShadow" line-rate="1" branch-rate="1"> + <classes> + <class name="box-shadow.ts" filename="src/atoms/BoxShadow/box-shadow.ts" line-rate="1" branch-rate="1"> + <methods> + </methods> + <lines> + <line number="4" hits="5" branch="false"/> + </lines> + </class> + <class name="index.ts" filename="src/atoms/BoxShadow/index.ts" line-rate="1" branch-rate="1"> + <methods> + </methods> + <lines> + </lines> + </class> + </classes> + </package> + <package name="src.atoms.Button" line-rate="0.4706" branch-rate="0.7646999999999999"> + <classes> + <class name="button.tsx" filename="src/atoms/Button/button.tsx" line-rate="0.4706" branch-rate="0.7646999999999999"> + <methods> + <method name="ButtonComponent" hits="41" signature="()V"> + <lines> + <line number="17" hits="41"/> + </lines> + </method> + <method name="(anonymous_1)" hits="0" signature="()V"> + <lines> + <line number="34" hits="0"/> + </lines> + </method> + <method name="(anonymous_2)" hits="41" signature="()V"> + <lines> + <line number="70" hits="41"/> + </lines> + </method> + <method name="(anonymous_3)" hits="41" signature="()V"> + <lines> + <line number="72" hits="41"/> + </lines> + </method> + <method name="(anonymous_4)" hits="41" signature="()V"> + <lines> + <line number="74" hits="41"/> + </lines> + </method> + </methods> + <lines> + <line number="31" hits="41" branch="false"/> + <line number="32" hits="41" branch="false"/> + <line number="34" hits="41" branch="false"/> + <line number="35" hits="0" branch="true" condition-coverage="0% (0/4)"/> + <line number="36" hits="0" branch="false"/> + <line number="37" hits="0" branch="false"/> + <line number="38" hits="0" branch="false"/> + <line number="39" hits="0" branch="false"/> + <line number="40" hits="0" branch="false"/> + <line number="41" hits="0" branch="false"/> + <line number="42" hits="0" branch="false"/> + <line number="43" hits="0" branch="false"/> + <line number="47" hits="41" branch="false"/> + <line number="68" hits="10" branch="false"/> + <line number="70" hits="41" branch="true" condition-coverage="100% (1/1)"/> + <line number="72" hits="41" branch="true" condition-coverage="100% (3/3)"/> + <line number="75" hits="41" branch="true" condition-coverage="100% (2/2)"/> + </lines> + </class> + <class name="index.ts" filename="src/atoms/Button/index.ts" line-rate="1" branch-rate="1"> + <methods> + </methods> + <lines> + </lines> + </class> + </classes> + </package> + <package name="src.atoms.Container" line-rate="1" branch-rate="1"> + <classes> + <class name="components.ts" filename="src/atoms/Container/components.ts" line-rate="1" branch-rate="1"> + <methods> + <method name="(anonymous_0)" hits="35" signature="()V"> + <lines> + <line number="5" hits="35"/> + </lines> + </method> + <method name="(anonymous_1)" hits="35" signature="()V"> + <lines> + <line number="19" hits="35"/> + </lines> + </method> + <method name="(anonymous_2)" hits="35" signature="()V"> + <lines> + <line number="20" hits="35"/> + </lines> + </method> + <method name="(anonymous_3)" hits="35" signature="()V"> + <lines> + <line number="23" hits="35"/> + </lines> + </method> + </methods> + <lines> + <line number="4" hits="13" branch="false"/> + <line number="5" hits="35" branch="false"/> + <line number="13" hits="13" branch="false"/> + <line number="19" hits="35" branch="false"/> + <line number="20" hits="35" branch="false"/> + <line number="23" hits="35" branch="false"/> + </lines> + </class> + <class name="container.tsx" filename="src/atoms/Container/container.tsx" line-rate="1" branch-rate="1"> + <methods> + <method name="Container" hits="35" signature="()V"> + <lines> + <line number="12" hits="35"/> + </lines> + </method> + </methods> + <lines> + <line number="20" hits="35" branch="false"/> + </lines> + </class> + <class name="index.ts" filename="src/atoms/Container/index.ts" line-rate="1" branch-rate="1"> + <methods> + </methods> + <lines> + </lines> + </class> + </classes> + </package> + <package name="src.atoms.DownArrow" line-rate="1" branch-rate="1"> + <classes> + <class name="down-arrow.tsx" filename="src/atoms/DownArrow/down-arrow.tsx" line-rate="1" branch-rate="1"> + <methods> + <method name="DownArrow" hits="28" signature="()V"> + <lines> + <line number="3" hits="28"/> + </lines> + </method> + </methods> + <lines> + <line number="4" hits="28" branch="false"/> + </lines> + </class> + <class name="index.ts" filename="src/atoms/DownArrow/index.ts" line-rate="1" branch-rate="1"> + <methods> + </methods> + <lines> + </lines> + </class> + </classes> + </package> + <package name="src.molecules.Hero" line-rate="0.8695999999999999" branch-rate="0.7236"> + <classes> + <class name="components.ts" filename="src/molecules/Hero/components.ts" line-rate="0.8769" branch-rate="0.7143"> + <methods> + <method name="(anonymous_0)" hits="10" signature="()V"> + <lines> + <line number="26" hits="10"/> + </lines> + </method> + <method name="(anonymous_1)" hits="10" signature="()V"> + <lines> + <line number="28" hits="10"/> + </lines> + </method> + <method name="(anonymous_2)" hits="10" signature="()V"> + <lines> + <line number="94" hits="10"/> + </lines> + </method> + <method name="(anonymous_3)" hits="10" signature="()V"> + <lines> + <line number="103" hits="10"/> + </lines> + </method> + <method name="(anonymous_4)" hits="10" signature="()V"> + <lines> + <line number="121" hits="10"/> + </lines> + </method> + <method name="(anonymous_5)" hits="10" signature="()V"> + <lines> + <line number="182" hits="10"/> + </lines> + </method> + <method name="(anonymous_6)" hits="5" signature="()V"> + <lines> + <line number="203" hits="5"/> + </lines> + </method> + <method name="(anonymous_7)" hits="5" signature="()V"> + <lines> + <line number="218" hits="5"/> + </lines> + </method> + <method name="(anonymous_8)" hits="5" signature="()V"> + <lines> + <line number="236" hits="5"/> + </lines> + </method> + <method name="(anonymous_9)" hits="5" signature="()V"> + <lines> + <line number="241" hits="5"/> + </lines> + </method> + <method name="(anonymous_10)" hits="4" signature="()V"> + <lines> + <line number="249" hits="4"/> + </lines> + </method> + <method name="(anonymous_11)" hits="4" signature="()V"> + <lines> + <line number="254" hits="4"/> + </lines> + </method> + <method name="(anonymous_12)" hits="4" signature="()V"> + <lines> + <line number="264" hits="4"/> + </lines> + </method> + <method name="(anonymous_13)" hits="4" signature="()V"> + <lines> + <line number="277" hits="4"/> + </lines> + </method> + <method name="(anonymous_14)" hits="4" signature="()V"> + <lines> + <line number="282" hits="4"/> + </lines> + </method> + <method name="(anonymous_15)" hits="4" signature="()V"> + <lines> + <line number="294" hits="4"/> + </lines> + </method> + <method name="(anonymous_16)" hits="3" signature="()V"> + <lines> + <line number="299" hits="3"/> + </lines> + </method> + </methods> + <lines> + <line number="25" hits="2" branch="false"/> + <line number="26" hits="10" branch="false"/> + <line number="29" hits="10" branch="true" condition-coverage="100% (2/2)"/> + <line number="37" hits="3" branch="false"/> + <line number="39" hits="3" branch="true" condition-coverage="100% (2/2)"/> + <line number="40" hits="3" branch="false"/> + <line number="42" hits="3" branch="true" condition-coverage="100% (2/2)"/> + <line number="43" hits="1" branch="true" condition-coverage="75% (3/4)"/> + <line number="44" hits="1" branch="false"/> + <line number="45" hits="0" branch="true" condition-coverage="0% (0/4)"/> + <line number="46" hits="0" branch="false"/> + <line number="48" hits="1" branch="true" condition-coverage="50% (1/2)"/> + <line number="52" hits="0" branch="false"/> + <line number="53" hits="1" branch="true" condition-coverage="50% (1/2)"/> + <line number="57" hits="0" branch="false"/> + <line number="59" hits="1" branch="true" condition-coverage="50% (1/2)"/> + <line number="60" hits="1" branch="true" condition-coverage="50% (1/2)"/> + <line number="63" hits="3" branch="false"/> + <line number="95" hits="10" branch="true" condition-coverage="50% (1/2)"/> + <line number="103" hits="10" branch="false"/> + <line number="112" hits="2" branch="false"/> + <line number="122" hits="10" branch="true" condition-coverage="50% (2/4)"/> + <line number="125" hits="9" branch="false"/> + <line number="134" hits="0" branch="false"/> + <line number="151" hits="1" branch="false"/> + <line number="170" hits="2" branch="false"/> + <line number="181" hits="2" branch="false"/> + <line number="182" hits="10" branch="true" condition-coverage="100% (2/2)"/> + <line number="194" hits="2" branch="false"/> + <line number="204" hits="5" branch="true" condition-coverage="80% (4/5)"/> + <line number="207" hits="3" branch="false"/> + <line number="209" hits="0" branch="false"/> + <line number="211" hits="1" branch="false"/> + <line number="213" hits="1" branch="false"/> + <line number="219" hits="5" branch="true" condition-coverage="66.66666666666666% (4/6)"/> + <line number="222" hits="3" branch="false"/> + <line number="224" hits="0" branch="false"/> + <line number="226" hits="0" branch="false"/> + <line number="228" hits="1" branch="false"/> + <line number="230" hits="1" branch="false"/> + <line number="236" hits="5" branch="true" condition-coverage="100% (1/1)"/> + <line number="241" hits="5" branch="true" condition-coverage="100% (1/1)"/> + <line number="245" hits="2" branch="false"/> + <line number="249" hits="4" branch="true" condition-coverage="50% (1/2)"/> + <line number="255" hits="4" branch="true" condition-coverage="100% (3/3)"/> + <line number="258" hits="3" branch="false"/> + <line number="260" hits="1" branch="false"/> + <line number="265" hits="4" branch="true" condition-coverage="100% (4/4)"/> + <line number="268" hits="2" branch="false"/> + <line number="270" hits="1" branch="false"/> + <line number="272" hits="1" branch="false"/> + <line number="277" hits="4" branch="true" condition-coverage="100% (1/1)"/> + <line number="283" hits="4" branch="true" condition-coverage="100% (4/4)"/> + <line number="286" hits="2" branch="false"/> + <line number="288" hits="1" branch="false"/> + <line number="290" hits="1" branch="false"/> + <line number="294" hits="4" branch="true" condition-coverage="50% (1/2)"/> + <line number="298" hits="2" branch="false"/> + <line number="299" hits="3" branch="true" condition-coverage="50% (1/2)"/> + <line number="304" hits="2" branch="false"/> + <line number="311" hits="2" branch="false"/> + <line number="319" hits="2" branch="false"/> + <line number="329" hits="2" branch="false"/> + <line number="361" hits="2" branch="false"/> + <line number="371" hits="2" branch="false"/> + </lines> + </class> + <class name="hero.tsx" filename="src/molecules/Hero/hero.tsx" line-rate="0.75" branch-rate="0.76"> + <methods> + <method name="Hero" hits="10" signature="()V"> + <lines> + <line number="40" hits="10"/> + </lines> + </method> + <method name="(anonymous_1)" hits="0" signature="()V"> + <lines> + <line number="72" hits="0"/> + </lines> + </method> + <method name="(anonymous_2)" hits="3" signature="()V"> + <lines> + <line number="127" hits="3"/> + </lines> + </method> + </methods> + <lines> + <line number="56" hits="10" branch="false"/> + <line number="58" hits="10" branch="false"/> + <line number="73" hits="0" branch="true" condition-coverage="0% (0/2)"/> + <line number="128" hits="3" branch="false"/> + </lines> + </class> + <class name="index.ts" filename="src/molecules/Hero/index.ts" line-rate="1" branch-rate="1"> + <methods> + </methods> + <lines> + </lines> + </class> + </classes> + </package> + </packages> +</coverage> diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-4.xml b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-4.xml new file mode 100644 index 0000000000..36e36da3be --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-4.xml @@ -0,0 +1,348 @@ +<?xml version="1.0" ?> +<coverage line-rate="0.0" lines-covered="0" lines-valid="325" version="0.1"> + <package line-rate="0.0" name="Sources"> + <classes> + <class filename="Sources/TDSOptions.m" line-rate="0.0" name="TDSOptions.m"> + <lines> + <line hits="0" number="32" /> + <line hits="0" number="33" /> + <line hits="0" number="34" /> + <line hits="0" number="35" /> + <line hits="0" number="36" /> + <line hits="0" number="37" /> + <line hits="0" number="38" /> + <line hits="0" number="45" /> + <line hits="0" number="46" /> + <line hits="0" number="47" /> + <line hits="0" number="48" /> + <line hits="0" number="49" /> + <line hits="0" number="50" /> + <line hits="0" number="51" /> + <line hits="0" number="52" /> + <line hits="0" number="53" /> + <line hits="0" number="54" /> + <line hits="0" number="55" /> + <line hits="0" number="56" /> + <line hits="0" number="57" /> + <line hits="0" number="58" /> + <line hits="0" number="61" /> + <line hits="0" number="62" /> + <line hits="0" number="63" /> + <line hits="0" number="66" /> + <line hits="0" number="67" /> + <line hits="0" number="68" /> + <line hits="0" number="69" /> + <line hits="0" number="70" /> + <line hits="0" number="71" /> + <line hits="0" number="72" /> + <line hits="0" number="73" /> + <line hits="0" number="74" /> + <line hits="0" number="75" /> + <line hits="0" number="76" /> + <line hits="0" number="77" /> + </lines> + </class> + <class filename="Sources/TDSUserLock.m" line-rate="0.0" name="TDSUserLock.m"> + <lines> + <line hits="0" number="17" /> + <line hits="0" number="18" /> + <line hits="0" number="19" /> + <line hits="0" number="20" /> + <line hits="0" number="21" /> + <line hits="0" number="22" /> + <line hits="0" number="23" /> + <line hits="0" number="24" /> + <line hits="0" number="25" /> + <line hits="0" number="26" /> + <line hits="0" number="27" /> + <line hits="0" number="28" /> + <line hits="0" number="29" /> + <line hits="0" number="30" /> + <line hits="0" number="31" /> + <line hits="0" number="32" /> + <line hits="0" number="33" /> + <line hits="0" number="34" /> + <line hits="0" number="35" /> + <line hits="0" number="36" /> + <line hits="0" number="37" /> + <line hits="0" number="38" /> + <line hits="0" number="39" /> + <line hits="0" number="40" /> + <line hits="0" number="43" /> + <line hits="0" number="44" /> + <line hits="0" number="45" /> + <line hits="0" number="46" /> + <line hits="0" number="47" /> + <line hits="0" number="48" /> + <line hits="0" number="49" /> + <line hits="0" number="58" /> + <line hits="0" number="59" /> + <line hits="0" number="60" /> + <line hits="0" number="61" /> + <line hits="0" number="62" /> + <line hits="0" number="63" /> + <line hits="0" number="64" /> + <line hits="0" number="65" /> + <line hits="0" number="66" /> + <line hits="0" number="67" /> + <line hits="0" number="68" /> + <line hits="0" number="69" /> + <line hits="0" number="70" /> + </lines> + </class> + <class filename="Sources/TDSUserManager.m" line-rate="0.0" name="TDSUserManager.m"> + <lines> + <line hits="0" number="24" /> + <line hits="0" number="25" /> + <line hits="0" number="26" /> + <line hits="0" number="27" /> + <line hits="0" number="28" /> + <line hits="0" number="29" /> + <line hits="0" number="30" /> + <line hits="0" number="31" /> + <line hits="0" number="34" /> + <line hits="0" number="35" /> + <line hits="0" number="36" /> + <line hits="0" number="37" /> + <line hits="0" number="38" /> + <line hits="0" number="39" /> + <line hits="0" number="40" /> + <line hits="0" number="49" /> + <line hits="0" number="50" /> + <line hits="0" number="51" /> + <line hits="0" number="52" /> + <line hits="0" number="53" /> + <line hits="0" number="54" /> + <line hits="0" number="55" /> + <line hits="0" number="56" /> + <line hits="0" number="57" /> + <line hits="0" number="58" /> + <line hits="0" number="59" /> + <line hits="0" number="60" /> + <line hits="0" number="61" /> + <line hits="0" number="62" /> + <line hits="0" number="63" /> + <line hits="0" number="64" /> + <line hits="0" number="65" /> + <line hits="0" number="66" /> + <line hits="0" number="67" /> + <line hits="0" number="68" /> + <line hits="0" number="69" /> + <line hits="0" number="70" /> + <line hits="0" number="74" /> + <line hits="0" number="75" /> + <line hits="0" number="76" /> + <line hits="0" number="77" /> + <line hits="0" number="78" /> + <line hits="0" number="79" /> + <line hits="0" number="80" /> + <line hits="0" number="81" /> + <line hits="0" number="82" /> + <line hits="0" number="83" /> + <line hits="0" number="84" /> + <line hits="0" number="85" /> + <line hits="0" number="86" /> + <line hits="0" number="87" /> + <line hits="0" number="88" /> + <line hits="0" number="89" /> + <line hits="0" number="90" /> + <line hits="0" number="91" /> + <line hits="0" number="92" /> + <line hits="0" number="93" /> + <line hits="0" number="94" /> + <line hits="0" number="101" /> + <line hits="0" number="102" /> + <line hits="0" number="103" /> + <line hits="0" number="104" /> + <line hits="0" number="105" /> + <line hits="0" number="106" /> + <line hits="0" number="107" /> + <line hits="0" number="108" /> + <line hits="0" number="109" /> + <line hits="0" number="110" /> + <line hits="0" number="111" /> + <line hits="0" number="112" /> + <line hits="0" number="113" /> + <line hits="0" number="114" /> + <line hits="0" number="115" /> + <line hits="0" number="116" /> + <line hits="0" number="117" /> + <line hits="0" number="118" /> + <line hits="0" number="119" /> + <line hits="0" number="120" /> + <line hits="0" number="121" /> + <line hits="0" number="122" /> + <line hits="0" number="123" /> + <line hits="0" number="124" /> + <line hits="0" number="125" /> + <line hits="0" number="126" /> + <line hits="0" number="127" /> + <line hits="0" number="128" /> + <line hits="0" number="129" /> + <line hits="0" number="130" /> + <line hits="0" number="131" /> + <line hits="0" number="136" /> + <line hits="0" number="137" /> + <line hits="0" number="138" /> + <line hits="0" number="139" /> + <line hits="0" number="140" /> + <line hits="0" number="141" /> + <line hits="0" number="142" /> + <line hits="0" number="143" /> + <line hits="0" number="144" /> + <line hits="0" number="145" /> + <line hits="0" number="146" /> + <line hits="0" number="147" /> + <line hits="0" number="148" /> + <line hits="0" number="149" /> + <line hits="0" number="150" /> + <line hits="0" number="151" /> + <line hits="0" number="152" /> + <line hits="0" number="153" /> + <line hits="0" number="158" /> + <line hits="0" number="159" /> + <line hits="0" number="160" /> + <line hits="0" number="161" /> + <line hits="0" number="162" /> + <line hits="0" number="163" /> + <line hits="0" number="164" /> + <line hits="0" number="165" /> + <line hits="0" number="166" /> + <line hits="0" number="167" /> + <line hits="0" number="168" /> + <line hits="0" number="169" /> + <line hits="0" number="170" /> + <line hits="0" number="171" /> + <line hits="0" number="172" /> + <line hits="0" number="173" /> + <line hits="0" number="174" /> + <line hits="0" number="175" /> + <line hits="0" number="176" /> + <line hits="0" number="177" /> + <line hits="0" number="178" /> + <line hits="0" number="179" /> + <line hits="0" number="180" /> + <line hits="0" number="181" /> + <line hits="0" number="182" /> + <line hits="0" number="183" /> + <line hits="0" number="184" /> + <line hits="0" number="189" /> + <line hits="0" number="190" /> + <line hits="0" number="191" /> + <line hits="0" number="192" /> + <line hits="0" number="193" /> + <line hits="0" number="194" /> + <line hits="0" number="195" /> + <line hits="0" number="196" /> + <line hits="0" number="197" /> + <line hits="0" number="198" /> + <line hits="0" number="199" /> + <line hits="0" number="200" /> + <line hits="0" number="201" /> + <line hits="0" number="202" /> + <line hits="0" number="203" /> + <line hits="0" number="204" /> + <line hits="0" number="205" /> + <line hits="0" number="206" /> + <line hits="0" number="207" /> + <line hits="0" number="208" /> + <line hits="0" number="209" /> + <line hits="0" number="210" /> + <line hits="0" number="211" /> + <line hits="0" number="212" /> + <line hits="0" number="213" /> + <line hits="0" number="214" /> + <line hits="0" number="215" /> + <line hits="0" number="216" /> + <line hits="0" number="217" /> + <line hits="0" number="218" /> + <line hits="0" number="219" /> + <line hits="0" number="220" /> + <line hits="0" number="221" /> + <line hits="0" number="222" /> + <line hits="0" number="223" /> + <line hits="0" number="224" /> + <line hits="0" number="225" /> + <line hits="0" number="226" /> + <line hits="0" number="227" /> + <line hits="0" number="228" /> + <line hits="0" number="229" /> + <line hits="0" number="230" /> + <line hits="0" number="231" /> + <line hits="0" number="232" /> + <line hits="0" number="233" /> + <line hits="0" number="234" /> + <line hits="0" number="235" /> + <line hits="0" number="236" /> + <line hits="0" number="239" /> + <line hits="0" number="240" /> + <line hits="0" number="241" /> + <line hits="0" number="242" /> + <line hits="0" number="243" /> + <line hits="0" number="244" /> + <line hits="0" number="245" /> + <line hits="0" number="246" /> + <line hits="0" number="247" /> + <line hits="0" number="248" /> + <line hits="0" number="249" /> + <line hits="0" number="252" /> + <line hits="0" number="253" /> + <line hits="0" number="254" /> + <line hits="0" number="255" /> + <line hits="0" number="256" /> + <line hits="0" number="257" /> + <line hits="0" number="258" /> + <line hits="0" number="259" /> + <line hits="0" number="260" /> + <line hits="0" number="261" /> + <line hits="0" number="262" /> + <line hits="0" number="263" /> + <line hits="0" number="264" /> + <line hits="0" number="265" /> + <line hits="0" number="268" /> + <line hits="0" number="269" /> + <line hits="0" number="270" /> + <line hits="0" number="271" /> + <line hits="0" number="272" /> + <line hits="0" number="273" /> + <line hits="0" number="274" /> + <line hits="0" number="275" /> + <line hits="0" number="276" /> + <line hits="0" number="277" /> + <line hits="0" number="278" /> + <line hits="0" number="279" /> + <line hits="0" number="280" /> + <line hits="0" number="281" /> + <line hits="0" number="282" /> + <line hits="0" number="283" /> + <line hits="0" number="284" /> + <line hits="0" number="287" /> + <line hits="0" number="288" /> + <line hits="0" number="289" /> + <line hits="0" number="290" /> + <line hits="0" number="291" /> + <line hits="0" number="292" /> + <line hits="0" number="293" /> + <line hits="0" number="294" /> + <line hits="0" number="295" /> + <line hits="0" number="296" /> + </lines> + </class> + <class filename="Sources/TDSUtil.m" line-rate="0.0" name="TDSUtil.m"> + <lines> + <line hits="0" number="8" /> + <line hits="0" number="9" /> + <line hits="0" number="10" /> + <line hits="0" number="11" /> + <line hits="0" number="12" /> + <line hits="0" number="13" /> + <line hits="0" number="16" /> + <line hits="0" number="17" /> + <line hits="0" number="18" /> + <line hits="0" number="19" /> + <line hits="0" number="20" /> + </lines> + </class> + </classes> + </package> +</coverage> diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-5.xml b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-5.xml new file mode 100644 index 0000000000..5bc8e6e45d --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/cobertura-testdata-5.xml @@ -0,0 +1,441 @@ +<?xml version="1.0" ?> +<coverage branch-rate="0.7602339181286549" branches-covered="130" branches-valid="171" complexity="0" line-rate="0.8738738738738738" lines-covered="582" lines-valid="666" timestamp="1575668573" version="2.0.3"> + <sources> + <source>.</source> + </sources> + <packages> + <package branch-rate="0.75" complexity="0" line-rate="0.9672131147540983" name="src.graphql"> + <classes> + <class branch-rate="0.0" complexity="0" filename="src/graphql/queries.ts" line-rate="1.0" name="src.graphql.queries.ts"> + <methods/> + <lines> + <line branch="false" hits="3" number="1"/> + <line branch="false" hits="3" number="3"/> + <line branch="false" hits="3" number="50"/> + <line branch="false" hits="3" number="65"/> + <line branch="false" hits="3" number="80"/> + <line branch="false" hits="3" number="92"/> + <line branch="false" hits="3" number="138"/> + </lines> + </class> + <class branch-rate="0.8" complexity="0" filename="src/graphql/resolvers.ts" line-rate="0.974025974025974" name="src.graphql.resolvers.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_12)" signature=""> + <lines> + <line branch="false" hits="17" number="22"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_13)" signature=""> + <lines> + <line branch="false" hits="10" number="28"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_14)" signature=""> + <lines> + <line branch="false" hits="12" number="36"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_15)" signature=""> + <lines> + <line branch="false" hits="4" number="27"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_16)" signature=""> + <lines> + <line branch="false" hits="4" number="35"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_17)" signature=""> + <lines> + <line branch="false" hits="9" number="43"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_18)" signature=""> + <lines> + <line branch="false" hits="11" number="51"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_19)" signature=""> + <lines> + <line branch="false" hits="4" number="56"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_20)" signature=""> + <lines> + <line branch="false" hits="4" number="61"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_21)" signature=""> + <lines> + <line branch="false" hits="4" number="50"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_22)" signature=""> + <lines> + <line branch="false" hits="4" number="55"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_23)" signature=""> + <lines> + <line branch="false" hits="4" number="60"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_24)" signature=""> + <lines> + <line branch="false" hits="7" number="128"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_25)" signature=""> + <lines> + <line branch="false" hits="4" number="139"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_26)" signature=""> + <lines> + <line branch="false" hits="4" number="145"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_28)" signature=""> + <lines> + <line branch="false" hits="4" number="160"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_30)" signature=""> + <lines> + <line branch="false" hits="3" number="177"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_31)" signature=""> + <lines> + <line branch="false" hits="9" number="185"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_32)" signature=""> + <lines> + <line branch="false" hits="8" number="70"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_33)" signature=""> + <lines> + <line branch="false" hits="4" number="78"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_34)" signature=""> + <lines> + <line branch="false" hits="4" number="81"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_35)" signature=""> + <lines> + <line branch="false" hits="4" number="84"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_36)" signature=""> + <lines> + <line branch="false" hits="4" number="97"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_37)" signature=""> + <lines> + <line branch="false" hits="4" number="97"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_38)" signature=""> + <lines> + <line branch="false" hits="4" number="103"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_39)" signature=""> + <lines> + <line branch="false" hits="4" number="114"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_40)" signature=""> + <lines> + <line branch="false" hits="4" number="144"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_41)" signature=""> + <lines> + <line branch="false" hits="4" number="159"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_42)" signature=""> + <lines> + <line branch="false" hits="4" number="176"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_43)" signature=""> + <lines> + <line branch="false" hits="4" number="184"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="4" number="1"/> + <line branch="false" hits="4" number="2"/> + <line branch="false" hits="4" number="3"/> + <line branch="false" hits="4" number="5"/> + <line branch="false" hits="4" number="6"/> + <line branch="false" hits="4" number="7"/> + <line branch="false" hits="4" number="8"/> + <line branch="false" hits="4" number="9"/> + <line branch="false" hits="4" number="10"/> + <line branch="false" hits="4" number="14"/> + <line branch="false" hits="4" number="21"/> + <line branch="false" hits="17" number="24"/> + <line branch="false" hits="4" number="27"/> + <line branch="false" hits="4" number="28"/> + <line branch="false" hits="10" number="32"/> + <line branch="false" hits="4" number="35"/> + <line branch="false" hits="4" number="36"/> + <line branch="false" hits="12" number="37"/> + <line branch="false" hits="4" number="42"/> + <line branch="false" hits="9" number="45"/> + <line branch="false" hits="9" number="47"/> + <line branch="false" hits="4" number="50"/> + <line branch="false" hits="4" number="51"/> + <line branch="false" hits="11" number="52"/> + <line branch="false" hits="4" number="55"/> + <line branch="false" hits="4" number="56"/> + <line branch="false" hits="4" number="57"/> + <line branch="false" hits="4" number="60"/> + <line branch="false" hits="4" number="61"/> + <line branch="false" hits="4" number="62"/> + <line branch="false" hits="4" number="67"/> + <line branch="false" hits="4" number="70"/> + <line branch="false" hits="8" number="73"/> + <line branch="false" hits="4" number="78"/> + <line branch="false" hits="4" number="81"/> + <line branch="false" hits="4" number="83"/> + <line branch="false" hits="4" number="85"/> + <line branch="true" condition-coverage="100% (2/2)" hits="4" number="86"/> + <line branch="false" hits="4" number="87"/> + <line branch="false" hits="4" number="88"/> + <line branch="false" hits="4" number="94"/> + <line branch="false" hits="4" number="95"/> + <line branch="false" hits="4" number="97"/> + <line branch="false" hits="4" number="98"/> + <line branch="false" hits="4" number="103"/> + <line branch="false" hits="4" number="104"/> + <line branch="false" hits="4" number="107"/> + <line branch="false" hits="4" number="114"/> + <line branch="false" hits="4" number="115"/> + <line branch="false" hits="4" number="118"/> + <line branch="true" condition-coverage="50% (1/2)" hits="4" number="119"/> + <line branch="false" hits="0" number="120"/> + <line branch="false" hits="4" number="124"/> + <line branch="false" hits="7" number="130"/> + <line branch="false" hits="7" number="132"/> + <line branch="false" hits="7" number="134"/> + <line branch="false" hits="7" number="136"/> + <line branch="false" hits="4" number="140"/> + <line branch="false" hits="4" number="144"/> + <line branch="false" hits="4" number="145"/> + <line branch="false" hits="4" number="151"/> + <line branch="false" hits="4" number="159"/> + <line branch="false" hits="4" number="160"/> + <line branch="false" hits="4" number="165"/> + <line branch="true" condition-coverage="100% (2/2)" hits="4" number="166"/> + <line branch="true" condition-coverage="100% (2/2)" hits="4" number="167"/> + <line branch="false" hits="1" number="168"/> + <line branch="false" hits="4" number="169"/> + <line branch="false" hits="4" number="176"/> + <line branch="false" hits="4" number="177"/> + <line branch="false" hits="3" number="178"/> + <line branch="false" hits="4" number="184"/> + <line branch="false" hits="4" number="185"/> + <line branch="false" hits="9" number="186"/> + <line branch="false" hits="9" number="187"/> + <line branch="true" condition-coverage="50% (1/2)" hits="2" number="193"/> + <line branch="false" hits="0" number="194"/> + </lines> + </class> + <class branch-rate="0.7272727272727273" complexity="0" filename="src/graphql/router.ts" line-rate="0.9444444444444444" name="src.graphql.router.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="handleApolloClientError" signature=""> + <lines> + <line branch="false" hits="1" number="21"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_8)" signature=""> + <lines> + <line branch="false" hits="1" number="22"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="graphqlRoute" signature=""> + <lines> + <line branch="false" hits="18" number="43"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="11" number="53"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_11)" signature=""> + <lines> + <line branch="false" hits="11" number="53"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="3" number="12"/> + <line branch="false" hits="3" number="14"/> + <line branch="false" hits="1" number="22"/> + <line branch="true" condition-coverage="100% (3/3)" hits="1" number="23"/> + <line branch="true" condition-coverage="50% (1/2)" hits="0" number="26"/> + <line branch="true" condition-coverage="50% (1/2)" hits="1" number="32"/> + <line branch="false" hits="1" number="33"/> + <line branch="false" hits="1" number="34"/> + <line branch="false" hits="0" number="37"/> + <line branch="false" hits="3" number="43"/> + <line branch="false" hits="18" number="53"/> + <line branch="false" hits="11" number="54"/> + <line branch="true" condition-coverage="100% (2/2)" hits="0" number="55"/> + <line branch="false" hits="11" number="57"/> + <line branch="false" hits="11" number="58"/> + <line branch="false" hits="11" number="63"/> + <line branch="false" hits="11" number="64"/> + <line branch="true" condition-coverage="50% (1/2)" hits="10" number="65"/> + <line branch="false" hits="10" number="66"/> + <line branch="false" hits="1" number="68"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/graphql/schema.ts" line-rate="1.0" name="src.graphql.schema.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="getGraphqlSchema" signature=""> + <lines> + <line branch="false" hits="4" number="9"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="3" number="1"/> + <line branch="false" hits="3" number="2"/> + <line branch="false" hits="3" number="4"/> + <line branch="false" hits="3" number="5"/> + <line branch="false" hits="3" number="9"/> + <line branch="true" condition-coverage="0% (0/1)" hits="0" number="11"/> + <line branch="false" hits="4" number="13"/> + <line branch="false" hits="4" number="15"/> + <line branch="false" hits="4" number="16"/> + <line branch="false" hits="4" number="17"/> + <line branch="false" hits="4" number="19"/> + </lines> + </class> + <class branch-rate="0.8333333333333334" complexity="0" filename="src/graphql/transforms.ts" line-rate="0.9" name="src.graphql.transforms.ts"> + <methods> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_0)" signature=""> + <lines> + <line branch="false" hits="6" number="9"/> + </lines> + </method> + <method branch-rate="1.0" line-rate="1.0" name="(anonymous_1)" signature=""> + <lines> + <line branch="false" hits="1" number="20"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="4" number="9"/> + <line branch="true" condition-coverage="100% (2/2)" hits="6" number="13"/> + <line branch="false" hits="2" number="14"/> + <line branch="true" condition-coverage="100% (2/2)" hits="6" number="15"/> + <line branch="false" hits="1" number="16"/> + <line branch="false" hits="6" number="17"/> + <line branch="false" hits="4" number="20"/> + <line branch="true" condition-coverage="50% (1/2)" hits="1" number="23"/> + <line branch="false" hits="0" number="24"/> + <line branch="false" hits="1" number="25"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0.0" complexity="0" line-rate="0.0" name="src.workers"> + <classes> + <class branch-rate="0.0" complexity="0" filename="src/workers/primary-worker.js" line-rate="0.0" name="src.workers.primary-worker.js"> + <methods> + <method branch-rate="0.0" line-rate="0.0" name="doWork" signature=""> + <lines> + <line branch="false" hits="0" number="16"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="0" number="25"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_10)" signature=""> + <lines> + <line branch="false" hits="0" number="49"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="0" number="2"/> + <line branch="false" hits="0" number="3"/> + <line branch="false" hits="0" number="4"/> + <line branch="false" hits="0" number="5"/> + <line branch="false" hits="0" number="6"/> + <line branch="false" hits="0" number="8"/> + <line branch="false" hits="0" number="16"/> + <line branch="true" condition-coverage="0% (0/1)" hits="0" number="17"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="21"/> + <line branch="false" hits="0" number="22"/> + <line branch="false" hits="0" number="23"/> + <line branch="false" hits="0" number="24"/> + <line branch="false" hits="0" number="25"/> + <line branch="false" hits="0" number="27"/> + <line branch="false" hits="0" number="28"/> + <line branch="false" hits="0" number="31"/> + <line branch="false" hits="0" number="33"/> + <line branch="false" hits="0" number="34"/> + <line branch="false" hits="0" number="37"/> + <line branch="false" hits="0" number="38"/> + <line branch="false" hits="0" number="48"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="49"/> + <line branch="false" hits="0" number="51"/> + <line branch="false" hits="0" number="53"/> + </lines> + </class> + <class branch-rate="0.0" complexity="0" filename="src/workers/secondary-worker.js" line-rate="0.0" name="src.workers.secondary-worker.js"> + <methods> + <method branch-rate="0.0" line-rate="0.0" name="doWork" signature=""> + <lines> + <line branch="false" hits="0" number="4"/> + </lines> + </method> + <method branch-rate="0.0" line-rate="0.0" name="(anonymous_9)" signature=""> + <lines> + <line branch="false" hits="0" number="13"/> + </lines> + </method> + </methods> + <lines> + <line branch="false" hits="0" number="2"/> + <line branch="false" hits="0" number="4"/> + <line branch="true" condition-coverage="0% (0/1)" hits="0" number="5"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="9"/> + <line branch="false" hits="0" number="10"/> + <line branch="false" hits="0" number="11"/> + <line branch="false" hits="0" number="12"/> + <line branch="false" hits="0" number="13"/> + <line branch="false" hits="0" number="14"/> + <line branch="false" hits="0" number="15"/> + <line branch="false" hits="0" number="16"/> + <line branch="false" hits="0" number="18"/> + <line branch="false" hits="0" number="19"/> + <line branch="false" hits="0" number="22"/> + <line branch="false" hits="0" number="23"/> + <line branch="true" condition-coverage="0% (0/2)" hits="0" number="24"/> + <line branch="false" hits="0" number="25"/> + <line branch="false" hits="0" number="26"/> + <line branch="false" hits="0" number="27"/> + <line branch="false" hits="0" number="29"/> + </lines> + </class> + </classes> + </package> + </packages> +</coverage> diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-jsoncoverage-files-1.json b/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-jsoncoverage-files-1.json new file mode 100644 index 0000000000..b37f019305 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-jsoncoverage-files-1.json @@ -0,0 +1,319 @@ +[ + { + "filename": "src/main/java/com/example/Main.kt", + "lineHits": { + "28": 0, + "31": 0, + "36": 0, + "37": 0, + "38": 0, + "39": 0, + "40": 0, + "41": 0, + "42": 0, + "43": 0, + "44": 0, + "45": 0, + "46": 0, + "47": 0, + "48": 0, + "49": 0, + "50": 0, + "52": 0, + "53": 0, + "56": 0, + "57": 0, + "58": 0, + "59": 0, + "60": 0, + "62": 0, + "65": 0, + "66": 0, + "67": 0, + "69": 0, + "70": 0, + "71": 0, + "72": 0, + "74": 0, + "76": 0, + "77": 0, + "78": 0, + "79": 0, + "81": 0, + "82": 0, + "83": 0, + "84": 0, + "85": 0, + "86": 0, + "87": 0, + "88": 0, + "89": 0, + "92": 0, + "93": 0 + }, + "branchHits": {} + }, + { + "filename": "src/main/java/com/example/Parser.kt", + "lineHits": { + "5": 9, + "10": 7, + "12": 8, + "13": 2, + "14": 3, + "16": 28, + "17": 1, + "19": 4, + "20": 16, + "21": 18, + "22": 12, + "23": 5, + "24": 14, + "25": 22, + "26": 9, + "28": 7, + "29": 1, + "32": 2, + "34": 13, + "36": 0, + "37": 0, + "38": 0, + "39": 0, + "40": 0, + "43": 7, + "44": 0, + "46": 2, + "49": 7, + "50": 1, + "53": 5, + "54": 3, + "55": 18, + "56": 3, + "57": 1, + "58": 3, + "59": 3, + "60": 5, + "62": 1, + "64": 6, + "65": 2, + "69": 5, + "70": 14, + "71": 8, + "72": 20, + "73": 16, + "74": 22, + "75": 3, + "76": 2, + "77": 19, + "78": 1, + "79": 13, + "80": 5, + "81": 4, + "83": 4, + "84": 12, + "85": 10, + "86": 7, + "87": 9, + "94": 10, + "95": 5, + "96": 4, + "98": 9, + "99": 12, + "100": 10, + "101": 7, + "102": 4, + "103": 9, + "104": 10, + "105": 5, + "106": 10, + "107": 4, + "108": 3, + "109": 2, + "110": 5, + "111": 2, + "113": 1, + "114": 7, + "116": 3, + "117": 12, + "118": 26, + "119": 10, + "120": 7, + "122": 3, + "123": 9, + "124": 14, + "125": 2, + "126": 3 + }, + "branchHits": { + "12": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "16": { + "covered": 2, + "missed": 2, + "available": 4 + }, + "24": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "25": { + "covered": 6, + "missed": 2, + "available": 8 + }, + "38": { + "covered": 0, + "missed": 4, + "available": 4 + }, + "43": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "44": { + "covered": 0, + "missed": 2, + "available": 2 + }, + "55": { + "covered": 4, + "missed": 0, + "available": 4 + }, + "70": { + "covered": 1, + "missed": 3, + "available": 4 + }, + "73": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "75": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "77": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "79": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "85": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "94": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "100": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "104": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "108": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "119": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "124": { + "covered": 2, + "missed": 0, + "available": 2 + } + } + }, + { + "filename": "src/main/java/com/example/models/Thing.kt", + "lineHits": { + "9": 8, + "10": 3, + "11": 0, + "14": 8, + "15": 3, + "16": 1, + "19": 8, + "20": 3, + "21": 0, + "24": 3, + "25": 3, + "26": 1, + "29": 11, + "30": 3, + "31": 3, + "32": 3, + "35": 12, + "36": 12, + "37": 1, + "40": 5, + "41": 3, + "44": 3, + "45": 1, + "48": 12, + "49": 3, + "50": 3, + "51": 0 + }, + "branchHits": { + "14": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "15": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "24": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "25": { + "covered": 1, + "missed": 1, + "available": 2 + }, + "35": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "36": { + "covered": 2, + "missed": 0, + "available": 2 + }, + "44": { + "covered": 1, + "missed": 1, + "available": 2 + } + } + } +] diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-sourcefiles-1.txt b/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-sourcefiles-1.txt new file mode 100644 index 0000000000..84e69b0b4b --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-sourcefiles-1.txt @@ -0,0 +1,7 @@ +pom.xml +src/main/java/com/example/Parser.kt +src/main/java/com/example/Main.kt +src/main/java/com/example/models/Thing.kt +src/main/resources/app.conf +src/test/java/com/example/ParserTest.kt +src/test/resources/logback-test.xml diff --git a/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-testdata-1.xml b/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-testdata-1.xml new file mode 100644 index 0000000000..d07dd81b50 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/__fixtures__/jacoco-testdata-1.xml @@ -0,0 +1,282 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<report name="example"> + <sessioninfo id="743a5357362a-f32e3def" start="1575926125817" dump="1575926133882"/> + <package name="com/example"> + <sourcefile name="Main.kt"> + <line nr="28" mi="6" ci="0" mb="0" cb="0"/> + <line nr="31" mi="7" ci="0" mb="0" cb="0"/> + <line nr="36" mi="3" ci="0" mb="0" cb="0"/> + <line nr="37" mi="12" ci="0" mb="0" cb="0"/> + <line nr="38" mi="2" ci="0" mb="0" cb="0"/> + <line nr="39" mi="2" ci="0" mb="0" cb="0"/> + <line nr="40" mi="5" ci="0" mb="0" cb="0"/> + <line nr="41" mi="5" ci="0" mb="0" cb="0"/> + <line nr="42" mi="3" ci="0" mb="0" cb="0"/> + <line nr="43" mi="3" ci="0" mb="0" cb="0"/> + <line nr="44" mi="3" ci="0" mb="0" cb="0"/> + <line nr="45" mi="3" ci="0" mb="0" cb="0"/> + <line nr="46" mi="3" ci="0" mb="0" cb="0"/> + <line nr="47" mi="4" ci="0" mb="0" cb="0"/> + <line nr="48" mi="4" ci="0" mb="0" cb="0"/> + <line nr="49" mi="4" ci="0" mb="0" cb="0"/> + <line nr="50" mi="1" ci="0" mb="0" cb="0"/> + <line nr="52" mi="8" ci="0" mb="0" cb="0"/> + <line nr="53" mi="19" ci="0" mb="0" cb="0"/> + <line nr="56" mi="1" ci="0" mb="0" cb="0"/> + <line nr="57" mi="8" ci="0" mb="0" cb="0"/> + <line nr="58" mi="1" ci="0" mb="0" cb="0"/> + <line nr="59" mi="24" ci="0" mb="0" cb="0"/> + <line nr="60" mi="2" ci="0" mb="0" cb="0"/> + <line nr="62" mi="1" ci="0" mb="0" cb="0"/> + <line nr="65" mi="5" ci="0" mb="0" cb="0"/> + <line nr="66" mi="5" ci="0" mb="0" cb="0"/> + <line nr="67" mi="3" ci="0" mb="0" cb="0"/> + <line nr="69" mi="1" ci="0" mb="0" cb="0"/> + <line nr="70" mi="1" ci="0" mb="0" cb="0"/> + <line nr="71" mi="1" ci="0" mb="0" cb="0"/> + <line nr="72" mi="7" ci="0" mb="0" cb="0"/> + <line nr="74" mi="2" ci="0" mb="0" cb="0"/> + <line nr="76" mi="3" ci="0" mb="0" cb="0"/> + <line nr="77" mi="7" ci="0" mb="0" cb="0"/> + <line nr="78" mi="5" ci="0" mb="0" cb="0"/> + <line nr="79" mi="5" ci="0" mb="0" cb="0"/> + <line nr="81" mi="1" ci="0" mb="0" cb="0"/> + <line nr="82" mi="1" ci="0" mb="0" cb="0"/> + <line nr="83" mi="2" ci="0" mb="0" cb="0"/> + <line nr="84" mi="9" ci="0" mb="0" cb="0"/> + <line nr="85" mi="3" ci="0" mb="0" cb="0"/> + <line nr="86" mi="1" ci="0" mb="0" cb="0"/> + <line nr="87" mi="3" ci="0" mb="0" cb="0"/> + <line nr="88" mi="1" ci="0" mb="0" cb="0"/> + <line nr="89" mi="6" ci="0" mb="0" cb="0"/> + <line nr="92" mi="6" ci="0" mb="0" cb="0"/> + <line nr="93" mi="1" ci="0" mb="0" cb="0"/> + <counter type="INSTRUCTION" missed="219" covered="0"/> + <counter type="LINE" missed="48" covered="0"/> + <counter type="COMPLEXITY" missed="8" covered="0"/> + <counter type="METHOD" missed="8" covered="0"/> + <counter type="CLASS" missed="6" covered="0"/> + </sourcefile> + <sourcefile name="Parser.kt"> + <line nr="5" mi="0" ci="9" mb="0" cb="0"/> + <line nr="10" mi="0" ci="7" mb="0" cb="0"/> + <line nr="12" mi="1" ci="8" mb="1" cb="1"/> + <line nr="13" mi="0" ci="2" mb="0" cb="0"/> + <line nr="14" mi="0" ci="3" mb="0" cb="0"/> + <line nr="16" mi="2" ci="28" mb="2" cb="2"/> + <line nr="17" mi="0" ci="1" mb="0" cb="0"/> + <line nr="19" mi="0" ci="4" mb="0" cb="0"/> + <line nr="20" mi="0" ci="16" mb="0" cb="0"/> + <line nr="21" mi="0" ci="18" mb="0" cb="0"/> + <line nr="22" mi="0" ci="12" mb="0" cb="0"/> + <line nr="23" mi="0" ci="5" mb="0" cb="0"/> + <line nr="24" mi="0" ci="14" mb="0" cb="2"/> + <line nr="25" mi="1" ci="22" mb="2" cb="6"/> + <line nr="26" mi="0" ci="9" mb="0" cb="0"/> + <line nr="28" mi="0" ci="7" mb="0" cb="0"/> + <line nr="29" mi="0" ci="1" mb="0" cb="0"/> + <line nr="32" mi="0" ci="2" mb="0" cb="0"/> + <line nr="34" mi="0" ci="13" mb="0" cb="0"/> + <line nr="36" mi="2" ci="0" mb="0" cb="0"/> + <line nr="37" mi="9" ci="0" mb="0" cb="0"/> + <line nr="38" mi="37" ci="0" mb="4" cb="0"/> + <line nr="39" mi="3" ci="0" mb="0" cb="0"/> + <line nr="40" mi="1" ci="0" mb="0" cb="0"/> + <line nr="43" mi="0" ci="7" mb="1" cb="1"/> + <line nr="44" mi="20" ci="0" mb="2" cb="0"/> + <line nr="46" mi="0" ci="2" mb="0" cb="0"/> + <line nr="49" mi="0" ci="7" mb="0" cb="0"/> + <line nr="50" mi="0" ci="1" mb="0" cb="0"/> + <line nr="53" mi="0" ci="5" mb="0" cb="0"/> + <line nr="54" mi="0" ci="3" mb="0" cb="0"/> + <line nr="55" mi="0" ci="18" mb="0" cb="4"/> + <line nr="56" mi="0" ci="3" mb="0" cb="0"/> + <line nr="57" mi="0" ci="1" mb="0" cb="0"/> + <line nr="58" mi="0" ci="3" mb="0" cb="0"/> + <line nr="59" mi="0" ci="3" mb="0" cb="0"/> + <line nr="60" mi="0" ci="5" mb="0" cb="0"/> + <line nr="62" mi="0" ci="1" mb="0" cb="0"/> + <line nr="64" mi="0" ci="6" mb="0" cb="0"/> + <line nr="65" mi="0" ci="2" mb="0" cb="0"/> + <line nr="69" mi="2" ci="5" mb="0" cb="0"/> + <line nr="70" mi="17" ci="14" mb="3" cb="1"/> + <line nr="71" mi="1" ci="8" mb="0" cb="0"/> + <line nr="72" mi="0" ci="20" mb="0" cb="0"/> + <line nr="73" mi="0" ci="16" mb="0" cb="2"/> + <line nr="74" mi="0" ci="22" mb="0" cb="0"/> + <line nr="75" mi="2" ci="3" mb="1" cb="1"/> + <line nr="76" mi="0" ci="2" mb="0" cb="0"/> + <line nr="77" mi="0" ci="19" mb="0" cb="2"/> + <line nr="78" mi="0" ci="1" mb="0" cb="0"/> + <line nr="79" mi="0" ci="13" mb="0" cb="2"/> + <line nr="80" mi="0" ci="5" mb="0" cb="0"/> + <line nr="81" mi="0" ci="4" mb="0" cb="0"/> + <line nr="83" mi="0" ci="4" mb="0" cb="0"/> + <line nr="84" mi="0" ci="12" mb="0" cb="0"/> + <line nr="85" mi="0" ci="10" mb="0" cb="2"/> + <line nr="86" mi="0" ci="7" mb="0" cb="0"/> + <line nr="87" mi="0" ci="9" mb="0" cb="0"/> + <line nr="94" mi="0" ci="10" mb="0" cb="2"/> + <line nr="95" mi="0" ci="5" mb="0" cb="0"/> + <line nr="96" mi="0" ci="4" mb="0" cb="0"/> + <line nr="98" mi="0" ci="9" mb="0" cb="0"/> + <line nr="99" mi="0" ci="12" mb="0" cb="0"/> + <line nr="100" mi="0" ci="10" mb="0" cb="2"/> + <line nr="101" mi="0" ci="7" mb="0" cb="0"/> + <line nr="102" mi="0" ci="4" mb="0" cb="0"/> + <line nr="103" mi="0" ci="9" mb="0" cb="0"/> + <line nr="104" mi="0" ci="10" mb="0" cb="2"/> + <line nr="105" mi="0" ci="5" mb="0" cb="0"/> + <line nr="106" mi="0" ci="10" mb="0" cb="0"/> + <line nr="107" mi="0" ci="4" mb="0" cb="0"/> + <line nr="108" mi="0" ci="3" mb="0" cb="2"/> + <line nr="109" mi="0" ci="2" mb="0" cb="0"/> + <line nr="110" mi="0" ci="5" mb="0" cb="0"/> + <line nr="111" mi="0" ci="2" mb="0" cb="0"/> + <line nr="113" mi="0" ci="1" mb="0" cb="0"/> + <line nr="114" mi="0" ci="7" mb="0" cb="0"/> + <line nr="116" mi="0" ci="3" mb="0" cb="0"/> + <line nr="117" mi="0" ci="12" mb="0" cb="0"/> + <line nr="118" mi="0" ci="26" mb="0" cb="0"/> + <line nr="119" mi="0" ci="10" mb="0" cb="2"/> + <line nr="120" mi="0" ci="7" mb="0" cb="0"/> + <line nr="122" mi="0" ci="3" mb="0" cb="0"/> + <line nr="123" mi="0" ci="9" mb="0" cb="0"/> + <line nr="124" mi="0" ci="14" mb="0" cb="2"/> + <line nr="125" mi="0" ci="2" mb="0" cb="0"/> + <line nr="126" mi="0" ci="3" mb="0" cb="0"/> + <counter type="INSTRUCTION" missed="98" covered="642"/> + <counter type="BRANCH" missed="16" covered="38"/> + <counter type="LINE" missed="6" covered="81"/> + <counter type="COMPLEXITY" missed="15" covered="20"/> + <counter type="METHOD" missed="3" covered="5"/> + <counter type="CLASS" missed="2" covered="2"/> + </sourcefile> + </package> + <package name="com/example/models"> + <sourcefile name="Thing.kt"> + <line nr="9" mi="0" ci="8" mb="0" cb="0"/> + <line nr="10" mi="4" ci="3" mb="0" cb="0"/> + <line nr="11" mi="3" ci="0" mb="0" cb="0"/> + <line nr="14" mi="0" ci="8" mb="0" cb="2"/> + <line nr="15" mi="9" ci="3" mb="1" cb="1"/> + <line nr="16" mi="0" ci="1" mb="0" cb="0"/> + <line nr="19" mi="0" ci="8" mb="0" cb="0"/> + <line nr="20" mi="4" ci="3" mb="0" cb="0"/> + <line nr="21" mi="3" ci="0" mb="0" cb="0"/> + <line nr="24" mi="5" ci="3" mb="1" cb="1"/> + <line nr="25" mi="9" ci="3" mb="1" cb="1"/> + <line nr="26" mi="0" ci="1" mb="0" cb="0"/> + <line nr="29" mi="0" ci="11" mb="0" cb="0"/> + <line nr="30" mi="0" ci="3" mb="0" cb="0"/> + <line nr="31" mi="4" ci="3" mb="0" cb="0"/> + <line nr="32" mi="4" ci="3" mb="0" cb="0"/> + <line nr="35" mi="0" ci="12" mb="0" cb="2"/> + <line nr="36" mi="0" ci="12" mb="0" cb="2"/> + <line nr="37" mi="0" ci="1" mb="0" cb="0"/> + <line nr="40" mi="0" ci="5" mb="0" cb="0"/> + <line nr="41" mi="4" ci="3" mb="0" cb="0"/> + <line nr="44" mi="9" ci="3" mb="1" cb="1"/> + <line nr="45" mi="0" ci="1" mb="0" cb="0"/> + <line nr="48" mi="0" ci="12" mb="0" cb="0"/> + <line nr="49" mi="0" ci="3" mb="0" cb="0"/> + <line nr="50" mi="0" ci="3" mb="0" cb="0"/> + <line nr="51" mi="3" ci="0" mb="0" cb="0"/> + <counter type="INSTRUCTION" missed="61" covered="119"/> + <counter type="BRANCH" missed="4" covered="10"/> + <counter type="LINE" missed="3" covered="24"/> + <counter type="COMPLEXITY" missed="12" covered="16"/> + <counter type="METHOD" missed="8" covered="13"/> + <counter type="CLASS" missed="0" covered="5"/> + </sourcefile> + </package> + <package name="com/example/generated"> + <sourcefile name="Untracked.kt"> + <line nr="12" mi="8" ci="0" mb="0" cb="0"/> + <line nr="17" mi="6" ci="0" mb="0" cb="0"/> + <line nr="20" mi="8" ci="0" mb="0" cb="0"/> + <line nr="21" mi="2" ci="0" mb="0" cb="0"/> + <line nr="22" mi="3" ci="0" mb="0" cb="0"/> + <line nr="23" mi="4" ci="0" mb="0" cb="0"/> + <line nr="24" mi="13" ci="0" mb="0" cb="0"/> + <line nr="27" mi="7" ci="0" mb="0" cb="0"/> + <line nr="28" mi="5" ci="0" mb="4" cb="0"/> + <line nr="29" mi="19" ci="0" mb="0" cb="0"/> + <line nr="30" mi="4" ci="0" mb="0" cb="0"/> + <line nr="31" mi="3" ci="0" mb="0" cb="0"/> + <line nr="32" mi="1" ci="0" mb="0" cb="0"/> + <line nr="33" mi="1" ci="0" mb="0" cb="0"/> + <line nr="34" mi="2" ci="0" mb="0" cb="0"/> + <line nr="35" mi="2" ci="0" mb="0" cb="0"/> + <line nr="39" mi="23" ci="0" mb="0" cb="0"/> + <line nr="40" mi="3" ci="0" mb="0" cb="0"/> + <line nr="41" mi="3" ci="0" mb="0" cb="0"/> + <line nr="42" mi="1" ci="0" mb="0" cb="0"/> + <line nr="43" mi="5" ci="0" mb="0" cb="0"/> + <line nr="44" mi="3" ci="0" mb="2" cb="0"/> + <line nr="45" mi="21" ci="0" mb="0" cb="0"/> + <line nr="46" mi="13" ci="0" mb="0" cb="0"/> + <line nr="48" mi="1" ci="0" mb="0" cb="0"/> + <line nr="51" mi="9" ci="0" mb="0" cb="0"/> + <line nr="52" mi="2" ci="0" mb="0" cb="0"/> + <line nr="53" mi="3" ci="0" mb="0" cb="0"/> + <line nr="54" mi="4" ci="0" mb="0" cb="0"/> + <line nr="55" mi="13" ci="0" mb="0" cb="0"/> + <line nr="58" mi="7" ci="0" mb="0" cb="0"/> + <line nr="59" mi="5" ci="0" mb="4" cb="0"/> + <line nr="60" mi="19" ci="0" mb="0" cb="0"/> + <line nr="61" mi="4" ci="0" mb="0" cb="0"/> + <line nr="62" mi="3" ci="0" mb="0" cb="0"/> + <line nr="63" mi="1" ci="0" mb="0" cb="0"/> + <line nr="64" mi="1" ci="0" mb="0" cb="0"/> + <line nr="65" mi="2" ci="0" mb="0" cb="0"/> + <line nr="66" mi="2" ci="0" mb="0" cb="0"/> + <line nr="70" mi="23" ci="0" mb="0" cb="0"/> + <line nr="71" mi="1" ci="0" mb="0" cb="0"/> + <line nr="72" mi="2" ci="0" mb="0" cb="0"/> + <line nr="73" mi="3" ci="0" mb="0" cb="0"/> + <line nr="74" mi="1" ci="0" mb="0" cb="0"/> + <line nr="75" mi="5" ci="0" mb="0" cb="0"/> + <line nr="76" mi="3" ci="0" mb="2" cb="0"/> + <line nr="77" mi="21" ci="0" mb="0" cb="0"/> + <line nr="78" mi="13" ci="0" mb="0" cb="0"/> + <line nr="80" mi="1" ci="0" mb="0" cb="0"/> + <line nr="82" mi="1" ci="0" mb="0" cb="0"/> + <line nr="84" mi="15" ci="0" mb="0" cb="0"/> + <line nr="87" mi="1" ci="5" mb="0" cb="0"/> + <line nr="89" mi="0" ci="5" mb="0" cb="0"/> + <line nr="90" mi="0" ci="6" mb="0" cb="0"/> + <line nr="91" mi="0" ci="8" mb="0" cb="0"/> + <line nr="92" mi="0" ci="8" mb="0" cb="0"/> + <line nr="93" mi="0" ci="8" mb="0" cb="0"/> + <line nr="94" mi="0" ci="8" mb="0" cb="0"/> + <line nr="95" mi="0" ci="8" mb="0" cb="0"/> + <line nr="96" mi="0" ci="8" mb="0" cb="0"/> + <line nr="97" mi="0" ci="8" mb="0" cb="0"/> + <line nr="98" mi="0" ci="8" mb="0" cb="0"/> + <line nr="99" mi="0" ci="8" mb="0" cb="0"/> + <line nr="100" mi="0" ci="9" mb="0" cb="0"/> + <line nr="101" mi="0" ci="8" mb="0" cb="0"/> + <line nr="102" mi="0" ci="8" mb="0" cb="0"/> + <line nr="103" mi="0" ci="7" mb="0" cb="0"/> + <line nr="107" mi="2" ci="8" mb="0" cb="0"/> + <line nr="108" mi="0" ci="8" mb="0" cb="0"/> + <line nr="109" mi="0" ci="8" mb="0" cb="0"/> + <line nr="110" mi="0" ci="3" mb="0" cb="0"/> + <line nr="113" mi="2" ci="9" mb="0" cb="0"/> + <line nr="114" mi="0" ci="8" mb="0" cb="0"/> + <line nr="115" mi="0" ci="8" mb="0" cb="0"/> + <line nr="116" mi="0" ci="8" mb="0" cb="0"/> + <line nr="117" mi="0" ci="8" mb="0" cb="0"/> + <line nr="118" mi="0" ci="8" mb="0" cb="0"/> + <line nr="119" mi="0" ci="8" mb="0" cb="0"/> + <line nr="120" mi="0" ci="3" mb="0" cb="0"/> + <counter type="INSTRUCTION" missed="345" covered="212"/> + <counter type="BRANCH" missed="12" covered="0"/> + <counter type="LINE" missed="51" covered="28"/> + <counter type="COMPLEXITY" missed="19" covered="1"/> + <counter type="METHOD" missed="13" covered="1"/> + <counter type="CLASS" missed="9" covered="1"/> + </sourcefile> + </package> +</report> diff --git a/plugins/code-coverage-backend/src/service/converter/cobertura.test.ts b/plugins/code-coverage-backend/src/service/converter/cobertura.test.ts new file mode 100644 index 0000000000..72d4018f94 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/converter/cobertura.test.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { parseString } from 'xml2js'; +import fs from 'fs'; +import { Cobertura } from './cobertura'; +import { CoberturaXML } from './types'; +import { getVoidLogger } from '@backstage/backend-common'; + +/* eslint-disable no-restricted-syntax */ + +describe('convert cobertura', () => { + const converter = new Cobertura(getVoidLogger()); + [1, 2, 3, 4, 5].forEach(idx => { + let fixture: CoberturaXML; + parseString( + fs.readFileSync( + `${__dirname}/../__fixtures__/cobertura-testdata-${idx}.xml`, + ), + (_e, r) => { + fixture = r; + }, + ); + const expected = JSON.parse( + fs + .readFileSync( + `${__dirname}/../__fixtures__/cobertura-jsoncoverage-files-${idx}.json`, + ) + .toString(), + ); + const scmFiles = fs + .readFileSync( + `${__dirname}/../__fixtures__/cobertura-sourcefiles-${idx}.txt`, + ) + .toString() + .split('\n'); + + it(`${idx} converts a cobertura report`, () => { + const files = converter.convert(fixture, scmFiles); + + expect(files).toEqual(expected); + }); + }); +}); diff --git a/plugins/code-coverage-backend/src/service/converter/cobertura.ts b/plugins/code-coverage-backend/src/service/converter/cobertura.ts new file mode 100644 index 0000000000..72eeb25b56 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/converter/cobertura.ts @@ -0,0 +1,126 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { BranchHit, FileEntry } from '../jsoncoverage-types'; +import { CoberturaXML, InnerClass, LineHit } from './types'; +import { Logger } from 'winston'; +import { Converter } from '.'; + +export class Cobertura extends Converter { + constructor(readonly logger: Logger) { + super(logger); + } + + /** + * convert cobertura into shared json coverage format + * + * @param xml cobertura xml object + * @param scmFiles list of files that are commited to SCM + */ + convert(xml: CoberturaXML, scmFiles: string[]): FileEntry[] { + const ppc = xml.coverage.packages + ?.flatMap(p => p.package) + .filter(Boolean) + .flatMap(p => p.classes); + const pc = xml.coverage.package?.filter(Boolean).flatMap(p => p.classes); + + const classes = [ppc, pc] + .flat() + .filter(Boolean) + .flatMap(c => c.class) + .filter(Boolean); + const jscov: Array<FileEntry> = []; + + classes.forEach(c => { + const packageAndFilename = c.$.filename; + const lines = this.extractLines(c); + const lineHits: Record<number, number> = {}; + const branchHits: Record<number, BranchHit> = {}; + + lines.forEach(l => { + if (!lineHits[l.number]) { + lineHits[l.number] = 0; + } + lineHits[l.number] += l.hits; + if (l.branch && l['condition-coverage']) { + const bh = this.parseBranch(l['condition-coverage']); + if (bh) { + branchHits[l.number] = bh; + } + } + }); + + const currentFile = scmFiles.find(f => f.endsWith(packageAndFilename)); + this.logger.info(`matched ${packageAndFilename} to ${currentFile}`); + if ( + scmFiles.length === 0 || + (Object.keys(lineHits).length > 0 && currentFile) + ) { + jscov.push({ + filename: currentFile || packageAndFilename, + branchHits: branchHits, + lineHits: lineHits, + }); + } + }); + + return jscov; + } + + /** + * Parses branch coverage information from condition-coverage + * + * @param condition condition-coverage value from line coverage + */ + private parseBranch(condition: string): BranchHit | null { + const pattern = /[0-9\.]+\%\s\(([0-9]+)\/([0-9]+)\)/; + const match = condition.match(pattern); + if (!match) { + return null; + } + const covered = parseInt(match[1], 10); + const available = parseInt(match[2], 10); + return { + covered: covered, + missed: available - covered, + available: available, + }; + } + + /** + * Extract line hits from a class coverage entry + * + * @param clz class coverage information + */ + private extractLines(clz: InnerClass): Array<LineHit> { + const classLines = clz.lines.flatMap(l => l.line); + const methodLines = clz.methods + ?.flatMap(m => m.method) + .filter(Boolean) + .flatMap(m => m.lines) + .filter(Boolean) + .flatMap(l => l.line); + const lines = [classLines, methodLines].flat().filter(Boolean); + const lineHits = lines.map(l => { + return { + number: parseInt((l.$.number as unknown) as string, 10), + hits: parseInt((l.$.hits as unknown) as string, 10), + 'condition-coverage': l.$['condition-coverage'], + branch: l.$.branch, + }; + }); + return lineHits; + } +} diff --git a/plugins/code-coverage-backend/src/service/converter/index.ts b/plugins/code-coverage-backend/src/service/converter/index.ts new file mode 100644 index 0000000000..083af10f68 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/converter/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { Logger } from 'winston'; +import { FileEntry } from '../jsoncoverage-types'; + +export abstract class Converter { + constructor(readonly logger: Logger) {} + + abstract convert(xml: any, scmFiles: Array<string>): Array<FileEntry>; +} diff --git a/plugins/code-coverage-backend/src/service/converter/jacoco.test.ts b/plugins/code-coverage-backend/src/service/converter/jacoco.test.ts new file mode 100644 index 0000000000..48202748da --- /dev/null +++ b/plugins/code-coverage-backend/src/service/converter/jacoco.test.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { parseString } from 'xml2js'; +import fs from 'fs'; +import { Jacoco } from './jacoco'; +import { JacocoXML } from './types'; +import { getVoidLogger } from '@backstage/backend-common'; + +/* eslint-disable no-restricted-syntax */ + +describe('convert jacoco', () => { + const converter = new Jacoco(getVoidLogger()); + let fixture: JacocoXML; + parseString( + fs.readFileSync(`${__dirname}/../__fixtures__/jacoco-testdata-1.xml`), + (_e, r) => { + fixture = r; + }, + ); + const expected = JSON.parse( + fs + .readFileSync( + `${__dirname}/../__fixtures__/jacoco-jsoncoverage-files-1.json`, + ) + .toString(), + ); + const scmFiles = fs + .readFileSync(`${__dirname}/../__fixtures__/jacoco-sourcefiles-1.txt`) + .toString() + .split('\n'); + + it('converts a jacoco report', () => { + const files = converter.convert(fixture, scmFiles); + + expect(files.sort()).toEqual(expected.sort()); + }); +}); diff --git a/plugins/code-coverage-backend/src/service/converter/jacoco.ts b/plugins/code-coverage-backend/src/service/converter/jacoco.ts new file mode 100644 index 0000000000..fe60f9378c --- /dev/null +++ b/plugins/code-coverage-backend/src/service/converter/jacoco.ts @@ -0,0 +1,96 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { BranchHit, FileEntry } from '../jsoncoverage-types'; +import { JacocoSourceFile, JacocoXML } from './types'; +import { Logger } from 'winston'; +import { Converter } from '.'; + +type ParsedLine = { + number: number; + missed_instructions: number; + covered_instructions: number; + missed_branches: number; + covered_branches: number; +}; + +export class Jacoco extends Converter { + constructor(readonly logger: Logger) { + super(logger); + } + + /** + * Converts jacoco into shared json coverage format + * + * @param xml jacoco xml object + * @param scmFiles list of files that are commited to SCM + */ + convert(xml: JacocoXML, scmFiles: Array<string>): Array<FileEntry> { + const jscov: Array<FileEntry> = []; + + xml.report.package.forEach(r => { + const packageName = r.$.name; + r.sourcefile.forEach(sf => { + const fileName = sf.$.name; + const lines = this.extractLines(sf); + const lineHits: Record<number, number> = {}; + const branchHits: Record<number, BranchHit> = {}; + lines.forEach(l => { + if (!lineHits[l.number]) { + lineHits[l.number] = 0; + } + lineHits[l.number] += l.covered_instructions; + const ab = l.covered_branches + l.missed_branches; + if (ab > 0) { + branchHits[l.number] = { + covered: l.covered_branches, + missed: l.missed_branches, + available: ab, + }; + } + }); + + const packageAndFilename = `${packageName}/${fileName}`; + const currentFile = scmFiles.find(f => f.endsWith(packageAndFilename)); + this.logger.info(`matched ${packageAndFilename} to ${currentFile}`); + if (Object.keys(lineHits).length > 0 && currentFile) { + jscov.push({ + filename: currentFile, + branchHits: branchHits, + lineHits: lineHits, + }); + } + }); + }); + + return jscov; + } + + private extractLines(sourcefile: JacocoSourceFile): ParsedLine[] { + const parsed: ParsedLine[] = []; + + sourcefile.line.forEach(l => { + parsed.push({ + number: parseInt(l.$.nr, 10), + missed_instructions: parseInt(l.$.mi, 10), + covered_instructions: parseInt(l.$.ci, 10), + missed_branches: parseInt(l.$.mb, 10), + covered_branches: parseInt(l.$.cb, 10), + }); + }); + + return parsed; + } +} diff --git a/plugins/code-coverage-backend/src/service/converter/types.ts b/plugins/code-coverage-backend/src/service/converter/types.ts new file mode 100644 index 0000000000..35e70faae4 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/converter/types.ts @@ -0,0 +1,92 @@ +/* + * Copyright 2021 Spotify AB + * + * 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. + */ + +// *** Cobertura *** +export type CoberturaXML = { + coverage: Coverage; +}; + +export type Coverage = { + packages: Array<Package>; + package: Array<InnerPackage>; +}; + +export type Package = { + package: Array<InnerPackage>; +}; + +export type InnerPackage = { + classes: Array<Class>; +}; +export type Class = { + class: Array<InnerClass>; +}; +export type InnerClass = { + $: { + filename: string; + }; + lines: Array<Line>; + methods: Array<Method>; +}; +export type Method = { + method: Array<InnerMethod>; +}; +export type InnerMethod = { + lines: Array<Line>; +}; +export type Line = { + line: Array<InnerLine>; +}; + +export type InnerLine = { + $: LineHit; +}; + +export type LineHit = { + branch?: boolean; + 'condition-coverage'?: string; + number: number; + hits: number; +}; + +// *** Jacoco *** +export type JacocoXML = { + report: JacocoReport; +}; +export type JacocoReport = { + package: JacocoPackage[]; +}; +export type JacocoPackage = { + $: { + name: string; + }; + sourcefile: JacocoSourceFile[]; +}; +export type JacocoSourceFile = { + $: { + name: string; + }; + line: JacocoLine[]; +}; +export type JacocoLine = { + $: { + nr: string; + mi: string; + ci: string; + mb: string; + cb: string; + }; +}; diff --git a/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts b/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts new file mode 100644 index 0000000000..f1ef3dd694 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { EntityName } from '@backstage/catalog-model'; + +export type JsonCodeCoverage = { + metadata: CoverageMetadata; + entity: EntityName; + files: Array<FileEntry>; +}; + +export type JsonCoverageHistory = { + entity: EntityName; + history: Array<CoverageHistory>; +}; + +export type CoverageHistory = { + line: { + available: number; + covered: number; + }; + branch: BranchHit; +}; + +export type CoverageMetadata = { + vcs: { + type: string; + location: string; + }; + generationTime: number; +}; + +export type BranchHit = { + covered: number; + missed: number; + available: number; +}; + +export type FileEntry = { + filename: string; + lineHits: Record<number, number>; + branchHits: Record<number, BranchHit>; +}; + +export type AggregateCoverage = { + timestamp: number; + line: { + available: number; + covered: number; + missed: number; + percentage: number; + }; + branch: { + available: number; + covered: number; + missed: number; + percentage: number; + }; +}; diff --git a/plugins/code-coverage-backend/src/service/router.test.ts b/plugins/code-coverage-backend/src/service/router.test.ts new file mode 100644 index 0000000000..e18cd75c2f --- /dev/null +++ b/plugins/code-coverage-backend/src/service/router.test.ts @@ -0,0 +1,79 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 express from 'express'; +import request from 'supertest'; +import { + getVoidLogger, + PluginDatabaseManager, + PluginEndpointDiscovery, + SingleConnectionDatabaseManager, + UrlReaders, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { createRouter } from './router'; + +function createDatabase(): PluginDatabaseManager { + return SingleConnectionDatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'sqlite3', + connection: ':memory:', + }, + }, + }), + ).forPlugin('code-coverage'); +} + +const testDiscovery: jest.Mocked<PluginEndpointDiscovery> = { + getBaseUrl: jest + .fn() + .mockResolvedValue('http://localhost:7000/api/code-coverage'), + getExternalBaseUrl: jest.fn(), +}; +const mockUrlReader = UrlReaders.default({ + logger: getVoidLogger(), + config: new ConfigReader({}), +}); + +describe('createRouter', () => { + let app: express.Express; + + beforeAll(async () => { + const router = await createRouter({ + config: new ConfigReader({}), + database: createDatabase(), + discovery: testDiscovery, + urlReader: mockUrlReader, + logger: getVoidLogger(), + }); + app = express().use(router); + }); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('GET /health', () => { + it('returns ok', async () => { + const response = await request(app).get('/health'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ status: 'ok' }); + }); + }); +}); diff --git a/plugins/code-coverage-backend/src/service/router.ts b/plugins/code-coverage-backend/src/service/router.ts new file mode 100644 index 0000000000..3f3dcf8a1e --- /dev/null +++ b/plugins/code-coverage-backend/src/service/router.ts @@ -0,0 +1,229 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 express from 'express'; +import Router from 'express-promise-router'; +import { Logger } from 'winston'; +import xmlparser from 'express-xml-bodyparser'; +import { CatalogClient } from '@backstage/catalog-client'; +import { + errorHandler, + PluginDatabaseManager, + PluginEndpointDiscovery, + UrlReader, +} from '@backstage/backend-common'; +import { InputError, NotFoundError } from '@backstage/errors'; +import { Config } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; +import { CodeCoverageDatabase } from './CodeCoverageDatabase'; +import { aggregateCoverage, CoverageUtils } from './CoverageUtils'; +import { Cobertura } from './converter/cobertura'; +import { Jacoco } from './converter/jacoco'; +import { Converter } from './converter'; + +export interface RouterOptions { + config: Config; + discovery: PluginEndpointDiscovery; + database: PluginDatabaseManager; + urlReader: UrlReader; + logger: Logger; +} + +export interface CodeCoverageApi { + name: string; +} + +export const makeRouter = async ( + options: RouterOptions, +): Promise<express.Router> => { + const { config, logger, discovery, database, urlReader } = options; + + const codeCoverageDatabase = await CodeCoverageDatabase.create( + await database.getClient(), + logger, + ); + const codecovUrl = await discovery.getExternalBaseUrl('code-coverage'); + const catalogApi = new CatalogClient({ discoveryApi: discovery }); + const scm = ScmIntegrations.fromConfig(config); + + const router = Router(); + router.use(xmlparser()); + router.use(express.json()); + + const utils = new CoverageUtils(scm, urlReader); + + router.get('/health', async (_req, res) => { + res.status(200).json({ status: 'ok' }); + }); + + router.get('/:kind/:namespace/:name', async (req, res) => { + const { kind, namespace, name } = req.params; + const entity = await catalogApi.getEntityByName({ kind, namespace, name }); + if (!entity) { + throw new NotFoundError( + `No entity found matching ${kind}/${namespace}/${name}`, + ); + } + const stored = await codeCoverageDatabase.getCodeCoverage({ + kind, + namespace, + name, + }); + + const aggregate = aggregateCoverage(stored); + + res.status(200).json({ + ...stored, + aggregate: { + line: aggregate.line, + branch: aggregate.branch, + }, + }); + }); + + router.get('/:kind/:namespace/:name/history', async (req, res) => { + const { kind, namespace, name } = req.params; + const entity = await catalogApi.getEntityByName({ kind, namespace, name }); + if (!entity) { + throw new NotFoundError( + `No entity found matching ${kind}/${namespace}/${name}`, + ); + } + const { limit } = req.query; + const history = await codeCoverageDatabase.getHistory( + { + kind, + namespace, + name, + }, + parseInt(limit?.toString() || '10', 10), + ); + + res.status(200).json(history); + }); + + router.get('/:kind/:namespace/:name/file-content', async (req, res) => { + const { kind, namespace, name } = req.params; + const entity = await catalogApi.getEntityByName({ kind, namespace, name }); + if (!entity) { + throw new NotFoundError( + `No entity found matching ${kind}/${namespace}/${name}`, + ); + } + const { path } = req.query; + if (!path) { + throw new InputError('Need path query parameter'); + } + + const sourceLocation = + entity.metadata.annotations?.['backstage.io/source-location']; + if (!sourceLocation) { + throw new InputError( + `No "backstage.io/source-location" annotation on entity ${entity.kind}/${entity.metadata.namespace}/${entity.metadata.name}`, + ); + } + + const vcs = scm.byUrl(sourceLocation); + if (!vcs) { + throw new InputError(`Unable to determine SCM from ${sourceLocation}`); + } + + const scmTree = await urlReader.readTree(sourceLocation); + const scmFile = (await scmTree.files()).find(f => f.path === path); + if (!scmFile) { + res.status(400).json({ + message: "couldn't find file in SCM", + file: path, + scm: vcs.title, + }); + return; + } + const content = await scmFile?.content(); + if (!content) { + res.status(400).json({ + message: "couldn't process content of file in SCM", + file: path, + scm: vcs.title, + }); + return; + } + + const data = content.toString(); + res.status(200).contentType('text/plain').send(data); + }); + + router.post('/:kind/:namespace/:name/', async (req, res) => { + const { kind, namespace, name } = req.params; + const { coverageType } = req.query; + let converter: Converter; + if (!coverageType) { + throw new InputError('Need coverageType query parameter'); + } else if (coverageType === 'jacoco') { + converter = new Jacoco(logger); + } else if (coverageType === 'cobertura') { + converter = new Cobertura(logger); + } else { + throw new NotFoundError(`unsupported coverage type '${coverageType}`); + } + const entity = await catalogApi.getEntityByName({ kind, namespace, name }); + if (!entity) { + throw new NotFoundError( + `No entity found matching ${kind}/${namespace}/${name}`, + ); + } + const { + sourceLocation, + vcs, + scmFiles, + body, + } = await utils.processCoveragePayload(entity, req); + + const files = converter.convert(body, scmFiles); + if (!files || files.length === 0) { + throw new InputError(`Unable to parse body as ${coverageType}`); + } + + const coverage = await utils.buildCoverage( + entity, + sourceLocation, + vcs, + files, + ); + await codeCoverageDatabase.insertCodeCoverage(coverage); + + res.status(201).json({ + links: [ + { + rel: 'coverage', + href: `${codecovUrl}/${kind}/${namespace}/${name}`, + }, + ], + }); + }); + + router.use(errorHandler()); + return router; +}; + +export async function createRouter( + options: RouterOptions, +): Promise<express.Router> { + const logger = options.logger; + + logger.info('Initializing Code Coverage backend'); + + return makeRouter(options); +} diff --git a/plugins/code-coverage-backend/src/service/standaloneServer.ts b/plugins/code-coverage-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..8a3c4eaea1 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/standaloneServer.ts @@ -0,0 +1,64 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { + createServiceBuilder, + loadBackendConfig, + SingleHostDiscovery, + UrlReaders, + useHotMemoize, +} from '@backstage/backend-common'; +import { Server } from 'http'; +import { Logger } from 'winston'; +import { createRouter } from './router'; +import { DatabaseManager } from '@backstage/plugin-catalog-backend'; + +export interface ServerOptions { + port: number; + enableCors: boolean; + logger: Logger; +} + +export async function startStandaloneServer( + options: ServerOptions, +): Promise<Server> { + const logger = options.logger.child({ service: 'code-coverage-backend' }); + const config = await loadBackendConfig({ logger, argv: process.argv }); + + const db = useHotMemoize(module, () => + DatabaseManager.createInMemoryDatabaseConnection(), + ); + + logger.debug('Starting application server...'); + const router = await createRouter({ + database: { getClient: () => db }, + config, + discovery: SingleHostDiscovery.fromConfig(config), + urlReader: UrlReaders.default({ logger, config }), + logger, + }); + + const service = createServiceBuilder(module) + .enableCors({ origin: 'http://localhost:3000' }) + .addRouter('/code-coverage', router); + + return await service.start().catch(err => { + logger.error(err); + process.exit(1); + }); +} + +module.hot?.accept(); diff --git a/plugins/code-coverage-backend/src/setupTests.ts b/plugins/code-coverage-backend/src/setupTests.ts new file mode 100644 index 0000000000..ba33cf996b --- /dev/null +++ b/plugins/code-coverage-backend/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export {}; diff --git a/plugins/code-coverage/.eslintrc.js b/plugins/code-coverage/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/plugins/code-coverage/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/plugins/code-coverage/README.md b/plugins/code-coverage/README.md new file mode 100644 index 0000000000..b93ad7a091 --- /dev/null +++ b/plugins/code-coverage/README.md @@ -0,0 +1,19 @@ +# code-coverage + +This is the frontend part of the code-coverage plugin. It takes care of processing various coverage formats and standardizing them into a single json format, used by the frontend. + +## Configuring your entity + +In order to use this plugin, you must set the `backstage.io/code-coverage` annotation. + +```yaml +backstage.io/code-coverage: enabled +``` + +There's a feature to only include files that are in VCS in the coverage report, this is helpful to not count generated files for example. To enable this set the `backstage.io/code-coverage` annotation to `scm-only`. + +```yaml +backstage.io/code-coverage: scm-only +``` + +Note: This requires the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location) to be set. diff --git a/plugins/code-coverage/dev/index.tsx b/plugins/code-coverage/dev/index.tsx new file mode 100644 index 0000000000..9eabafb976 --- /dev/null +++ b/plugins/code-coverage/dev/index.tsx @@ -0,0 +1,26 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 React from 'react'; +import { createDevApp } from '@backstage/dev-utils'; +import { codeCoveragePlugin, CodeCoveragePage } from '../src/plugin'; + +createDevApp() + .registerPlugin(codeCoveragePlugin) + .addPage({ + element: <CodeCoveragePage />, + title: 'Root Page', + }) + .render(); diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json new file mode 100644 index 0000000000..75be2cab92 --- /dev/null +++ b/plugins/code-coverage/package.json @@ -0,0 +1,57 @@ +{ + "name": "@backstage/plugin-code-coverage", + "version": "0.1.1", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "build": "backstage-cli plugin:build", + "start": "backstage-cli plugin:serve", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "diff": "backstage-cli plugin:diff", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/catalog-model": "^0.7.2", + "@backstage/config": "^0.1.3", + "@backstage/core": "^0.6.2", + "@backstage/core-api": "^0.2.12", + "@backstage/dev-utils": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.1.0", + "@backstage/theme": "^0.2.3", + "@material-ui/core": "^4.11.0", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.45", + "@types/highlightjs": "^10.1.0", + "highlight.js": "^10.6.0", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-router": "6.0.0-beta.0", + "react-router-dom": "6.0.0-beta.0", + "react-use": "^15.3.3", + "recharts": "^1.8.5" + }, + "devDependencies": { + "@backstage/cli": "^0.6.1", + "@backstage/test-utils": "^0.1.7", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^10.4.1", + "@testing-library/user-event": "^12.0.7", + "@types/jest": "^26.0.7", + "@types/node": "^12.0.0", + "@types/recharts": "^1.8.15", + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts new file mode 100644 index 0000000000..da18bde267 --- /dev/null +++ b/plugins/code-coverage/src/api.ts @@ -0,0 +1,102 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { createApiRef } from '@backstage/core'; +import { Config } from '@backstage/config'; +import { EntityName } from '@backstage/catalog-model'; + +export class FetchError extends Error { + get name(): string { + return this.constructor.name; + } + + static async forResponse(resp: Response): Promise<FetchError> { + return new FetchError( + `Request failed with status code ${ + resp.status + }.\nReason: ${await resp.text()}`, + ); + } +} + +export type CodeCoverageApi = { + url: string; + getCoverageForEntity: (entity: EntityName) => Promise<any>; + getFileContentFromEntity: ( + entity: EntityName, + filePath: string, + ) => Promise<any>; + getCoverageHistoryForEntity: ( + entity: EntityName, + limit?: number, + ) => Promise<any>; +}; + +export const codeCoverageApiRef = createApiRef<CodeCoverageApi>({ + id: 'plugin.code-coverage.service', + description: 'Used by the code coverage plugin to make requests', +}); + +export class CodeCoverageRestApi implements CodeCoverageApi { + static fromConfig(config: Config) { + return new CodeCoverageRestApi(config.getString('backend.baseUrl')); + } + + constructor(public url: string) {} + + private async fetch<T = any | string>( + input: string, + init?: RequestInit, + ): Promise<T | string> { + const resp = await fetch(`${this.url}${input}`, init); + if (!resp.ok) throw await FetchError.forResponse(resp); + if (resp.headers.get('content-type')?.includes('application/json')) { + return await resp.json(); + } + return await resp.text(); + } + + async getCoverageForEntity({ + kind, + namespace, + name, + }: EntityName): Promise<any> { + return await this.fetch<any>( + `/api/code-coverage/${kind}/${namespace}/${name}`, + ); + } + + async getFileContentFromEntity( + { kind, namespace, name }: EntityName, + filePath: string, + ): Promise<any> { + return await this.fetch<any>( + `/api/code-coverage/${kind}/${namespace}/${name}/file-content?path=${filePath}`, + ); + } + + async getCoverageHistoryForEntity( + { kind, namespace, name }: EntityName, + limit?: number, + ): Promise<any> { + const hasValidLimit = limit && limit > 0; + return await this.fetch<any>( + `/api/code-coverage/${kind}/${namespace}/${name}/history${ + hasValidLimit ? `?limit=${limit}` : '' + }`, + ); + } +} diff --git a/plugins/code-coverage/src/components/CodeCoveragePage/CodeCoveragePage.tsx b/plugins/code-coverage/src/components/CodeCoveragePage/CodeCoveragePage.tsx new file mode 100644 index 0000000000..47811b93cd --- /dev/null +++ b/plugins/code-coverage/src/components/CodeCoveragePage/CodeCoveragePage.tsx @@ -0,0 +1,31 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React from 'react'; +import { Content, ContentHeader, Page } from '@backstage/core'; +import { CoverageHistoryChart } from '../CoverageHistoryChart'; +import { FileExplorer } from '../FileExplorer'; + +export const CodeCoveragePage = () => { + return ( + <Page themeId="tool"> + <Content> + <ContentHeader title="Code coverage" /> + <CoverageHistoryChart /> + <FileExplorer /> + </Content> + </Page> + ); +}; diff --git a/plugins/code-coverage/src/components/CodeCoveragePage/index.ts b/plugins/code-coverage/src/components/CodeCoveragePage/index.ts new file mode 100644 index 0000000000..c5479c0098 --- /dev/null +++ b/plugins/code-coverage/src/components/CodeCoveragePage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { CodeCoveragePage } from './CodeCoveragePage'; diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx new file mode 100644 index 0000000000..a7bfeceb19 --- /dev/null +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx @@ -0,0 +1,169 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React from 'react'; +import { + Box, + Card, + CardContent, + MenuItem, + Select, + Typography, +} from '@material-ui/core'; +import { + LineChart, + XAxis, + YAxis, + Tooltip, + Legend, + Line, + CartesianGrid, + ResponsiveContainer, +} from 'recharts'; +import { useAsync } from 'react-use'; +import { useApi } from '@backstage/core-api'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { codeCoverageApiRef } from '../../api'; +import { Progress } from '@backstage/core'; +import { Alert } from '@material-ui/lab'; +import TrendingDownIcon from '@material-ui/icons/TrendingDown'; +import TrendingUpIcon from '@material-ui/icons/TrendingUp'; +import TrendingFlatIcon from '@material-ui/icons/TrendingFlat'; + +type Coverage = 'line' | 'branch'; + +const getTrendIcon = (trend: number) => { + switch (true) { + case trend > 0: + return <TrendingUpIcon style={{ color: 'green' }} />; + case trend < 0: + return <TrendingDownIcon style={{ color: 'red' }} />; + case trend === 0: + default: + return <TrendingFlatIcon />; + } +}; + +export const CoverageHistoryChart = () => { + const { entity } = useEntity(); + const codeCoverageApi = useApi(codeCoverageApiRef); + const { + loading: loadingHistory, + error: errorHistory, + value: valueHistory, + } = useAsync( + async () => + await codeCoverageApi.getCoverageHistoryForEntity({ + kind: entity.kind, + namespace: entity.metadata.namespace || 'default', + name: entity.metadata.name, + }), + ); + + if (loadingHistory) { + return <Progress />; + } else if (errorHistory) { + return <Alert severity="error">{errorHistory.message}</Alert>; + } + + if (!valueHistory.history.length) { + return ( + <Box> + <Card> + <CardContent> + <Box mb={2} display="flex" justifyContent="space-between"> + <Typography variant="h5">History</Typography> + </Box> + No coverage history found + </CardContent> + </Card> + </Box> + ); + } + + const oldestCoverage = valueHistory.history[0]; + const [latestCoverage] = valueHistory.history.slice(-1); + + const getTrendForCoverage = (type: Coverage) => { + if (!oldestCoverage[type].percentage) { + return 0; + } + return ( + ((latestCoverage[type].percentage - oldestCoverage[type].percentage) / + oldestCoverage[type].percentage) * + 100 + ); + }; + + const lineTrend = getTrendForCoverage('line'); + const branchTrend = getTrendForCoverage('branch'); + + return ( + <Box> + <Card> + <CardContent> + <Box mb={2} display="flex" justifyContent="space-between"> + <Typography variant="h5">History</Typography> + <Select> + <MenuItem>7</MenuItem> + </Select> + </Box> + <Box px={6} display="flex"> + <Box display="flex" mr={4}> + {getTrendIcon(lineTrend)} + <Typography> + Current line: {latestCoverage.line.percentage}%<br />( + {Math.floor(lineTrend)}% change over{' '} + {valueHistory.history.length} builds) + </Typography> + </Box> + <Box display="flex"> + {getTrendIcon(branchTrend)} + <Typography> + Current branch: {latestCoverage.branch.percentage}%<br />( + {Math.floor(branchTrend)}% change over{' '} + {valueHistory.history.length} builds) + </Typography> + </Box> + </Box> + <ResponsiveContainer width="100%" height={300}> + <LineChart + data={valueHistory.history} + margin={{ right: 48, top: 32 }} + > + <CartesianGrid strokeDasharray="3 3" /> + <XAxis dataKey="timestamp" /> + <YAxis dataKey="line.percentage" /> + <YAxis dataKey="branch.percentage" /> + <Tooltip /> + <Legend /> + <Line + type="monotone" + dataKey="branch.percentage" + stroke="#8884d8" + /> + <Line + type="monotone" + dataKey="line.percentage" + stroke="#82ca9d" + /> + </LineChart> + </ResponsiveContainer> + </CardContent> + </Card> + </Box> + ); +}; diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/index.ts b/plugins/code-coverage/src/components/CoverageHistoryChart/index.ts new file mode 100644 index 0000000000..b9dd72e34b --- /dev/null +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { CoverageHistoryChart } from './CoverageHistoryChart'; diff --git a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx new file mode 100644 index 0000000000..a4eabf715d --- /dev/null +++ b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx @@ -0,0 +1,103 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 React, { FC } from 'react'; + +// styles +import { makeStyles } from '@material-ui/core'; +import { red, green } from '@material-ui/core/colors'; + +const useStyles = makeStyles(theme => ({ + lineNumberCell: { + color: `${theme.palette.grey[500]}`, + fontSize: '90%', + borderRight: `1px solid ${theme.palette.grey[500]}`, + paddingRight: '8px', + textAlign: 'right', + }, + hitCountCell: { + width: '50px', + borderRight: `1px solid ${theme.palette.grey[500]}`, + textAlign: 'center', + color: 'white', // need to enforce this color since it needs to stand out against colored background + paddingLeft: `${theme.spacing(1)}`, + paddingRight: `${theme.spacing(1)}`, + }, + countRoundedRectangle: { + borderRadius: '45px', + fontSize: '90%', + padding: '1px 3px 1px 3px', + width: '50px', + }, + hitCountRoundedRectangle: { + backgroundColor: `${green[500]}`, + }, + notHitCountRoundedRectangle: { + backgroundColor: `${red[500]}`, + }, + codeLine: { + paddingLeft: `${theme.spacing(1)}`, + whiteSpace: 'pre', + fontSize: '90%', + }, + hitCodeLine: { + backgroundColor: `${green[100]}`, + }, + notHitCodeLine: { + backgroundColor: `${red[100]}`, + }, +})); + +type CodeRowProps = { + lineNumber: number; + lineContent: string; + lineHits?: number | null; +}; +const CodeRow: FC<CodeRowProps> = ({ + lineNumber, + lineContent, + lineHits = null, +}: CodeRowProps) => { + const classes = useStyles(); + const hitCountRoundedRectangleClass = [classes.countRoundedRectangle]; + const lineContentClass = [classes.codeLine]; + + let hitRoundedRectangle = null; + if (lineHits !== null) { + if (lineHits > 0) { + hitCountRoundedRectangleClass.push(classes.hitCountRoundedRectangle); + lineContentClass.push(classes.hitCodeLine); + } else { + hitCountRoundedRectangleClass.push(classes.notHitCountRoundedRectangle); + lineContentClass.push(classes.notHitCodeLine); + } + hitRoundedRectangle = ( + <div className={hitCountRoundedRectangleClass.join(' ')}>{lineHits}</div> + ); + } + + return ( + <tr> + <td className={classes.lineNumberCell}>{lineNumber}</td> + <td className={classes.hitCountCell}>{hitRoundedRectangle}</td> + <td + className={lineContentClass.join(' ')} + dangerouslySetInnerHTML={{ __html: lineContent }} + /> + </tr> + ); +}; + +export default CodeRow; diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx new file mode 100644 index 0000000000..7b1bc2c070 --- /dev/null +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -0,0 +1,137 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React, { FC, useEffect } from 'react'; +import { useApi } from '@backstage/core-api'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { useAsync } from 'react-use'; +import { codeCoverageApiRef } from '../../api'; +import { Progress } from '@backstage/core'; +import { Alert } from '@material-ui/lab'; +import { makeStyles, Paper } from '@material-ui/core'; +import { highlightLines } from './Highlighter'; +import { FileCoverage } from './FileExplorer'; +import CoverageRow from './CoverageRow'; + +type Props = { + filename: string; + coverage: FileCoverage; +}; + +const getContent = async (value: any) => { + let blob = value; + if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) { + blob = new Blob([value], { type: 'application/octet-stream' }); + } + return value; +}; + +const useStyles = makeStyles(theme => ({ + paper: { + margin: 'auto', + top: '2em', + width: '80%', + backgroundColor: theme.palette.background.paper, + border: '2px solid #000', + boxShadow: theme.shadows[5], + padding: theme.spacing(2, 4, 3), + overflow: 'scroll', + }, + coverageFileViewTable: { + borderSpacing: '0px', + width: '80%', + marginTop: theme.spacing(2), + }, +})); + +type FormattedLinesProps = { + highlightedLines: string[]; + lineHits: Record<number, number>; +}; +const FormattedLines: FC<FormattedLinesProps> = ({ + highlightedLines, + lineHits, +}: FormattedLinesProps) => { + return ( + <> + {highlightedLines.map((lineContent, idx) => { + const line = idx + 1; + return ( + <CoverageRow + key={line} + lineNumber={line} + lineContent={lineContent} + lineHits={lineHits[line]} + /> + ); + })} + </> + ); +}; + +export const FileContent = ({ filename, coverage }: Props) => { + const { entity } = useEntity(); + const codeCoverageApi = useApi(codeCoverageApiRef); + const { loading, error, value } = useAsync( + async () => + await codeCoverageApi.getFileContentFromEntity( + { + kind: entity.kind, + namespace: entity.metadata.namespace || 'default', + name: entity.metadata.name, + }, + filename, + ), + ); + + useEffect(() => { + if (value) getContent(value); + }, [value]); + + const classes = useStyles(); + + if (loading) { + return <Progress />; + } else if (error) { + return <Alert severity="error">{error.message}</Alert>; + } + + const [language] = filename.split('.').slice(-1); + const highlightedLines = highlightLines(language, value.split('\n')); + + // List of formatted nodes containing highlighted code + // lineHits array where lineHits[i] is number of hits for line i + 1 + const lineHits = Object.entries(coverage.lineHits).reduce( + (acc: Record<string, number>, next: [string, number]) => { + acc[next[0]] = next[1]; + return acc; + }, + {}, + ); + + return ( + <Paper variant="outlined" className={classes.paper}> + <table className={classes.coverageFileViewTable}> + <tbody> + <FormattedLines + highlightedLines={highlightedLines} + lineHits={lineHits} + /> + </tbody> + </table> + </Paper> + ); +}; diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx new file mode 100644 index 0000000000..11baa419f4 --- /dev/null +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx @@ -0,0 +1,280 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { useApi } from '@backstage/core-api'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { Progress, Table, TableColumn } from '@backstage/core'; +import { + Box, + Card, + CardContent, + Modal, + Tooltip, + Typography, +} from '@material-ui/core'; +import React, { Fragment, useEffect, useState } from 'react'; +import { useAsync } from 'react-use'; +import { codeCoverageApiRef } from '../../api'; +import { Alert } from '@material-ui/lab'; +import DescriptionIcon from '@material-ui/icons/Description'; +import { FileContent } from './FileContent'; + +export type FileCoverage = { + filename: string; + branchHits: { [branch: number]: number }; + lineHits: { [line: number]: number }; +}; + +type FileStructureObject = Record<string, any>; + +type CoverageTableRow = { + filename?: string; + files: CoverageTableRow[]; + coverage: number; + missing: number; + tracked: number; + path: string; + tableData?: { id: number }; +}; + +const buildFileStructure = (row: CoverageTableRow) => { + const dataGroupedByPath: FileStructureObject = row.files.reduce( + (acc: FileStructureObject, cur: CoverageTableRow) => { + let path = cur.filename; + if (row.path) { + path = path?.split(`${row.path}/`)[1]; + } + const pathArray = path?.split('/'); + + if (!pathArray) { + return acc; + } + if (!acc.hasOwnProperty(pathArray[0])) { + acc[pathArray[0]] = []; + } + acc[pathArray[0]].push(cur); + return acc; + }, + {}, + ); + + row.files = Object.keys(dataGroupedByPath).map(pathGroup => { + return buildFileStructure({ + path: pathGroup, + files: dataGroupedByPath.hasOwnProperty('files') + ? dataGroupedByPath.files + : dataGroupedByPath[pathGroup], + coverage: + dataGroupedByPath[pathGroup].reduce( + (acc: number, cur: CoverageTableRow) => acc + cur.coverage, + 0, + ) / dataGroupedByPath[pathGroup].length, + missing: dataGroupedByPath[pathGroup].reduce( + (acc: number, cur: CoverageTableRow) => acc + cur.missing, + 0, + ), + tracked: dataGroupedByPath[pathGroup].reduce( + (acc: number, cur: CoverageTableRow) => acc + cur.tracked, + 0, + ), + }); + }); + return row; +}; + +const formatInitialData = (value: any) => { + return buildFileStructure({ + path: '', + coverage: value.aggregate.line.percentage, + missing: value.aggregate.line.missed, + tracked: value.aggregate.line.available, + files: value.files.map((fc: FileCoverage) => { + return { + path: '', + filename: fc.filename, + coverage: Math.floor( + (Object.values(fc.lineHits).filter((hits: number) => hits > 0) + .length / + Object.values(fc.lineHits).length) * + 100, + ), + missing: Object.values(fc.lineHits).filter(hits => !hits).length, + tracked: Object.values(fc.lineHits).length, + }; + }), + }); +}; + +export const FileExplorer = () => { + const { entity } = useEntity(); + const [curData, setCurData] = useState<CoverageTableRow | undefined>(); + const [tableData, setTableData] = useState<CoverageTableRow[] | undefined>(); + const [curPath, setCurPath] = useState(''); + const [modalOpen, setModalOpen] = useState(false); + const [curFile, setCurFile] = useState(''); + const codeCoverageApi = useApi(codeCoverageApiRef); + const { loading, error, value } = useAsync( + async () => + await codeCoverageApi.getCoverageForEntity({ + kind: entity.kind, + namespace: entity.metadata.namespace || 'default', + name: entity.metadata.name, + }), + ); + + useEffect(() => { + if (!value) return; + const data = formatInitialData(value); + setCurData(data); + if (data.files) setTableData(data.files); + }, [value]); + + if (loading) { + return <Progress />; + } else if (error) { + return <Alert severity="error">{error.message}</Alert>; + } + + const moveDownIntoPath = (path: string) => { + const nextPathData = tableData!.find( + (d: CoverageTableRow) => d.path === path, + ); + if (nextPathData && nextPathData.files) { + setTableData(nextPathData.files); + } + }; + + const moveUpIntoPath = (path: string) => { + const pathArray = path.split('/').filter(p => p.length); + let data = curData?.files; + pathArray.forEach(p => { + data = data?.find(d => d.path === p)?.files; + }); + setCurPath(path); + setTableData(data); + }; + + const columns: TableColumn<CoverageTableRow>[] = [ + { + title: 'Path', + type: 'string', + field: 'path', + render: (row: CoverageTableRow) => { + if (row.files?.length) { + return ( + <div + role="button" + tabIndex={row.tableData!.id} + style={{ color: 'lightblue', cursor: 'pointer' }} + onKeyDown={() => { + setCurPath(`${curPath}/${row.path}`); + moveDownIntoPath(row.path); + }} + onClick={() => { + setCurPath(`${curPath}/${row.path}`); + moveDownIntoPath(row.path); + }} + > + {row.path} + </div> + ); + } + + return ( + <Box display="flex" alignItems="center"> + {row.path} + <Tooltip title="View file content"> + <DescriptionIcon + fontSize="small" + style={{ color: 'lightblue', cursor: 'pointer' }} + onClick={() => { + setCurFile(`${curPath.slice(1)}/${row.path}`); + setModalOpen(true); + }} + /> + </Tooltip> + </Box> + ); + }, + }, + { + title: 'Coverage', + type: 'numeric', + field: 'coverage', + render: (row: CoverageTableRow) => `${row.coverage}%`, + }, + { + title: 'Missing lines', + type: 'numeric', + field: 'missing', + }, + { + title: 'Tracked lines', + type: 'numeric', + field: 'tracked', + }, + ]; + + const pathArray = curPath.split('/'); + const lastPathElementIndex = pathArray.length - 1; + const fileCoverage = value.files.find((f: FileCoverage) => + f.filename.endsWith(curFile), + ); + + return ( + <Box mt={8}> + <Card> + <CardContent> + <Box mb={2} display="flex" justifyContent="space-between"> + <Typography variant="h5">Explore Files</Typography> + </Box> + <Box mb={2} display="flex"> + {pathArray.map((pathElement, idx) => ( + <Fragment key={pathElement || 'root'}> + <div + role="button" + tabIndex={idx} + style={{ + color: `${idx !== lastPathElementIndex && 'lightblue'}`, + cursor: `${idx !== lastPathElementIndex && 'pointer'}`, + }} + onKeyDown={() => moveUpIntoPath(pathElement)} + onClick={() => moveUpIntoPath(pathElement)} + > + {pathElement || 'root'} + </div> + <div>{'\u00A0/\u00A0'}</div> + </Fragment> + ))} + </Box> + <Table + emptyContent={<>No files found</>} + data={tableData || []} + columns={columns} + /> + <Modal + open={modalOpen} + onClick={event => event.stopPropagation()} + onClose={() => setModalOpen(false)} + style={{ overflow: 'scroll' }} + > + <FileContent filename={curFile} coverage={fileCoverage} /> + </Modal> + </CardContent> + </Card> + </Box> + ); +}; diff --git a/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts b/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts new file mode 100644 index 0000000000..fda1a11f11 --- /dev/null +++ b/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts @@ -0,0 +1,54 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 'highlight.js/styles/atom-one-dark.css'; +import highlight from 'highlight.js'; + +/* + * Given a file extension, repo name, and array of code lines, return a Promise resolving + * to an array of formatted lines with html/css formatting. + * + * @param {String} fileExtension The extension of the source file + * @param {String} repo The name of the code repository + * @param {Array<String>} lines The source code lines + * + * @returns {Promise<Array<String>>} Promise of formatted lines + * + * @see http://highlightjs.readthedocs.io/en/latest/api.html#highlight-name-value-ignore-illegals-continuation + */ +export const highlightLines = (fileExtension: string, lines: Array<string>) => { + const formattedLines: Array<string> = []; + let state: CompiledMode | Language | undefined; + let fileformat = fileExtension; + if (fileExtension === 'm') { + fileformat = 'objectivec'; + } + if (fileExtension === 'tsx') { + fileformat = 'typescript'; + } + if (fileExtension === 'jsx') { + fileformat = 'javascript'; + } + if (fileExtension === 'kt') { + fileformat = 'kotlin'; + } + + lines.forEach(line => { + const result = highlight.highlight(fileformat, line, true, state); + state = result.top; + formattedLines.push(result.value); + }); + return formattedLines; +}; diff --git a/plugins/code-coverage/src/components/FileExplorer/index.ts b/plugins/code-coverage/src/components/FileExplorer/index.ts new file mode 100644 index 0000000000..88da4059bd --- /dev/null +++ b/plugins/code-coverage/src/components/FileExplorer/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { FileExplorer } from './FileExplorer'; diff --git a/plugins/code-coverage/src/components/Router.tsx b/plugins/code-coverage/src/components/Router.tsx new file mode 100644 index 0000000000..12be6ef5a8 --- /dev/null +++ b/plugins/code-coverage/src/components/Router.tsx @@ -0,0 +1,34 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React from 'react'; +import { Entity } from '@backstage/catalog-model'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { MissingAnnotationEmptyState } from '@backstage/core'; +import { CodeCoveragePage } from './CodeCoveragePage'; + +export const isCodeCoverageAvailable = (entity: Entity) => + Boolean(entity.metadata.annotations?.['backstage.io/code-coverage']); + +export const Router = () => { + const { entity } = useEntity(); + + if (!isCodeCoverageAvailable(entity)) { + return ( + <MissingAnnotationEmptyState annotation="backstage.io/code-coverage" /> + ); + } + return <CodeCoveragePage />; +}; diff --git a/plugins/code-coverage/src/dev/index.tsx b/plugins/code-coverage/src/dev/index.tsx new file mode 100644 index 0000000000..5c944b097a --- /dev/null +++ b/plugins/code-coverage/src/dev/index.tsx @@ -0,0 +1,28 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { createDevApp } from '@backstage/dev-utils'; +import { codeCoveragePlugin } from '../plugin'; +import { codeCoverageApiRef, CodeCoverageRestApi } from '../api'; + +createDevApp() + .registerPlugin(codeCoveragePlugin) + .registerApi({ + api: codeCoverageApiRef, + deps: {}, + factory: () => new CodeCoverageRestApi('http://localhost:3000'), + }) + .render(); diff --git a/plugins/code-coverage/src/index.ts b/plugins/code-coverage/src/index.ts new file mode 100644 index 0000000000..84010e64ac --- /dev/null +++ b/plugins/code-coverage/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { codeCoveragePlugin, EntityCodeCoverageContent } from './plugin'; +export { + Router, + isCodeCoverageAvailable, + isCodeCoverageAvailable as isPluginApplicableToEntity, +} from './components/Router'; + +// export { createBackendRouter } from './backend/router'; diff --git a/plugins/code-coverage/src/plugin.test.ts b/plugins/code-coverage/src/plugin.test.ts new file mode 100644 index 0000000000..9a34c66965 --- /dev/null +++ b/plugins/code-coverage/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { codeCoveragePlugin } from './plugin'; + +describe('code-coverage', () => { + it('should export plugin', () => { + expect(codeCoveragePlugin).toBeDefined(); + }); +}); diff --git a/plugins/code-coverage/src/plugin.ts b/plugins/code-coverage/src/plugin.ts new file mode 100644 index 0000000000..fa5f31d9cc --- /dev/null +++ b/plugins/code-coverage/src/plugin.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { + configApiRef, + createApiFactory, + createPlugin, + createRoutableExtension, +} from '@backstage/core'; +import { codeCoverageApiRef, CodeCoverageRestApi } from './api'; + +import { rootRouteRef } from './routes'; + +export const codeCoveragePlugin = createPlugin({ + id: 'code-coverage', + routes: { + root: rootRouteRef, + }, + apis: [ + createApiFactory({ + api: codeCoverageApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => CodeCoverageRestApi.fromConfig(configApi), + }), + ], +}); + +export const EntityCodeCoverageContent = codeCoveragePlugin.provide( + createRoutableExtension({ + component: () => import('./components/Router').then(m => m.Router), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/code-coverage/src/routes.ts b/plugins/code-coverage/src/routes.ts new file mode 100644 index 0000000000..9eaf7859f5 --- /dev/null +++ b/plugins/code-coverage/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { createRouteRef } from '@backstage/core'; + +export const rootRouteRef = createRouteRef({ + title: 'code-coverage', +}); diff --git a/plugins/code-coverage/src/setupTests.ts b/plugins/code-coverage/src/setupTests.ts new file mode 100644 index 0000000000..0cec5b395d --- /dev/null +++ b/plugins/code-coverage/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/yarn.lock b/yarn.lock index a9b95da3ec..baf771b351 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1623,6 +1623,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.3": + version "7.13.10" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" + integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4", "@babel/template@^7.12.13", "@babel/template@^7.3.3": version "7.12.13" resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" @@ -1679,6 +1686,138 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@backstage/backend-common@^0.5.4": + version "0.5.6" + resolved "https://registry.npmjs.org/@backstage/backend-common/-/backend-common-0.5.6.tgz#e49840eaa6738f6697319ccdfff04ce40cc54b72" + integrity sha512-BzKlcTZLAVDpH87fi2TCWIFO9DfVdaPIIZ8gZSorCuLLErG4X7CS/zQiujJZ/zD5HGtO2QB57fuRkwjBMhJhhw== + dependencies: + "@backstage/cli-common" "^0.1.1" + "@backstage/config" "^0.1.2" + "@backstage/config-loader" "^0.5.1" + "@backstage/integration" "^0.5.1" + "@octokit/rest" "^18.0.12" + "@types/cors" "^2.8.6" + "@types/dockerode" "^3.2.1" + "@types/express" "^4.17.6" + archiver "^5.0.2" + compression "^1.7.4" + concat-stream "^2.0.0" + cors "^2.8.5" + cross-fetch "^3.0.6" + dockerode "^3.2.1" + express "^4.17.1" + express-promise-router "^3.0.3" + fs-extra "^9.0.1" + git-url-parse "^11.4.4" + helmet "^4.0.0" + isomorphic-git "^1.8.0" + knex "^0.95.1" + lodash "^4.17.15" + logform "^2.1.1" + minimatch "^3.0.4" + minimist "^1.2.5" + morgan "^1.10.0" + selfsigned "^1.10.7" + stoppable "^1.1.0" + tar "^6.0.5" + unzipper "^0.10.11" + winston "^3.2.1" + +"@backstage/config-loader@^0.5.1": + version "0.5.1" + resolved "https://registry.npmjs.org/@backstage/config-loader/-/config-loader-0.5.1.tgz#a80f2047e209d2f41b17ad715c632ab142385b39" + integrity sha512-PmwXERs5BIf77sUIg3Fhp/elkR6ELj0czmpUgP4cuEdtazi0WcmdjCUC2DjgsKJWvYggsL1o372QKHh/M5AMTQ== + dependencies: + "@backstage/cli-common" "^0.1.1" + "@backstage/config" "^0.1.1" + ajv "^7.0.3" + fs-extra "^9.0.0" + json-schema "^0.2.5" + json-schema-merge-allof "^0.7.0" + typescript-json-schema "^0.47.0" + yaml "^1.9.2" + yup "^0.29.3" + +"@backstage/core@^0.6.2": + version "0.6.3" + resolved "https://registry.npmjs.org/@backstage/core/-/core-0.6.3.tgz#574ca46ab59e18af07fcf3a248c4428d4dfcc302" + integrity sha512-OSpnvotyCkb6fL02T1Z5TLcogRlOzVIH8YBfNlKeo/Xo/JnlVp1uSpQxCWjAW/lzGK5gp6oh3ezFRjm69mTwSA== + dependencies: + "@backstage/config" "^0.1.3" + "@backstage/core-api" "^0.2.11" + "@backstage/theme" "^0.2.3" + "@material-ui/core" "^4.11.0" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.45" + "@testing-library/react-hooks" "^3.4.2" + "@types/dagre" "^0.7.44" + "@types/prop-types" "^15.7.3" + "@types/react" "^16.9" + "@types/react-sparklines" "^1.7.0" + "@types/react-text-truncate" "^0.14.0" + classnames "^2.2.6" + clsx "^1.1.0" + d3-selection "^2.0.0" + d3-shape "^2.0.0" + d3-zoom "^2.0.0" + dagre "^0.8.5" + immer "^8.0.1" + lodash "^4.17.15" + material-table "^1.69.1" + prop-types "^15.7.2" + qs "^6.9.4" + rc-progress "^3.0.0" + react "^16.12.0" + react-dom "^16.12.0" + react-helmet "6.1.0" + react-hook-form "^6.6.0" + react-markdown "^5.0.2" + react-router "6.0.0-beta.0" + react-router-dom "6.0.0-beta.0" + react-sparklines "^1.7.0" + react-syntax-highlighter "^13.5.1" + react-text-truncate "^0.16.0" + react-use "^15.3.3" + remark-gfm "^1.0.0" + zen-observable "^0.8.15" + +"@backstage/plugin-catalog-backend@^0.6.5": + version "0.6.7" + resolved "https://registry.npmjs.org/@backstage/plugin-catalog-backend/-/plugin-catalog-backend-0.6.7.tgz#97d0ed6db6aeb04e09ed0fee05e76bacf66cc179" + integrity sha512-Ey9PXyUjmi8IxQNSXBhF6Sl2SmZ/iXCFHXnffH8XCdBFTZS8HDRE2tSOlIIU4XQKd6lJVuAGTekas2DkaS9/lA== + dependencies: + "@azure/msal-node" "^1.0.0-beta.3" + "@backstage/backend-common" "^0.6.0" + "@backstage/catalog-model" "^0.7.4" + "@backstage/config" "^0.1.4" + "@backstage/errors" "^0.1.1" + "@backstage/integration" "^0.5.1" + "@backstage/plugin-search-backend-node" "^0.1.2" + "@backstage/search-common" "^0.1.1" + "@octokit/graphql" "^4.5.8" + "@types/express" "^4.17.6" + "@types/ldapjs" "^1.0.9" + aws-sdk "^2.840.0" + codeowners-utils "^1.0.2" + core-js "^3.6.5" + cross-fetch "^3.0.6" + express "^4.17.1" + express-promise-router "^4.1.0" + fs-extra "^9.0.0" + git-url-parse "^11.4.4" + glob "^7.1.6" + knex "^0.95.1" + ldapjs "^2.2.0" + lodash "^4.17.15" + morgan "^1.10.0" + p-limit "^3.0.2" + qs "^6.9.4" + uuid "^8.0.0" + winston "^3.2.1" + yaml "^1.9.2" + yn "^4.0.0" + yup "^0.29.3" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -5520,6 +5659,20 @@ lz-string "^1.4.4" pretty-format "^26.6.2" +"@testing-library/dom@^7.22.3": + version "7.30.3" + resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-7.30.3.tgz#779ea9bbb92d63302461800a388a5a890ac22519" + integrity sha512-7JhIg2MW6WPwyikH2iL3o7z+FTVgSOd2jqCwTAHqK7Qal2gRRYiUQyURAxtbK9VXm/UTyG9bRihv8C5Tznr2zw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^4.2.2" + chalk "^4.1.0" + dom-accessibility-api "^0.5.4" + lz-string "^1.4.4" + pretty-format "^26.6.2" + "@testing-library/jest-dom@^5.10.1": version "5.11.9" resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.9.tgz#e6b3cd687021f89f261bd53cbe367041fbd3e975" @@ -5550,6 +5703,14 @@ "@babel/runtime" "^7.5.4" "@types/testing-library__react-hooks" "^3.4.0" +"@testing-library/react@^10.4.1": + version "10.4.9" + resolved "https://registry.npmjs.org/@testing-library/react/-/react-10.4.9.tgz#9faa29c6a1a217bf8bbb96a28bd29d7a847ca150" + integrity sha512-pHZKkqUy0tmiD81afs8xfiuseXfU/N7rAX3iKjeZYje86t9VaB0LrxYVa+OOsvkrveX5jCK3IjajVn2MbePvqA== + dependencies: + "@babel/runtime" "^7.10.3" + "@testing-library/dom" "^7.22.3" + "@testing-library/react@^11.2.5": version "11.2.6" resolved "https://registry.npmjs.org/@testing-library/react/-/react-11.2.6.tgz#586a23adc63615985d85be0c903f374dab19200b" @@ -5902,6 +6063,14 @@ dependencies: "@types/express" "*" +"@types/express-xml-bodyparser@^0.3.2": + version "0.3.2" + resolved "https://registry.npmjs.org/@types/express-xml-bodyparser/-/express-xml-bodyparser-0.3.2.tgz#8566883271d4a28fc57b471d06e6c08047496acb" + integrity sha512-qX01S9eZI/XY48OLI7+5GnofaFG3VyBEn0oIrY5rxkq/T0U2EBpiUfM0scILUluIR6UGBHMM5C2b8Pmir3Xrtw== + dependencies: + "@types/express" "*" + "@types/xml2js" "*" + "@types/express@*", "@types/express@4.17.7", "@types/express@^4.17.6", "@types/express@^4.17.7": version "4.17.7" resolved "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59" @@ -5968,6 +6137,13 @@ dependencies: "@types/unist" "*" +"@types/highlightjs@^10.1.0": + version "10.1.0" + resolved "https://registry.npmjs.org/@types/highlightjs/-/highlightjs-10.1.0.tgz#bf16135e3c736db053f026a1fa8ff3aa247ef5c1" + integrity sha512-xCmqJdhDi4EqrfNDU5ZfZV2ejhszpWBkJS/jYCoAHZhQBBUGnE26l0AzHsZHoe37z4ZETFoZn8HKTIFDjRrfwA== + dependencies: + highlight.js "^10.1.0" + "@types/history@*": version "4.7.5" resolved "https://registry.npmjs.org/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860" @@ -6313,6 +6489,11 @@ resolved "https://registry.npmjs.org/@types/node/-/node-10.17.35.tgz#58058f29b870e6ae57b20e4f6e928f02b7129f56" integrity sha512-gXx7jAWpMddu0f7a+L+txMplp3FnHl53OhQIF9puXKq3hDGY/GjH+MF04oWnV/adPSCrbtHumDCFwzq2VhltWA== +"@types/node@^12.0.0": + version "12.20.10" + resolved "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz#4dcb8a85a8f1211acafb88d72fafc7e3d2685583" + integrity sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw== + "@types/node@^12.7.1": version "12.12.58" resolved "https://registry.npmjs.org/@types/node/-/node-12.12.58.tgz#46dae9b2b9ee5992818c8f7cee01ff4ce03ab44c" @@ -6901,7 +7082,7 @@ dependencies: "@types/node" "*" -"@types/xml2js@^0.4.7": +"@types/xml2js@*", "@types/xml2js@^0.4.7": version "0.4.8" resolved "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.8.tgz#84c120c864a5976d0b5cf2f930a75d850fc2b03a" integrity sha512-EyvT83ezOdec7BhDaEcsklWy7RSIdi6CNe95tmOAK0yx/Lm30C9K75snT3fYayK59ApC2oyW+rcHErdG05FHJA== @@ -9990,7 +10171,7 @@ compare-versions@^3.6.0: resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== -component-emitter@^1.2.1, component-emitter@^1.3.0: +component-emitter@^1.2.0, component-emitter@^1.2.1, component-emitter@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -10294,7 +10475,7 @@ cookie@^0.4.1, cookie@~0.4.1: resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== -cookiejar@^2.1.2: +cookiejar@^2.1.0, cookiejar@^2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== @@ -12844,6 +13025,15 @@ expect@^26.6.2: jest-message-util "^26.6.2" jest-regex-util "^26.0.0" +express-promise-router@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/express-promise-router/-/express-promise-router-3.0.3.tgz#5e6d22a5a3f013d71833172fe8d7ab780c3f6b70" + integrity sha1-Xm0ipaPwE9cYMxcv6NereAw/a3A= + dependencies: + is-promise "^2.1.0" + lodash.flattendeep "^4.0.0" + methods "^1.0.0" + express-promise-router@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/express-promise-router/-/express-promise-router-4.1.0.tgz#79160e145c27610ba411bceb0552a36f11dbab4f" @@ -12867,6 +13057,13 @@ express-session@^1.17.1: safe-buffer "5.2.0" uid-safe "~2.1.5" +express-xml-bodyparser@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/express-xml-bodyparser/-/express-xml-bodyparser-0.3.0.tgz#b1f5a98adf6c6e412c4ccba634234b82945c62be" + integrity sha1-sfWpit9sbkEsTMumNCNLgpRcYr4= + dependencies: + xml2js "^0.4.11" + express@^4.0.0, express@^4.17.0, express@^4.17.1: version "4.17.1" resolved "https://registry.npmjs.org/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -13434,7 +13631,7 @@ fork-ts-checker-webpack-plugin@4.1.6, fork-ts-checker-webpack-plugin@^4.0.5, for tapable "^1.0.0" worker-rpc "^0.1.0" -form-data@^2.3.2, form-data@^2.5.0: +form-data@^2.3.1, form-data@^2.3.2, form-data@^2.5.0: version "2.5.1" resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== @@ -13475,7 +13672,7 @@ format@^0.2.0: resolved "https://registry.npmjs.org/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= -formidable@^1.2.2: +formidable@^1.2.0, formidable@^1.2.2: version "1.2.2" resolved "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== @@ -14672,6 +14869,11 @@ hex-color-regex@^1.1.0: resolved "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== +highlight.js@^10.1.0, highlight.js@^10.6.0: + version "10.7.2" + resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360" + integrity sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg== + highlight.js@^10.1.1, highlight.js@^10.4.1, highlight.js@~10.4.0: version "10.4.1" resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" @@ -15120,6 +15322,11 @@ immer@8.0.1: resolved "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== +immer@^8.0.1: + version "8.0.4" + resolved "https://registry.npmjs.org/immer/-/immer-8.0.4.tgz#3a21605a4e2dded852fb2afd208ad50969737b7a" + integrity sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ== + immer@^9.0.1: version "9.0.1" resolved "https://registry.npmjs.org/immer/-/immer-9.0.1.tgz#1116368e051f9a0fd188c5136b6efb74ed69c57f" @@ -18336,7 +18543,7 @@ meros@^1.1.2: resolved "https://registry.npmjs.org/meros/-/meros-1.1.4.tgz#c17994d3133db8b23807f62bec7f0cb276cfd948" integrity sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ== -methods@^1.0.0, methods@^1.1.2, methods@~1.1.2: +methods@^1.0.0, methods@^1.1.1, methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= @@ -18449,7 +18656,7 @@ mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, m dependencies: mime-db "1.46.0" -mime@1.6.0, mime@^1.4.0: +mime@1.6.0, mime@^1.4.0, mime@^1.4.1: version "1.6.0" resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -21585,6 +21792,13 @@ qs@6.7.0: resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@^6.5.1: + version "6.10.1" + resolved "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" + integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + dependencies: + side-channel "^1.0.4" + qs@^6.5.2, qs@^6.6.0, qs@^6.7.0, qs@^6.9.1, qs@^6.9.4, qs@^6.9.6: version "6.9.6" resolved "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" @@ -22160,7 +22374,7 @@ react-string-replace@^0.4.1: dependencies: lodash "^4.17.4" -react-syntax-highlighter@^13.5.0: +react-syntax-highlighter@^13.5.0, react-syntax-highlighter@^13.5.1: version "13.5.3" resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-13.5.3.tgz#9712850f883a3e19eb858cf93fad7bb357eea9c6" integrity sha512-crPaF+QGPeHNIblxxCdf2Lg936NAHKhNhuMzRL3F9ct6aYXL3NcZtCL0Rms9+qVo6Y1EQLdXGypBNSbPL/r+qg== @@ -22454,7 +22668,7 @@ read@1, read@~1.0.1: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -23634,6 +23848,15 @@ side-channel@^1.0.2: es-abstract "^1.17.0-next.1" object-inspect "^1.7.0" +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + sigmund@~1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -24588,6 +24811,22 @@ sucrase@^3.17.1: pirates "^4.0.1" ts-interface-checker "^0.1.9" +superagent@^3.8.3: + version "3.8.3" + resolved "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128" + integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA== + dependencies: + component-emitter "^1.2.0" + cookiejar "^2.1.0" + debug "^3.1.0" + extend "^3.0.0" + form-data "^2.3.1" + formidable "^1.2.0" + methods "^1.1.1" + mime "^1.4.1" + qs "^6.5.1" + readable-stream "^2.3.5" + superagent@^6.1.0: version "6.1.0" resolved "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz#09f08807bc41108ef164cfb4be293cebd480f4a6" @@ -24605,6 +24844,14 @@ superagent@^6.1.0: readable-stream "^3.6.0" semver "^7.3.2" +supertest@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz#c2234dbdd6dc79b6f15b99c8d6577b90e4ce3f36" + integrity sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ== + dependencies: + methods "^1.1.2" + superagent "^3.8.3" + supertest@^6.1.3: version "6.1.3" resolved "https://registry.npmjs.org/supertest/-/supertest-6.1.3.tgz#3f49ea964514c206c334073e8dc4e70519c7403f" @@ -25586,6 +25833,17 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript-json-schema@^0.47.0: + version "0.47.0" + resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.47.0.tgz#84dde5460b127c6774da81bf70b23c7e04857b13" + integrity sha512-A6NVwSOTSsNDHfaqDcDeKwwyXEeKqBHoAr20jcetnYj4e8C6zVFofAVhAuwsBXCRYiWEE/lyHrcxpsSpbIk0Mg== + dependencies: + "@types/json-schema" "^7.0.6" + glob "^7.1.6" + json-stable-stringify "^1.0.1" + typescript "^4.1.3" + yargs "^16.2.0" + typescript-json-schema@^0.49.0: version "0.49.0" resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.49.0.tgz#442f6347ca85fb0d9811f217fb0d6537b68734b3" @@ -26095,7 +26353,7 @@ uuid@^7.0.3: resolved "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@^8.0.0, uuid@^8.2.0, uuid@^8.3.0: +uuid@^8.0.0, uuid@^8.2.0, uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -26833,7 +27091,7 @@ xml2js@0.4.19: sax ">=0.6.0" xmlbuilder "~9.0.1" -xml2js@^0.4.19, xml2js@^0.4.23: +xml2js@^0.4.11, xml2js@^0.4.19, xml2js@^0.4.23: version "0.4.23" resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== From 0e57ec3f91ace25cb53c77ccfea3525eef35d6e3 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 11:36:19 -0400 Subject: [PATCH 047/262] Update URLs to be more consistent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GET /report?entity=<ref> POST /report?entity=<ref>&coverageType=<cobertura|jacoco> GET /history?entity=<ref> GET /file-content?entity=<ref>&path=<filepath> Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage-backend/README.md | 16 +-- .../migrations/20210302_init.js | 4 +- .../src/service/CodeCoverageDatabase.test.ts | 17 ++-- .../src/service/CodeCoverageDatabase.ts | 43 ++++---- .../src/service/CoverageUtils.ts | 2 +- .../src/service/router.ts | 98 ++++++++++--------- plugins/code-coverage/src/api.ts | 26 +++-- 7 files changed, 105 insertions(+), 101 deletions(-) diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index 2e2f5ba91f..3229dc940f 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -22,12 +22,12 @@ Note: This requires the [`backstage.io/source-location` annotation](https://back ### Adding cobertura report -POST a cobertura xml to `/:kind/:namespace/:name?coverageType=cobertura` +POST a cobertura xml to `/report` Example: ```json -// curl -X POST -H "Content-Type:text/xml" -d @cobertura.xml "localhost:7000/api/code-coverage/Component/default/entity-name?coverageType=cobertura" +// curl -X POST -H "Content-Type:text/xml" -d @cobertura.xml "localhost:7000/api/code-coverage/report?entity=component:default/entity-name&coverageType=cobertura" { "links": [ { @@ -40,12 +40,12 @@ Example: ### Adding jacoco report -POST a jacoco xml to `/:kind/:namespace/:name?coverageType=jacoco` +POST a jacoco xml to `/report` Example: ```json -// curl -X POST -H "Content-Type:text/xml" -d @jacoco.xml "localhost:7000/api/code-coverage/Component/default/entity-name?coverageType=jacoco" +// curl -X POST -H "Content-Type:text/xml" -d @jacoco.xml "localhost:7000/api/code-coverage/report?entity=component:default/entity-name&coverageType=jacoco" { "links": [ { @@ -58,12 +58,12 @@ Example: ### Reading json coverage -GET `/:kind/:namespace/:name` +GET `/report` Example: ```json -// curl localhost:7000/api/code-coverage/Component/default/entity-name +// curl localhost:7000/api/code-coverage/report?entity=component:default/entity-name { "aggregate": { "branch": { @@ -102,12 +102,12 @@ Example: ### Coverage history -GET `/:kind/:namespace/:name/history` +GET `/history` Example ```json -// curl localhost:7000/api/code-coverage/Component/default/entity-name/history +// curl localhost:7000/api/code-coverage/history?entity=component:default/entity-name { "entity": { "kind": "Component", diff --git a/plugins/code-coverage-backend/migrations/20210302_init.js b/plugins/code-coverage-backend/migrations/20210302_init.js index 0edd455e7d..b156a9d08d 100644 --- a/plugins/code-coverage-backend/migrations/20210302_init.js +++ b/plugins/code-coverage-backend/migrations/20210302_init.js @@ -27,9 +27,7 @@ exports.up = async function up(knex) { .primary() .notNullable() .comment('The ID of the code coverage'); - table.text('entity_name').notNullable().comment('entity name'); - table.text('entity_kind').notNullable().comment('entity kind'); - table.text('entity_namespace').notNullable().comment('entity namespace'); + table.text('entity').notNullable().comment('entity string reference'); table .text('coverage') .notNullable() diff --git a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts index af734dd358..108146287d 100644 --- a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts +++ b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts @@ -17,6 +17,7 @@ import { getVoidLogger, SingleConnectionDatabaseManager, } from '@backstage/backend-common'; +import { stringifyEntityRef } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import { CodeCoverageDatabase, @@ -142,11 +143,13 @@ describe('CodeCoverageDatabase', () => { describe('getCodeCoverage', () => { it("can get coverage that's in the database", async () => { - const cov = await database.getCodeCoverage({ - name: 'test-entity', - kind: 'Component', - namespace: 'default', - }); + const cov = await database.getCodeCoverage( + stringifyEntityRef({ + name: 'test-entity', + kind: 'Component', + namespace: 'default', + }), + ); expect(cov).toEqual(coverage[1]); }); }); @@ -154,11 +157,11 @@ describe('CodeCoverageDatabase', () => { describe('getHistory', () => { it("can get history that's in the database", async () => { const cov = await database.getHistory( - { + stringifyEntityRef({ name: 'test-entity', kind: 'Component', namespace: 'default', - }, + }), 5, ); expect(cov.history.length).toEqual(2); diff --git a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts index 44109e8e2e..cb83c2f606 100644 --- a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts +++ b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts @@ -15,7 +15,7 @@ */ import { resolvePackagePath } from '@backstage/backend-common'; import { NotFoundError } from '@backstage/errors'; -import { EntityName } from '@backstage/catalog-model'; +import { parseEntityName, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; @@ -24,17 +24,15 @@ import { JsonCodeCoverage, JsonCoverageHistory } from './jsoncoverage-types'; export type RawDbCoverageRow = { id: string; - entity_name: string; - entity_namespace: string; - entity_kind: string; + entity: string; coverage: string; }; export interface CodeCoverageStore { insertCodeCoverage( coverage: JsonCodeCoverage, ): Promise<{ codeCoverageId: string }>; - getCodeCoverage(entity: EntityName): Promise<JsonCodeCoverage>; - getHistory(entity: EntityName, limit: number): Promise<JsonCoverageHistory>; + getCodeCoverage(entity: string): Promise<JsonCodeCoverage>; + getHistory(entity: string, limit: number): Promise<JsonCoverageHistory>; } const migrationsDir = resolvePackagePath( @@ -55,22 +53,22 @@ export class CodeCoverageDatabase implements CodeCoverageStore { coverage: JsonCodeCoverage, ): Promise<{ codeCoverageId: string }> { const codeCoverageId = uuid(); + this.logger.error(JSON.stringify(coverage.entity)); + const entity = stringifyEntityRef({ + kind: coverage.entity.kind, + namespace: coverage.entity.namespace, + name: coverage.entity.name, + }); await this.db<RawDbCoverageRow>('code_coverage').insert({ id: codeCoverageId, - entity_name: coverage.entity.name, - entity_kind: coverage.entity.kind, - entity_namespace: coverage.entity.namespace, + entity: entity, coverage: JSON.stringify(coverage), }); return { codeCoverageId }; } - async getCodeCoverage(entity: EntityName): Promise<JsonCodeCoverage> { + async getCodeCoverage(entity: string): Promise<JsonCodeCoverage> { const [result] = await this.db<RawDbCoverageRow>('code_coverage') - .where({ - entity_name: entity.name, - entity_kind: entity.kind, - entity_namespace: entity.namespace, - }) + .where({ entity: entity }) .orderBy('created_at', 'desc') .limit(1) .select(); @@ -87,15 +85,11 @@ export class CodeCoverageDatabase implements CodeCoverageStore { } async getHistory( - entity: EntityName, + entity: string, limit: number, ): Promise<JsonCoverageHistory> { const res = await this.db<RawDbCoverageRow>('code_coverage') - .where({ - entity_name: entity.name, - entity_kind: entity.kind, - entity_namespace: entity.namespace, - }) + .where({ entity: entity }) .orderBy('created_at', 'desc') .limit(limit) .select(); @@ -104,8 +98,13 @@ export class CodeCoverageDatabase implements CodeCoverageStore { .map(r => JSON.parse(r.coverage)) .map(c => aggregateCoverage(c)); + const entityName = parseEntityName(entity); return { - entity, + entity: { + name: entityName.name, + kind: entityName.kind, + namespace: entityName.namespace, + }, history: history, }; } diff --git a/plugins/code-coverage-backend/src/service/CoverageUtils.ts b/plugins/code-coverage-backend/src/service/CoverageUtils.ts index 0ed1561003..031e72434a 100644 --- a/plugins/code-coverage-backend/src/service/CoverageUtils.ts +++ b/plugins/code-coverage-backend/src/service/CoverageUtils.ts @@ -16,7 +16,7 @@ import { Request } from 'express'; import { UrlReader } from '@backstage/backend-common'; import { InputError, NotFoundError } from '@backstage/errors'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, EntityName } from '@backstage/catalog-model'; import { ScmIntegration, ScmIntegrations } from '@backstage/integration'; import { AggregateCoverage, diff --git a/plugins/code-coverage-backend/src/service/router.ts b/plugins/code-coverage-backend/src/service/router.ts index 3f3dcf8a1e..576bc26a31 100644 --- a/plugins/code-coverage-backend/src/service/router.ts +++ b/plugins/code-coverage-backend/src/service/router.ts @@ -33,6 +33,11 @@ import { aggregateCoverage, CoverageUtils } from './CoverageUtils'; import { Cobertura } from './converter/cobertura'; import { Jacoco } from './converter/jacoco'; import { Converter } from './converter'; +import { + EntityRef, + parseEntityName, + parseEntityRef, +} from '@backstage/catalog-model'; export interface RouterOptions { config: Config; @@ -69,19 +74,17 @@ export const makeRouter = async ( res.status(200).json({ status: 'ok' }); }); - router.get('/:kind/:namespace/:name', async (req, res) => { - const { kind, namespace, name } = req.params; - const entity = await catalogApi.getEntityByName({ kind, namespace, name }); - if (!entity) { - throw new NotFoundError( - `No entity found matching ${kind}/${namespace}/${name}`, - ); + /** + * /report?entity=component:default/mycomponent + */ + router.get('/report', async (req, res) => { + const { entity } = req.query; + const entityName = parseEntityName(entity as EntityRef); + const entityLookup = await catalogApi.getEntityByName(entityName); + if (!entityLookup) { + throw new NotFoundError(`No entity found matching ${entity}`); } - const stored = await codeCoverageDatabase.getCodeCoverage({ - kind, - namespace, - name, - }); + const stored = await codeCoverageDatabase.getCodeCoverage(entity as string); const aggregate = aggregateCoverage(stored); @@ -94,45 +97,45 @@ export const makeRouter = async ( }); }); - router.get('/:kind/:namespace/:name/history', async (req, res) => { - const { kind, namespace, name } = req.params; - const entity = await catalogApi.getEntityByName({ kind, namespace, name }); - if (!entity) { - throw new NotFoundError( - `No entity found matching ${kind}/${namespace}/${name}`, - ); + /** + * /history?entity=component:default/mycomponent + */ + router.get('/history', async (req, res) => { + const { entity } = req.query; + const entityName = parseEntityName(entity as EntityRef); + const entityLookup = await catalogApi.getEntityByName(entityName); + if (!entityLookup) { + throw new NotFoundError(`No entity found matching ${entity}`); } const { limit } = req.query; const history = await codeCoverageDatabase.getHistory( - { - kind, - namespace, - name, - }, + entity as string, parseInt(limit?.toString() || '10', 10), ); res.status(200).json(history); }); - router.get('/:kind/:namespace/:name/file-content', async (req, res) => { - const { kind, namespace, name } = req.params; - const entity = await catalogApi.getEntityByName({ kind, namespace, name }); - if (!entity) { - throw new NotFoundError( - `No entity found matching ${kind}/${namespace}/${name}`, - ); + /** + * /file-content?entity=component:default/mycomponent&path=src/some-file.go + */ + router.get('/file-content', async (req, res) => { + const { entity, path } = req.query; + const entityName = parseEntityName(entity as EntityRef); + const entityLookup = await catalogApi.getEntityByName(entityName); + if (!entityLookup) { + throw new NotFoundError(`No entity found matching ${entity}`); } - const { path } = req.query; + if (!path) { throw new InputError('Need path query parameter'); } const sourceLocation = - entity.metadata.annotations?.['backstage.io/source-location']; + entityLookup.metadata.annotations?.['backstage.io/source-location']; if (!sourceLocation) { throw new InputError( - `No "backstage.io/source-location" annotation on entity ${entity.kind}/${entity.metadata.namespace}/${entity.metadata.name}`, + `No "backstage.io/source-location" annotation on entity ${entity}`, ); } @@ -165,9 +168,17 @@ export const makeRouter = async ( res.status(200).contentType('text/plain').send(data); }); - router.post('/:kind/:namespace/:name/', async (req, res) => { - const { kind, namespace, name } = req.params; - const { coverageType } = req.query; + /** + * /report?entity=component:default/mycomponent&coverageType=cobertura + */ + router.post('/report', async (req, res) => { + const { entity, coverageType } = req.query; + const entityName = parseEntityName(entity as EntityRef); + const entityLookup = await catalogApi.getEntityByName(entityName); + if (!entityLookup) { + throw new NotFoundError(`No entity found matching ${entity}`); + } + let converter: Converter; if (!coverageType) { throw new InputError('Need coverageType query parameter'); @@ -178,18 +189,13 @@ export const makeRouter = async ( } else { throw new NotFoundError(`unsupported coverage type '${coverageType}`); } - const entity = await catalogApi.getEntityByName({ kind, namespace, name }); - if (!entity) { - throw new NotFoundError( - `No entity found matching ${kind}/${namespace}/${name}`, - ); - } + const { sourceLocation, vcs, scmFiles, body, - } = await utils.processCoveragePayload(entity, req); + } = await utils.processCoveragePayload(entityLookup, req); const files = converter.convert(body, scmFiles); if (!files || files.length === 0) { @@ -197,7 +203,7 @@ export const makeRouter = async ( } const coverage = await utils.buildCoverage( - entity, + entityLookup, sourceLocation, vcs, files, @@ -208,7 +214,7 @@ export const makeRouter = async ( links: [ { rel: 'coverage', - href: `${codecovUrl}/${kind}/${namespace}/${name}`, + href: `${codecovUrl}/report?entity=${entity}`, }, ], }); diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts index da18bde267..000ff132e9 100644 --- a/plugins/code-coverage/src/api.ts +++ b/plugins/code-coverage/src/api.ts @@ -16,7 +16,7 @@ import { createApiRef } from '@backstage/core'; import { Config } from '@backstage/config'; -import { EntityName } from '@backstage/catalog-model'; +import { EntityName, stringifyEntityRef } from '@backstage/catalog-model'; export class FetchError extends Error { get name(): string { @@ -69,33 +69,31 @@ export class CodeCoverageRestApi implements CodeCoverageApi { return await resp.text(); } - async getCoverageForEntity({ - kind, - namespace, - name, - }: EntityName): Promise<any> { - return await this.fetch<any>( - `/api/code-coverage/${kind}/${namespace}/${name}`, - ); + async getCoverageForEntity(entityName: EntityName): Promise<any> { + const entity = stringifyEntityRef(entityName); + return await this.fetch<any>(`/api/code-coverage/report?entity=${entity}`); } async getFileContentFromEntity( - { kind, namespace, name }: EntityName, + entityName: EntityName, filePath: string, ): Promise<any> { + const entity = stringifyEntityRef(entityName); return await this.fetch<any>( - `/api/code-coverage/${kind}/${namespace}/${name}/file-content?path=${filePath}`, + /// file-content?entity=component:default/mycomponent&path=src/some-file.go + `/api/code-coverage/file-content?entity=${entity}&path=${filePath}`, ); } async getCoverageHistoryForEntity( - { kind, namespace, name }: EntityName, + entityName: EntityName, limit?: number, ): Promise<any> { + const entity = stringifyEntityRef(entityName); const hasValidLimit = limit && limit > 0; return await this.fetch<any>( - `/api/code-coverage/${kind}/${namespace}/${name}/history${ - hasValidLimit ? `?limit=${limit}` : '' + `/api/code-coverage/history?entity=${entity}${ + hasValidLimit ? `&limit=${limit}` : '' }`, ); } From bf02f21eb9dcd3217382e5986c40a96108384f07 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 11:51:04 -0400 Subject: [PATCH 048/262] Address minor code style comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit move code out of `converter/index.ts`. change Converter to be an interface. remove unused function remove commented out import Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../src/service/converter/Converter.ts | 20 +++++++++++++++++++ .../src/service/converter/cobertura.ts | 6 +++--- .../src/service/converter/index.ts | 10 +++------- .../src/service/converter/jacoco.ts | 6 +++--- .../components/FileExplorer/FileContent.tsx | 14 +------------ .../components/FileExplorer/Highlighter.ts | 7 +++---- plugins/code-coverage/src/index.ts | 2 -- 7 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 plugins/code-coverage-backend/src/service/converter/Converter.ts diff --git a/plugins/code-coverage-backend/src/service/converter/Converter.ts b/plugins/code-coverage-backend/src/service/converter/Converter.ts new file mode 100644 index 0000000000..20c6920c99 --- /dev/null +++ b/plugins/code-coverage-backend/src/service/converter/Converter.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { FileEntry } from '../jsoncoverage-types'; + +export interface Converter { + convert(xml: unknown, scmFiles: Array<string>): Array<FileEntry>; +} diff --git a/plugins/code-coverage-backend/src/service/converter/cobertura.ts b/plugins/code-coverage-backend/src/service/converter/cobertura.ts index 72eeb25b56..fd3cfe9c01 100644 --- a/plugins/code-coverage-backend/src/service/converter/cobertura.ts +++ b/plugins/code-coverage-backend/src/service/converter/cobertura.ts @@ -16,11 +16,11 @@ import { BranchHit, FileEntry } from '../jsoncoverage-types'; import { CoberturaXML, InnerClass, LineHit } from './types'; import { Logger } from 'winston'; -import { Converter } from '.'; +import { Converter } from './Converter'; -export class Cobertura extends Converter { +export class Cobertura implements Converter { constructor(readonly logger: Logger) { - super(logger); + this.logger = logger; } /** diff --git a/plugins/code-coverage-backend/src/service/converter/index.ts b/plugins/code-coverage-backend/src/service/converter/index.ts index 083af10f68..8ea7a41f65 100644 --- a/plugins/code-coverage-backend/src/service/converter/index.ts +++ b/plugins/code-coverage-backend/src/service/converter/index.ts @@ -13,11 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Logger } from 'winston'; -import { FileEntry } from '../jsoncoverage-types'; -export abstract class Converter { - constructor(readonly logger: Logger) {} - - abstract convert(xml: any, scmFiles: Array<string>): Array<FileEntry>; -} +export * from './Converter'; +export { Cobertura } from './cobertura'; +export { Jacoco } from './jacoco'; diff --git a/plugins/code-coverage-backend/src/service/converter/jacoco.ts b/plugins/code-coverage-backend/src/service/converter/jacoco.ts index fe60f9378c..8dfcf0cb51 100644 --- a/plugins/code-coverage-backend/src/service/converter/jacoco.ts +++ b/plugins/code-coverage-backend/src/service/converter/jacoco.ts @@ -16,7 +16,7 @@ import { BranchHit, FileEntry } from '../jsoncoverage-types'; import { JacocoSourceFile, JacocoXML } from './types'; import { Logger } from 'winston'; -import { Converter } from '.'; +import { Converter } from './Converter'; type ParsedLine = { number: number; @@ -26,9 +26,9 @@ type ParsedLine = { covered_branches: number; }; -export class Jacoco extends Converter { +export class Jacoco implements Converter { constructor(readonly logger: Logger) { - super(logger); + this.logger = logger; } /** diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index 7b1bc2c070..358cd72f24 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { FC, useEffect } from 'react'; +import React, { FC } from 'react'; import { useApi } from '@backstage/core-api'; import { useEntity } from '@backstage/plugin-catalog-react'; import { useAsync } from 'react-use'; @@ -31,14 +31,6 @@ type Props = { coverage: FileCoverage; }; -const getContent = async (value: any) => { - let blob = value; - if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) { - blob = new Blob([value], { type: 'application/octet-stream' }); - } - return value; -}; - const useStyles = makeStyles(theme => ({ paper: { margin: 'auto', @@ -97,10 +89,6 @@ export const FileContent = ({ filename, coverage }: Props) => { ), ); - useEffect(() => { - if (value) getContent(value); - }, [value]); - const classes = useStyles(); if (loading) { diff --git a/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts b/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts index fda1a11f11..39f56200b6 100644 --- a/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts +++ b/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts @@ -20,11 +20,10 @@ import highlight from 'highlight.js'; * Given a file extension, repo name, and array of code lines, return a Promise resolving * to an array of formatted lines with html/css formatting. * - * @param {String} fileExtension The extension of the source file - * @param {String} repo The name of the code repository - * @param {Array<String>} lines The source code lines + * @param fileExtension The extension of the source file + * @param lines The source code lines * - * @returns {Promise<Array<String>>} Promise of formatted lines + * @returns Promise of formatted lines * * @see http://highlightjs.readthedocs.io/en/latest/api.html#highlight-name-value-ignore-illegals-continuation */ diff --git a/plugins/code-coverage/src/index.ts b/plugins/code-coverage/src/index.ts index 84010e64ac..7542f963b5 100644 --- a/plugins/code-coverage/src/index.ts +++ b/plugins/code-coverage/src/index.ts @@ -19,5 +19,3 @@ export { isCodeCoverageAvailable, isCodeCoverageAvailable as isPluginApplicableToEntity, } from './components/Router'; - -// export { createBackendRouter } from './backend/router'; From 5813a89427d49d9e62115d8bbbe43415bdf0a7b0 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 12:03:53 -0400 Subject: [PATCH 049/262] fix types in frontend api client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage-backend/src/index.ts | 2 ++ plugins/code-coverage/package.json | 1 + plugins/code-coverage/src/api.ts | 31 ++++++++++++------- .../components/FileExplorer/FileContent.tsx | 10 +++++- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/plugins/code-coverage-backend/src/index.ts b/plugins/code-coverage-backend/src/index.ts index 7612c392a2..12de31b541 100644 --- a/plugins/code-coverage-backend/src/index.ts +++ b/plugins/code-coverage-backend/src/index.ts @@ -15,3 +15,5 @@ */ export * from './service/router'; + +export * from './service/jsoncoverage-types'; diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 75be2cab92..47d065a092 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -26,6 +26,7 @@ "@backstage/core-api": "^0.2.12", "@backstage/dev-utils": "^0.1.11", "@backstage/plugin-catalog-react": "^0.1.0", + "@backstage/plugin-code-coverage-backend": "^0.1.0", "@backstage/theme": "^0.2.3", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts index 000ff132e9..f386fa03fe 100644 --- a/plugins/code-coverage/src/api.ts +++ b/plugins/code-coverage/src/api.ts @@ -17,6 +17,10 @@ import { createApiRef } from '@backstage/core'; import { Config } from '@backstage/config'; import { EntityName, stringifyEntityRef } from '@backstage/catalog-model'; +import { + JsonCodeCoverage, + JsonCoverageHistory, +} from '@backstage/plugin-code-coverage-backend'; export class FetchError extends Error { get name(): string { @@ -34,15 +38,15 @@ export class FetchError extends Error { export type CodeCoverageApi = { url: string; - getCoverageForEntity: (entity: EntityName) => Promise<any>; + getCoverageForEntity: (entity: EntityName) => Promise<JsonCodeCoverage>; getFileContentFromEntity: ( entity: EntityName, filePath: string, - ) => Promise<any>; + ) => Promise<string>; getCoverageHistoryForEntity: ( entity: EntityName, limit?: number, - ) => Promise<any>; + ) => Promise<JsonCoverageHistory>; }; export const codeCoverageApiRef = createApiRef<CodeCoverageApi>({ @@ -57,7 +61,7 @@ export class CodeCoverageRestApi implements CodeCoverageApi { constructor(public url: string) {} - private async fetch<T = any | string>( + private async fetch<T = unknown | string | JsonCoverageHistory>( input: string, init?: RequestInit, ): Promise<T | string> { @@ -69,18 +73,21 @@ export class CodeCoverageRestApi implements CodeCoverageApi { return await resp.text(); } - async getCoverageForEntity(entityName: EntityName): Promise<any> { + async getCoverageForEntity( + entityName: EntityName, + ): Promise<JsonCodeCoverage> { const entity = stringifyEntityRef(entityName); - return await this.fetch<any>(`/api/code-coverage/report?entity=${entity}`); + return (await this.fetch<JsonCodeCoverage>( + `/api/code-coverage/report?entity=${entity}`, + )) as JsonCodeCoverage; } async getFileContentFromEntity( entityName: EntityName, filePath: string, - ): Promise<any> { + ): Promise<string> { const entity = stringifyEntityRef(entityName); - return await this.fetch<any>( - /// file-content?entity=component:default/mycomponent&path=src/some-file.go + return await this.fetch<string>( `/api/code-coverage/file-content?entity=${entity}&path=${filePath}`, ); } @@ -88,13 +95,13 @@ export class CodeCoverageRestApi implements CodeCoverageApi { async getCoverageHistoryForEntity( entityName: EntityName, limit?: number, - ): Promise<any> { + ): Promise<JsonCoverageHistory> { const entity = stringifyEntityRef(entityName); const hasValidLimit = limit && limit > 0; - return await this.fetch<any>( + return (await this.fetch<JsonCoverageHistory>( `/api/code-coverage/history?entity=${entity}${ hasValidLimit ? `&limit=${limit}` : '' }`, - ); + )) as JsonCoverageHistory; } } diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index 358cd72f24..72c8b27a12 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -93,9 +93,17 @@ export const FileContent = ({ filename, coverage }: Props) => { if (loading) { return <Progress />; - } else if (error) { + } + if (error) { return <Alert severity="error">{error.message}</Alert>; } + if (!value) { + return ( + <Alert severity="error"> + Unable to retrieve file content for {filename} + </Alert> + ); + } const [language] = filename.split('.').slice(-1); const highlightedLines = highlightLines(language, value.split('\n')); From aa1812c580ade33553258a32e7a1f6cc6a242c8d Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 12:08:42 -0400 Subject: [PATCH 050/262] encodeURI on all params in frontend api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage/src/api.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts index f386fa03fe..1443f9de72 100644 --- a/plugins/code-coverage/src/api.ts +++ b/plugins/code-coverage/src/api.ts @@ -76,7 +76,7 @@ export class CodeCoverageRestApi implements CodeCoverageApi { async getCoverageForEntity( entityName: EntityName, ): Promise<JsonCodeCoverage> { - const entity = stringifyEntityRef(entityName); + const entity = encodeURI(stringifyEntityRef(entityName)); return (await this.fetch<JsonCodeCoverage>( `/api/code-coverage/report?entity=${entity}`, )) as JsonCodeCoverage; @@ -86,9 +86,11 @@ export class CodeCoverageRestApi implements CodeCoverageApi { entityName: EntityName, filePath: string, ): Promise<string> { - const entity = stringifyEntityRef(entityName); + const entity = encodeURI(stringifyEntityRef(entityName)); return await this.fetch<string>( - `/api/code-coverage/file-content?entity=${entity}&path=${filePath}`, + `/api/code-coverage/file-content?entity=${entity}&path=${encodeURI( + filePath, + )}`, ); } @@ -96,11 +98,11 @@ export class CodeCoverageRestApi implements CodeCoverageApi { entityName: EntityName, limit?: number, ): Promise<JsonCoverageHistory> { - const entity = stringifyEntityRef(entityName); + const entity = encodeURI(stringifyEntityRef(entityName)); const hasValidLimit = limit && limit > 0; return (await this.fetch<JsonCoverageHistory>( `/api/code-coverage/history?entity=${entity}${ - hasValidLimit ? `&limit=${limit}` : '' + hasValidLimit ? `&limit=${encodeURI(`${limit}`)}` : '' }`, )) as JsonCoverageHistory; } From 07768e8b9ede09255dd4156add5f27b44d0b36d5 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 12:22:51 -0400 Subject: [PATCH 051/262] use theme colors for trend icons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../src/service/jsoncoverage-types.ts | 2 +- .../src/service/router.ts | 6 +---- plugins/code-coverage/package.json | 1 + .../CoverageHistoryChart.tsx | 25 +++++++++++++++---- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts b/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts index f1ef3dd694..34fcf57968 100644 --- a/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts +++ b/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts @@ -23,7 +23,7 @@ export type JsonCodeCoverage = { export type JsonCoverageHistory = { entity: EntityName; - history: Array<CoverageHistory>; + history: Array<AggregateCoverage>; }; export type CoverageHistory = { diff --git a/plugins/code-coverage-backend/src/service/router.ts b/plugins/code-coverage-backend/src/service/router.ts index 576bc26a31..aba5326f5d 100644 --- a/plugins/code-coverage-backend/src/service/router.ts +++ b/plugins/code-coverage-backend/src/service/router.ts @@ -33,11 +33,7 @@ import { aggregateCoverage, CoverageUtils } from './CoverageUtils'; import { Cobertura } from './converter/cobertura'; import { Jacoco } from './converter/jacoco'; import { Converter } from './converter'; -import { - EntityRef, - parseEntityName, - parseEntityRef, -} from '@backstage/catalog-model'; +import { EntityRef, parseEntityName } from '@backstage/catalog-model'; export interface RouterOptions { config: Config; diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 47d065a092..e17d894b43 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -30,6 +30,7 @@ "@backstage/theme": "^0.2.3", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", + "@material-ui/styles": "^4.11.0", "@material-ui/lab": "4.0.0-alpha.45", "@types/highlightjs": "^10.1.0", "highlight.js": "^10.6.0", diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx index a7bfeceb19..3e8d9b6387 100644 --- a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx @@ -19,6 +19,7 @@ import { Box, Card, CardContent, + makeStyles, MenuItem, Select, Typography, @@ -42,15 +43,26 @@ import { Alert } from '@material-ui/lab'; import TrendingDownIcon from '@material-ui/icons/TrendingDown'; import TrendingUpIcon from '@material-ui/icons/TrendingUp'; import TrendingFlatIcon from '@material-ui/icons/TrendingFlat'; +import { BackstageTheme } from '@backstage/theme'; +import { ClassNameMap } from '@material-ui/styles'; type Coverage = 'line' | 'branch'; -const getTrendIcon = (trend: number) => { +const useStyles = makeStyles<BackstageTheme>(theme => ({ + trendDown: { + color: theme.palette.status.warning, + }, + trendUp: { + color: theme.palette.status.ok, + }, +})); + +const getTrendIcon = (trend: number, classes: ClassNameMap) => { switch (true) { case trend > 0: - return <TrendingUpIcon style={{ color: 'green' }} />; + return <TrendingUpIcon className={classes.trendUp} />; case trend < 0: - return <TrendingDownIcon style={{ color: 'red' }} />; + return <TrendingDownIcon className={classes.trendDown} />; case trend === 0: default: return <TrendingFlatIcon />; @@ -72,11 +84,14 @@ export const CoverageHistoryChart = () => { name: entity.metadata.name, }), ); + const classes = useStyles(); if (loadingHistory) { return <Progress />; } else if (errorHistory) { return <Alert severity="error">{errorHistory.message}</Alert>; + } else if (!valueHistory) { + return <Alert severity="warning">No history found.</Alert>; } if (!valueHistory.history.length) { @@ -123,7 +138,7 @@ export const CoverageHistoryChart = () => { </Box> <Box px={6} display="flex"> <Box display="flex" mr={4}> - {getTrendIcon(lineTrend)} + {getTrendIcon(lineTrend, classes)} <Typography> Current line: {latestCoverage.line.percentage}%<br />( {Math.floor(lineTrend)}% change over{' '} @@ -131,7 +146,7 @@ export const CoverageHistoryChart = () => { </Typography> </Box> <Box display="flex"> - {getTrendIcon(branchTrend)} + {getTrendIcon(branchTrend, classes)} <Typography> Current branch: {latestCoverage.branch.percentage}%<br />( {Math.floor(branchTrend)}% change over{' '} From bd0e05632a6131a87b96e73bc253dafd82d3981c Mon Sep 17 00:00:00 2001 From: Rickard Dybeck <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 12:45:43 -0400 Subject: [PATCH 052/262] use theme spacing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../code-coverage/src/components/FileExplorer/CoverageRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx index a4eabf715d..99d173a9ce 100644 --- a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx @@ -24,7 +24,7 @@ const useStyles = makeStyles(theme => ({ color: `${theme.palette.grey[500]}`, fontSize: '90%', borderRight: `1px solid ${theme.palette.grey[500]}`, - paddingRight: '8px', + paddingRight: theme.spacing(1), textAlign: 'right', }, hitCountCell: { From 8e09c5fa2d9d394355822cf6426d2b1e573a2f49 Mon Sep 17 00:00:00 2001 From: Rickard Dybeck <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 12:46:33 -0400 Subject: [PATCH 053/262] remove string interpolation for theme spacing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../code-coverage/src/components/FileExplorer/CoverageRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx index 99d173a9ce..659bd4cb1d 100644 --- a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx @@ -32,7 +32,7 @@ const useStyles = makeStyles(theme => ({ borderRight: `1px solid ${theme.palette.grey[500]}`, textAlign: 'center', color: 'white', // need to enforce this color since it needs to stand out against colored background - paddingLeft: `${theme.spacing(1)}`, + paddingLeft: theme.spacing(1), paddingRight: `${theme.spacing(1)}`, }, countRoundedRectangle: { From 25b40a66a673674fe8ebe737972b022a60e59a75 Mon Sep 17 00:00:00 2001 From: Rickard Dybeck <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 12:47:31 -0400 Subject: [PATCH 054/262] don't wrap color in string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../code-coverage/src/components/FileExplorer/CoverageRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx index 659bd4cb1d..b213ad05de 100644 --- a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx @@ -42,7 +42,7 @@ const useStyles = makeStyles(theme => ({ width: '50px', }, hitCountRoundedRectangle: { - backgroundColor: `${green[500]}`, + backgroundColor: green[500], }, notHitCountRoundedRectangle: { backgroundColor: `${red[500]}`, From 10f5e0c7ec7de06f378a194de7d999dee33215e6 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 12:55:10 -0400 Subject: [PATCH 055/262] fix error panels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage/package.json | 5 +- plugins/code-coverage/src/api.ts | 5 +- .../CoverageHistoryChart.tsx | 7 ++- .../components/FileExplorer/FileContent.tsx | 4 +- .../components/FileExplorer/FileExplorer.tsx | 31 ++++++---- yarn.lock | 61 +------------------ 6 files changed, 36 insertions(+), 77 deletions(-) diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index e17d894b43..eabd961f4b 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -22,16 +22,17 @@ "dependencies": { "@backstage/catalog-model": "^0.7.2", "@backstage/config": "^0.1.3", - "@backstage/core": "^0.6.2", + "@backstage/core": "^0.7.5", "@backstage/core-api": "^0.2.12", "@backstage/dev-utils": "^0.1.11", + "@backstage/errors": "^0.1.0", "@backstage/plugin-catalog-react": "^0.1.0", "@backstage/plugin-code-coverage-backend": "^0.1.0", "@backstage/theme": "^0.2.3", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/styles": "^4.11.0", - "@material-ui/lab": "4.0.0-alpha.45", + "@material-ui/lab": "4.0.0-alpha.57", "@types/highlightjs": "^10.1.0", "highlight.js": "^10.6.0", "react": "^16.13.1", diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts index 1443f9de72..1a1bd542ae 100644 --- a/plugins/code-coverage/src/api.ts +++ b/plugins/code-coverage/src/api.ts @@ -21,6 +21,7 @@ import { JsonCodeCoverage, JsonCoverageHistory, } from '@backstage/plugin-code-coverage-backend'; +import { ResponseError } from '@backstage/errors'; export class FetchError extends Error { get name(): string { @@ -66,7 +67,9 @@ export class CodeCoverageRestApi implements CodeCoverageApi { init?: RequestInit, ): Promise<T | string> { const resp = await fetch(`${this.url}${input}`, init); - if (!resp.ok) throw await FetchError.forResponse(resp); + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } if (resp.headers.get('content-type')?.includes('application/json')) { return await resp.json(); } diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx index 3e8d9b6387..4f4f442315 100644 --- a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx @@ -38,7 +38,7 @@ import { useAsync } from 'react-use'; import { useApi } from '@backstage/core-api'; import { useEntity } from '@backstage/plugin-catalog-react'; import { codeCoverageApiRef } from '../../api'; -import { Progress } from '@backstage/core'; +import { Progress, ResponseErrorPanel } from '@backstage/core'; import { Alert } from '@material-ui/lab'; import TrendingDownIcon from '@material-ui/icons/TrendingDown'; import TrendingUpIcon from '@material-ui/icons/TrendingUp'; @@ -88,8 +88,9 @@ export const CoverageHistoryChart = () => { if (loadingHistory) { return <Progress />; - } else if (errorHistory) { - return <Alert severity="error">{errorHistory.message}</Alert>; + } + if (errorHistory) { + return <ResponseErrorPanel error={errorHistory} />; } else if (!valueHistory) { return <Alert severity="warning">No history found.</Alert>; } diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index 72c8b27a12..6844557307 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -23,12 +23,12 @@ import { Progress } from '@backstage/core'; import { Alert } from '@material-ui/lab'; import { makeStyles, Paper } from '@material-ui/core'; import { highlightLines } from './Highlighter'; -import { FileCoverage } from './FileExplorer'; import CoverageRow from './CoverageRow'; +import { FileEntry } from '@backstage/plugin-code-coverage-backend'; type Props = { filename: string; - coverage: FileCoverage; + coverage: FileEntry; }; const useStyles = makeStyles(theme => ({ diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx index 11baa419f4..da20ba0ed6 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx @@ -16,7 +16,12 @@ import { useApi } from '@backstage/core-api'; import { useEntity } from '@backstage/plugin-catalog-react'; -import { Progress, Table, TableColumn } from '@backstage/core'; +import { + Progress, + ResponseErrorPanel, + Table, + TableColumn, +} from '@backstage/core'; import { Box, Card, @@ -28,15 +33,10 @@ import { import React, { Fragment, useEffect, useState } from 'react'; import { useAsync } from 'react-use'; import { codeCoverageApiRef } from '../../api'; -import { Alert } from '@material-ui/lab'; import DescriptionIcon from '@material-ui/icons/Description'; import { FileContent } from './FileContent'; - -export type FileCoverage = { - filename: string; - branchHits: { [branch: number]: number }; - lineHits: { [line: number]: number }; -}; +import { Alert } from '@material-ui/lab'; +import { FileEntry } from '@backstage/plugin-code-coverage-backend'; type FileStructureObject = Record<string, any>; @@ -101,7 +101,7 @@ const formatInitialData = (value: any) => { coverage: value.aggregate.line.percentage, missing: value.aggregate.line.missed, tracked: value.aggregate.line.available, - files: value.files.map((fc: FileCoverage) => { + files: value.files.map((fc: FileEntry) => { return { path: '', filename: fc.filename, @@ -145,7 +145,12 @@ export const FileExplorer = () => { if (loading) { return <Progress />; } else if (error) { - return <Alert severity="error">{error.message}</Alert>; + return <ResponseErrorPanel error={error} />; + } + if (!value) { + return ( + <Alert severity="warning">No code coverage found for ${entity}</Alert> + ); } const moveDownIntoPath = (path: string) => { @@ -230,10 +235,14 @@ export const FileExplorer = () => { const pathArray = curPath.split('/'); const lastPathElementIndex = pathArray.length - 1; - const fileCoverage = value.files.find((f: FileCoverage) => + const fileCoverage = value.files.find((f: FileEntry) => f.filename.endsWith(curFile), ); + if (!fileCoverage) { + return null; + } + return ( <Box mt={8}> <Card> diff --git a/yarn.lock b/yarn.lock index baf771b351..79f7d85b38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1616,14 +1616,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.13.10" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" - integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.10.3": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.13.10" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== @@ -1738,49 +1731,6 @@ yaml "^1.9.2" yup "^0.29.3" -"@backstage/core@^0.6.2": - version "0.6.3" - resolved "https://registry.npmjs.org/@backstage/core/-/core-0.6.3.tgz#574ca46ab59e18af07fcf3a248c4428d4dfcc302" - integrity sha512-OSpnvotyCkb6fL02T1Z5TLcogRlOzVIH8YBfNlKeo/Xo/JnlVp1uSpQxCWjAW/lzGK5gp6oh3ezFRjm69mTwSA== - dependencies: - "@backstage/config" "^0.1.3" - "@backstage/core-api" "^0.2.11" - "@backstage/theme" "^0.2.3" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@testing-library/react-hooks" "^3.4.2" - "@types/dagre" "^0.7.44" - "@types/prop-types" "^15.7.3" - "@types/react" "^16.9" - "@types/react-sparklines" "^1.7.0" - "@types/react-text-truncate" "^0.14.0" - classnames "^2.2.6" - clsx "^1.1.0" - d3-selection "^2.0.0" - d3-shape "^2.0.0" - d3-zoom "^2.0.0" - dagre "^0.8.5" - immer "^8.0.1" - lodash "^4.17.15" - material-table "^1.69.1" - prop-types "^15.7.2" - qs "^6.9.4" - rc-progress "^3.0.0" - react "^16.12.0" - react-dom "^16.12.0" - react-helmet "6.1.0" - react-hook-form "^6.6.0" - react-markdown "^5.0.2" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-sparklines "^1.7.0" - react-syntax-highlighter "^13.5.1" - react-text-truncate "^0.16.0" - react-use "^15.3.3" - remark-gfm "^1.0.0" - zen-observable "^0.8.15" - "@backstage/plugin-catalog-backend@^0.6.5": version "0.6.7" resolved "https://registry.npmjs.org/@backstage/plugin-catalog-backend/-/plugin-catalog-backend-0.6.7.tgz#97d0ed6db6aeb04e09ed0fee05e76bacf66cc179" @@ -3917,7 +3867,7 @@ react-transition-group "^4.0.0" rifm "^0.7.0" -"@material-ui/styles@^4.10.0", "@material-ui/styles@^4.11.3", "@material-ui/styles@^4.9.6": +"@material-ui/styles@^4.10.0", "@material-ui/styles@^4.11.0", "@material-ui/styles@^4.11.3", "@material-ui/styles@^4.9.6": version "4.11.3" resolved "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.3.tgz#1b8d97775a4a643b53478c895e3f2a464e8916f2" integrity sha512-HzVzCG+PpgUGMUYEJ2rTEmQYeonGh41BYfILNFb/1ueqma+p1meSdu4RX6NjxYBMhf7k+jgfHFTTz+L1SXL/Zg== @@ -15322,11 +15272,6 @@ immer@8.0.1: resolved "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== -immer@^8.0.1: - version "8.0.4" - resolved "https://registry.npmjs.org/immer/-/immer-8.0.4.tgz#3a21605a4e2dded852fb2afd208ad50969737b7a" - integrity sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ== - immer@^9.0.1: version "9.0.1" resolved "https://registry.npmjs.org/immer/-/immer-9.0.1.tgz#1116368e051f9a0fd188c5136b6efb74ed69c57f" @@ -22374,7 +22319,7 @@ react-string-replace@^0.4.1: dependencies: lodash "^4.17.4" -react-syntax-highlighter@^13.5.0, react-syntax-highlighter@^13.5.1: +react-syntax-highlighter@^13.5.0: version "13.5.3" resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-13.5.3.tgz#9712850f883a3e19eb858cf93fad7bb357eea9c6" integrity sha512-crPaF+QGPeHNIblxxCdf2Lg936NAHKhNhuMzRL3F9ct6aYXL3NcZtCL0Rms9+qVo6Y1EQLdXGypBNSbPL/r+qg== From 57a10500cd9d471d41a1bbaeb6094f3ffe7148cd Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 13:06:01 -0400 Subject: [PATCH 056/262] add code-coverage annotation to well-known-annotations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../software-catalog/well-known-annotations.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/features/software-catalog/well-known-annotations.md b/docs/features/software-catalog/well-known-annotations.md index 0053c14b79..5cfe8f39ef 100644 --- a/docs/features/software-catalog/well-known-annotations.md +++ b/docs/features/software-catalog/well-known-annotations.md @@ -273,6 +273,20 @@ project within your organization. Specifying this annotation may enable SonarQube related features in Backstage for that entity. +### backstage.io/code-coverage + +```yaml +# Example: +metadata: + annotations: + backstage.io/code-coverage: scm-only +``` + +The value of this annotation controls the code-coverage backstage plugin. If set +to smc-only the plugin will only take into account files stored in source +control (e.g. ignoring generated code). If set to any other non-false:y value +all files covered by a coverage report will be taken into account. + ## Deprecated Annotations The following annotations are deprecated, and only listed here to aid in From 9132deaa768a01ec4259554d8e743a8d7845714e Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 13:58:31 -0400 Subject: [PATCH 057/262] fix file content explorer, use getEntitySourceLocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../code-coverage-backend/src/service/router.ts | 14 +++++++++----- .../src/components/FileExplorer/FileContent.tsx | 6 +++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/plugins/code-coverage-backend/src/service/router.ts b/plugins/code-coverage-backend/src/service/router.ts index aba5326f5d..f2e34cd07a 100644 --- a/plugins/code-coverage-backend/src/service/router.ts +++ b/plugins/code-coverage-backend/src/service/router.ts @@ -33,7 +33,11 @@ import { aggregateCoverage, CoverageUtils } from './CoverageUtils'; import { Cobertura } from './converter/cobertura'; import { Jacoco } from './converter/jacoco'; import { Converter } from './converter'; -import { EntityRef, parseEntityName } from '@backstage/catalog-model'; +import { + EntityRef, + getEntitySourceLocation, + parseEntityName, +} from '@backstage/catalog-model'; export interface RouterOptions { config: Config; @@ -127,20 +131,20 @@ export const makeRouter = async ( throw new InputError('Need path query parameter'); } - const sourceLocation = - entityLookup.metadata.annotations?.['backstage.io/source-location']; + const sourceLocation = getEntitySourceLocation(entityLookup); + if (!sourceLocation) { throw new InputError( `No "backstage.io/source-location" annotation on entity ${entity}`, ); } - const vcs = scm.byUrl(sourceLocation); + const vcs = scm.byUrl(sourceLocation.target); if (!vcs) { throw new InputError(`Unable to determine SCM from ${sourceLocation}`); } - const scmTree = await urlReader.readTree(sourceLocation); + const scmTree = await urlReader.readTree(sourceLocation.target); const scmFile = (await scmTree.files()).find(f => f.path === path); if (!scmFile) { res.status(400).json({ diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index 6844557307..e4ade53f37 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -19,7 +19,7 @@ import { useApi } from '@backstage/core-api'; import { useEntity } from '@backstage/plugin-catalog-react'; import { useAsync } from 'react-use'; import { codeCoverageApiRef } from '../../api'; -import { Progress } from '@backstage/core'; +import { Progress, ResponseErrorPanel } from '@backstage/core'; import { Alert } from '@material-ui/lab'; import { makeStyles, Paper } from '@material-ui/core'; import { highlightLines } from './Highlighter'; @@ -95,11 +95,11 @@ export const FileContent = ({ filename, coverage }: Props) => { return <Progress />; } if (error) { - return <Alert severity="error">{error.message}</Alert>; + return <ResponseErrorPanel error={error} />; } if (!value) { return ( - <Alert severity="error"> + <Alert severity="warning"> Unable to retrieve file content for {filename} </Alert> ); From b64e81b80d4cd7e50d9beb6bd55ef3253025e048 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 13:59:04 -0400 Subject: [PATCH 058/262] use discoveryApi to find code-coverage-backend api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage/src/api.ts | 25 ++++++++++++------------- plugins/code-coverage/src/plugin.ts | 6 +++--- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts index 1a1bd542ae..2fa2dab05a 100644 --- a/plugins/code-coverage/src/api.ts +++ b/plugins/code-coverage/src/api.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createApiRef } from '@backstage/core'; +import { createApiRef, DiscoveryApi } from '@backstage/core'; import { Config } from '@backstage/config'; import { EntityName, stringifyEntityRef } from '@backstage/catalog-model'; import { @@ -38,7 +38,7 @@ export class FetchError extends Error { } export type CodeCoverageApi = { - url: string; + discovery: DiscoveryApi; getCoverageForEntity: (entity: EntityName) => Promise<JsonCodeCoverage>; getFileContentFromEntity: ( entity: EntityName, @@ -56,17 +56,18 @@ export const codeCoverageApiRef = createApiRef<CodeCoverageApi>({ }); export class CodeCoverageRestApi implements CodeCoverageApi { - static fromConfig(config: Config) { - return new CodeCoverageRestApi(config.getString('backend.baseUrl')); - } + url: string = ''; - constructor(public url: string) {} + constructor(public discovery: DiscoveryApi) {} private async fetch<T = unknown | string | JsonCoverageHistory>( - input: string, + path: string, init?: RequestInit, ): Promise<T | string> { - const resp = await fetch(`${this.url}${input}`, init); + if (!this.url) { + this.url = await this.discovery.getBaseUrl('code-coverage'); + } + const resp = await fetch(`${this.url}${path}`, init); if (!resp.ok) { throw await ResponseError.fromResponse(resp); } @@ -81,7 +82,7 @@ export class CodeCoverageRestApi implements CodeCoverageApi { ): Promise<JsonCodeCoverage> { const entity = encodeURI(stringifyEntityRef(entityName)); return (await this.fetch<JsonCodeCoverage>( - `/api/code-coverage/report?entity=${entity}`, + `/report?entity=${entity}`, )) as JsonCodeCoverage; } @@ -91,9 +92,7 @@ export class CodeCoverageRestApi implements CodeCoverageApi { ): Promise<string> { const entity = encodeURI(stringifyEntityRef(entityName)); return await this.fetch<string>( - `/api/code-coverage/file-content?entity=${entity}&path=${encodeURI( - filePath, - )}`, + `/file-content?entity=${entity}&path=${encodeURI(filePath)}`, ); } @@ -104,7 +103,7 @@ export class CodeCoverageRestApi implements CodeCoverageApi { const entity = encodeURI(stringifyEntityRef(entityName)); const hasValidLimit = limit && limit > 0; return (await this.fetch<JsonCoverageHistory>( - `/api/code-coverage/history?entity=${entity}${ + `/history?entity=${entity}${ hasValidLimit ? `&limit=${encodeURI(`${limit}`)}` : '' }`, )) as JsonCoverageHistory; diff --git a/plugins/code-coverage/src/plugin.ts b/plugins/code-coverage/src/plugin.ts index fa5f31d9cc..68e8291bc4 100644 --- a/plugins/code-coverage/src/plugin.ts +++ b/plugins/code-coverage/src/plugin.ts @@ -14,10 +14,10 @@ * limitations under the License. */ import { - configApiRef, createApiFactory, createPlugin, createRoutableExtension, + discoveryApiRef, } from '@backstage/core'; import { codeCoverageApiRef, CodeCoverageRestApi } from './api'; @@ -31,8 +31,8 @@ export const codeCoveragePlugin = createPlugin({ apis: [ createApiFactory({ api: codeCoverageApiRef, - deps: { configApi: configApiRef }, - factory: ({ configApi }) => CodeCoverageRestApi.fromConfig(configApi), + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new CodeCoverageRestApi(discoveryApi), }), ], }); From d4b2b0869d849589476f466653abcbb07566c9cd Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 14:07:12 -0400 Subject: [PATCH 059/262] use getEntitySourceLocation in CoverageUtils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../src/service/CoverageUtils.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/plugins/code-coverage-backend/src/service/CoverageUtils.ts b/plugins/code-coverage-backend/src/service/CoverageUtils.ts index 031e72434a..4850ac9b1b 100644 --- a/plugins/code-coverage-backend/src/service/CoverageUtils.ts +++ b/plugins/code-coverage-backend/src/service/CoverageUtils.ts @@ -16,7 +16,11 @@ import { Request } from 'express'; import { UrlReader } from '@backstage/backend-common'; import { InputError, NotFoundError } from '@backstage/errors'; -import { Entity, EntityName } from '@backstage/catalog-model'; +import { + Entity, + getEntitySourceLocation, + stringifyEntityRef, +} from '@backstage/catalog-model'; import { ScmIntegration, ScmIntegrations } from '@backstage/integration'; import { AggregateCoverage, @@ -96,11 +100,18 @@ export class CoverageUtils { let scmFiles: string[] = []; if (enforceScmFiles) { - sourceLocation = - entity.metadata.annotations?.['backstage.io/source-location']; + try { + const sl = getEntitySourceLocation(entity); + sourceLocation = sl.target; + } catch (e: unknown) { + // TODO: logging + } + if (!sourceLocation) { throw new InputError( - `No "backstage.io/source-location" annotation on entity ${entity.kind}/${entity.metadata.namespace}/${entity.metadata.name}`, + `No "backstage.io/source-location" annotation on entity ${stringifyEntityRef( + entity, + )}`, ); } From 50ce122fca75f39cf96640e8b8f9ce4fd854bfcc Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 15:07:20 -0400 Subject: [PATCH 060/262] Stop using React.FC, use CardHeader instead of Box MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../CoverageHistoryChart.tsx | 108 ++++++++---------- .../components/FileExplorer/CoverageRow.tsx | 4 +- .../components/FileExplorer/FileContent.tsx | 4 +- .../components/FileExplorer/FileExplorer.tsx | 80 ++++++------- 4 files changed, 87 insertions(+), 109 deletions(-) diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx index 4f4f442315..f9927a17d3 100644 --- a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx @@ -19,9 +19,8 @@ import { Box, Card, CardContent, + CardHeader, makeStyles, - MenuItem, - Select, Typography, } from '@material-ui/core'; import { @@ -97,16 +96,10 @@ export const CoverageHistoryChart = () => { if (!valueHistory.history.length) { return ( - <Box> - <Card> - <CardContent> - <Box mb={2} display="flex" justifyContent="space-between"> - <Typography variant="h5">History</Typography> - </Box> - No coverage history found - </CardContent> - </Card> - </Box> + <Card> + <CardHeader title="History" /> + <CardContent>No coverage history found</CardContent> + </Card> ); } @@ -128,58 +121,47 @@ export const CoverageHistoryChart = () => { const branchTrend = getTrendForCoverage('branch'); return ( - <Box> - <Card> - <CardContent> - <Box mb={2} display="flex" justifyContent="space-between"> - <Typography variant="h5">History</Typography> - <Select> - <MenuItem>7</MenuItem> - </Select> + <Card> + <CardHeader title="History" /> + <CardContent> + <Box px={6} display="flex"> + <Box display="flex" mr={4}> + {getTrendIcon(lineTrend, classes)} + <Typography> + Current line: {latestCoverage.line.percentage}%<br />( + {Math.floor(lineTrend)}% change over {valueHistory.history.length}{' '} + builds) + </Typography> </Box> - <Box px={6} display="flex"> - <Box display="flex" mr={4}> - {getTrendIcon(lineTrend, classes)} - <Typography> - Current line: {latestCoverage.line.percentage}%<br />( - {Math.floor(lineTrend)}% change over{' '} - {valueHistory.history.length} builds) - </Typography> - </Box> - <Box display="flex"> - {getTrendIcon(branchTrend, classes)} - <Typography> - Current branch: {latestCoverage.branch.percentage}%<br />( - {Math.floor(branchTrend)}% change over{' '} - {valueHistory.history.length} builds) - </Typography> - </Box> + <Box display="flex"> + {getTrendIcon(branchTrend, classes)} + <Typography> + Current branch: {latestCoverage.branch.percentage}%<br />( + {Math.floor(branchTrend)}% change over{' '} + {valueHistory.history.length} builds) + </Typography> </Box> - <ResponsiveContainer width="100%" height={300}> - <LineChart - data={valueHistory.history} - margin={{ right: 48, top: 32 }} - > - <CartesianGrid strokeDasharray="3 3" /> - <XAxis dataKey="timestamp" /> - <YAxis dataKey="line.percentage" /> - <YAxis dataKey="branch.percentage" /> - <Tooltip /> - <Legend /> - <Line - type="monotone" - dataKey="branch.percentage" - stroke="#8884d8" - /> - <Line - type="monotone" - dataKey="line.percentage" - stroke="#82ca9d" - /> - </LineChart> - </ResponsiveContainer> - </CardContent> - </Card> - </Box> + </Box> + <ResponsiveContainer width="100%" height={300}> + <LineChart + data={valueHistory.history} + margin={{ right: 48, top: 32 }} + > + <CartesianGrid strokeDasharray="3 3" /> + <XAxis dataKey="timestamp" /> + <YAxis dataKey="line.percentage" /> + <YAxis dataKey="branch.percentage" /> + <Tooltip /> + <Legend /> + <Line + type="monotone" + dataKey="branch.percentage" + stroke="#8884d8" + /> + <Line type="monotone" dataKey="line.percentage" stroke="#82ca9d" /> + </LineChart> + </ResponsiveContainer> + </CardContent> + </Card> ); }; diff --git a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx index b213ad05de..4af4fbbf4e 100644 --- a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { FC } from 'react'; +import React from 'react'; // styles import { makeStyles } from '@material-ui/core'; @@ -65,7 +65,7 @@ type CodeRowProps = { lineContent: string; lineHits?: number | null; }; -const CodeRow: FC<CodeRowProps> = ({ +const CodeRow = ({ lineNumber, lineContent, lineHits = null, diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index e4ade53f37..703489f587 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { FC } from 'react'; +import React from 'react'; import { useApi } from '@backstage/core-api'; import { useEntity } from '@backstage/plugin-catalog-react'; import { useAsync } from 'react-use'; @@ -53,7 +53,7 @@ type FormattedLinesProps = { highlightedLines: string[]; lineHits: Record<number, number>; }; -const FormattedLines: FC<FormattedLinesProps> = ({ +const FormattedLines = ({ highlightedLines, lineHits, }: FormattedLinesProps) => { diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx index da20ba0ed6..704edcdf15 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx @@ -26,9 +26,9 @@ import { Box, Card, CardContent, + CardHeader, Modal, Tooltip, - Typography, } from '@material-ui/core'; import React, { Fragment, useEffect, useState } from 'react'; import { useAsync } from 'react-use'; @@ -244,46 +244,42 @@ export const FileExplorer = () => { } return ( - <Box mt={8}> - <Card> - <CardContent> - <Box mb={2} display="flex" justifyContent="space-between"> - <Typography variant="h5">Explore Files</Typography> - </Box> - <Box mb={2} display="flex"> - {pathArray.map((pathElement, idx) => ( - <Fragment key={pathElement || 'root'}> - <div - role="button" - tabIndex={idx} - style={{ - color: `${idx !== lastPathElementIndex && 'lightblue'}`, - cursor: `${idx !== lastPathElementIndex && 'pointer'}`, - }} - onKeyDown={() => moveUpIntoPath(pathElement)} - onClick={() => moveUpIntoPath(pathElement)} - > - {pathElement || 'root'} - </div> - <div>{'\u00A0/\u00A0'}</div> - </Fragment> - ))} - </Box> - <Table - emptyContent={<>No files found</>} - data={tableData || []} - columns={columns} - /> - <Modal - open={modalOpen} - onClick={event => event.stopPropagation()} - onClose={() => setModalOpen(false)} - style={{ overflow: 'scroll' }} - > - <FileContent filename={curFile} coverage={fileCoverage} /> - </Modal> - </CardContent> - </Card> - </Box> + <Card> + <CardHeader title="Explore Files" /> + <CardContent> + <Box mb={2} display="flex"> + {pathArray.map((pathElement, idx) => ( + <Fragment key={pathElement || 'root'}> + <div + role="button" + tabIndex={idx} + style={{ + color: `${idx !== lastPathElementIndex && 'lightblue'}`, + cursor: `${idx !== lastPathElementIndex && 'pointer'}`, + }} + onKeyDown={() => moveUpIntoPath(pathElement)} + onClick={() => moveUpIntoPath(pathElement)} + > + {pathElement || 'root'} + </div> + <div>{'\u00A0/\u00A0'}</div> + </Fragment> + ))} + </Box> + <Table + emptyContent={<>No files found</>} + data={tableData || []} + columns={columns} + /> + <Modal + open={modalOpen} + onClick={event => event.stopPropagation()} + onClose={() => setModalOpen(false)} + style={{ overflow: 'scroll' }} + > + <FileContent filename={curFile} coverage={fileCoverage} /> + </Modal> + </CardContent> + </Card> ); }; From 24acde68321711350f975cfd03b966949e64cf4e Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 15:10:22 -0400 Subject: [PATCH 061/262] set dependency on entity for FileContent#useAsync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../code-coverage/src/components/FileExplorer/FileContent.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index 703489f587..0d7f495daf 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -87,6 +87,7 @@ export const FileContent = ({ filename, coverage }: Props) => { }, filename, ), + [entity], ); const classes = useStyles(); From eb6a17971af5d241b3c257f89673bcc0e6d62f75 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 15:16:16 -0400 Subject: [PATCH 062/262] Fix theming of CoverageRow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../src/components/FileExplorer/CoverageRow.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx index 4af4fbbf4e..8b9da9d9e8 100644 --- a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx @@ -17,7 +17,6 @@ import React from 'react'; // styles import { makeStyles } from '@material-ui/core'; -import { red, green } from '@material-ui/core/colors'; const useStyles = makeStyles(theme => ({ lineNumberCell: { @@ -33,7 +32,7 @@ const useStyles = makeStyles(theme => ({ textAlign: 'center', color: 'white', // need to enforce this color since it needs to stand out against colored background paddingLeft: theme.spacing(1), - paddingRight: `${theme.spacing(1)}`, + paddingRight: theme.spacing(1), }, countRoundedRectangle: { borderRadius: '45px', @@ -42,10 +41,10 @@ const useStyles = makeStyles(theme => ({ width: '50px', }, hitCountRoundedRectangle: { - backgroundColor: green[500], + backgroundColor: `${theme.palette.success.main}`, }, notHitCountRoundedRectangle: { - backgroundColor: `${red[500]}`, + backgroundColor: `${theme.palette.error.main}`, }, codeLine: { paddingLeft: `${theme.spacing(1)}`, @@ -53,10 +52,10 @@ const useStyles = makeStyles(theme => ({ fontSize: '90%', }, hitCodeLine: { - backgroundColor: `${green[100]}`, + backgroundColor: `${theme.palette.success.main}`, }, notHitCodeLine: { - backgroundColor: `${red[100]}`, + backgroundColor: `${theme.palette.error.main}`, }, })); From fd2fe42176520b1b519d9fa80f98bc234b5d6d4a Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 15:20:14 -0400 Subject: [PATCH 063/262] FileContent: remove unnecessary styling on paper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../code-coverage/src/components/FileExplorer/FileContent.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index 0d7f495daf..afaff61340 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -36,7 +36,6 @@ const useStyles = makeStyles(theme => ({ margin: 'auto', top: '2em', width: '80%', - backgroundColor: theme.palette.background.paper, border: '2px solid #000', boxShadow: theme.shadows[5], padding: theme.spacing(2, 4, 3), From bf7a3aee587e10cb689412cc6cd0248d76169d63 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 15:54:26 -0400 Subject: [PATCH 064/262] may not be necessary to set source-location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage-backend/README.md | 2 +- plugins/code-coverage/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index 3229dc940f..157b5e8ddb 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -16,7 +16,7 @@ There's a feature to only include files that are in VCS in the coverage report, backstage.io/code-coverage: scm-only ``` -Note: This requires the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location) to be set. +Note: It may be required to set the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location), however this should generally not be needed. ## API diff --git a/plugins/code-coverage/README.md b/plugins/code-coverage/README.md index b93ad7a091..c271b9ff36 100644 --- a/plugins/code-coverage/README.md +++ b/plugins/code-coverage/README.md @@ -16,4 +16,4 @@ There's a feature to only include files that are in VCS in the coverage report, backstage.io/code-coverage: scm-only ``` -Note: This requires the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location) to be set. +Note: It may be required to set the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location), however this should generally not be needed. From 12a45d22adf4d9eff2856e4ee99000e8f8c4cc46 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Mon, 19 Apr 2021 16:31:25 -0400 Subject: [PATCH 065/262] fix some tsc issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage/dev/index.tsx | 4 ++-- plugins/code-coverage/src/api.ts | 1 - plugins/code-coverage/src/dev/index.tsx | 5 +++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/code-coverage/dev/index.tsx b/plugins/code-coverage/dev/index.tsx index 9eabafb976..69ff4bcda2 100644 --- a/plugins/code-coverage/dev/index.tsx +++ b/plugins/code-coverage/dev/index.tsx @@ -15,12 +15,12 @@ */ import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; -import { codeCoveragePlugin, CodeCoveragePage } from '../src/plugin'; +import { codeCoveragePlugin, EntityCodeCoverageContent } from '../src/plugin'; createDevApp() .registerPlugin(codeCoveragePlugin) .addPage({ - element: <CodeCoveragePage />, + element: <EntityCodeCoverageContent />, title: 'Root Page', }) .render(); diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts index 2fa2dab05a..d168f50d95 100644 --- a/plugins/code-coverage/src/api.ts +++ b/plugins/code-coverage/src/api.ts @@ -15,7 +15,6 @@ */ import { createApiRef, DiscoveryApi } from '@backstage/core'; -import { Config } from '@backstage/config'; import { EntityName, stringifyEntityRef } from '@backstage/catalog-model'; import { JsonCodeCoverage, diff --git a/plugins/code-coverage/src/dev/index.tsx b/plugins/code-coverage/src/dev/index.tsx index 5c944b097a..4bbcdf07c5 100644 --- a/plugins/code-coverage/src/dev/index.tsx +++ b/plugins/code-coverage/src/dev/index.tsx @@ -17,12 +17,13 @@ import { createDevApp } from '@backstage/dev-utils'; import { codeCoveragePlugin } from '../plugin'; import { codeCoverageApiRef, CodeCoverageRestApi } from '../api'; +import { discoveryApiRef } from '@backstage/core-api'; createDevApp() .registerPlugin(codeCoveragePlugin) .registerApi({ api: codeCoverageApiRef, - deps: {}, - factory: () => new CodeCoverageRestApi('http://localhost:3000'), + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new CodeCoverageRestApi(discoveryApi), }) .render(); From eb35e81128a641db4872a3cced572df8582dd8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Tue, 20 Apr 2021 14:19:23 +0200 Subject: [PATCH 066/262] update express-promise-router to the repo standard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage-backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 79de777dfa..8bcce8784d 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -29,7 +29,7 @@ "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", "express": "^4.17.1", - "express-promise-router": "^3.0.3", + "express-promise-router": "^4.1.0", "express-xml-bodyparser": "^0.3.0", "knex": "^0.95.1", "uuid": "^8.3.2", From 9ed45248b918c5c6209d1a219c5c6ea45e905f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Tue, 20 Apr 2021 14:34:26 +0200 Subject: [PATCH 067/262] update vocab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .github/styles/vocab.txt | 3 +++ plugins/code-coverage-backend/README.md | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 5a778b5ea3..a12f638a74 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -10,6 +10,7 @@ Chai Changesets Chanwit Cloudformation +Cobertura Codecov Codehilite Config @@ -34,6 +35,7 @@ Hackathons Heroku Hostname Iain +JaCoCo JavaScript Kaewkasi Knex @@ -78,6 +80,7 @@ Tolerations WWW Weaveworks Webpack +XML Zalando Zhou abc diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index 157b5e8ddb..8d1491ef14 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -20,9 +20,9 @@ Note: It may be required to set the [`backstage.io/source-location` annotation]( ## API -### Adding cobertura report +### Adding a Cobertura report -POST a cobertura xml to `/report` +POST a Cobertura XML file to `/report` Example: @@ -38,9 +38,9 @@ Example: } ``` -### Adding jacoco report +### Adding a JaCoCo report -POST a jacoco xml to `/report` +POST a JaCoCo XML file to `/report` Example: From 22a9a88b46c591cef3304020dd0d05b2bf348989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Tue, 20 Apr 2021 14:49:17 +0200 Subject: [PATCH 068/262] move to devdependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/code-coverage/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index eabd961f4b..a4a9cc5584 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -33,7 +33,6 @@ "@material-ui/icons": "^4.9.1", "@material-ui/styles": "^4.11.0", "@material-ui/lab": "4.0.0-alpha.57", - "@types/highlightjs": "^10.1.0", "highlight.js": "^10.6.0", "react": "^16.13.1", "react-dom": "^16.13.1", @@ -48,6 +47,7 @@ "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", + "@types/highlightjs": "^10.1.0", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", "@types/recharts": "^1.8.15", From 7f521339b992636b8ed1e87a55db41a2ceeee5ca Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Tue, 20 Apr 2021 10:50:10 -0400 Subject: [PATCH 069/262] fix test fixture Signed-off-by: alde <r.dybeck@gmail.com> --- .../code-coverage-backend/src/service/CoverageUtils.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts b/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts index 5a5cffbced..4a96e67338 100644 --- a/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts +++ b/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts @@ -305,7 +305,8 @@ describe('CodeCoverageUtils', () => { namespace: 'test', annotations: { 'backstage.io/code-coverage': 'scm-only', - 'backstage.io/source-location': 'https://github.com/example/test/', + 'backstage.io/source-location': + 'url:https://github.com/example/test/', }, }, apiVersion: 'backstage.io/v1alpha1', From 50bd7ce58ace0673668f5b07e11961cd661708f2 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Tue, 20 Apr 2021 11:48:23 -0400 Subject: [PATCH 070/262] align dependency versions Signed-off-by: alde <r.dybeck@gmail.com> --- plugins/code-coverage/package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index a4a9cc5584..974e93e430 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -24,15 +24,14 @@ "@backstage/config": "^0.1.3", "@backstage/core": "^0.7.5", "@backstage/core-api": "^0.2.12", - "@backstage/dev-utils": "^0.1.11", "@backstage/errors": "^0.1.0", "@backstage/plugin-catalog-react": "^0.1.0", "@backstage/plugin-code-coverage-backend": "^0.1.0", - "@backstage/theme": "^0.2.3", + "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/styles": "^4.11.0", - "@material-ui/lab": "4.0.0-alpha.57", + "@material-ui/lab": "4.0.0-alpha.45", "highlight.js": "^10.6.0", "react": "^16.13.1", "react-dom": "^16.13.1", @@ -42,14 +41,15 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.6.1", - "@backstage/test-utils": "^0.1.7", + "@backstage/cli": "^0.6.8", + "@backstage/dev-utils": "^0.1.13", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^10.4.1", + "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", "@types/highlightjs": "^10.1.0", "@types/jest": "^26.0.7", - "@types/node": "^12.0.0", + "@types/node": "^14.14.32", "@types/recharts": "^1.8.15", "cross-fetch": "^3.0.6", "msw": "^0.21.2" From 5fa7f679339f8f04e58b40a39e5fd7a663619a72 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Tue, 20 Apr 2021 12:15:49 -0400 Subject: [PATCH 071/262] remove src/dev/ folder Signed-off-by: alde <r.dybeck@gmail.com> --- plugins/code-coverage/src/dev/index.tsx | 29 ------------------------- 1 file changed, 29 deletions(-) delete mode 100644 plugins/code-coverage/src/dev/index.tsx diff --git a/plugins/code-coverage/src/dev/index.tsx b/plugins/code-coverage/src/dev/index.tsx deleted file mode 100644 index 4bbcdf07c5..0000000000 --- a/plugins/code-coverage/src/dev/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { createDevApp } from '@backstage/dev-utils'; -import { codeCoveragePlugin } from '../plugin'; -import { codeCoverageApiRef, CodeCoverageRestApi } from '../api'; -import { discoveryApiRef } from '@backstage/core-api'; - -createDevApp() - .registerPlugin(codeCoveragePlugin) - .registerApi({ - api: codeCoverageApiRef, - deps: { discoveryApi: discoveryApiRef }, - factory: ({ discoveryApi }) => new CodeCoverageRestApi(discoveryApi), - }) - .render(); From 87a82498b9bc506ef9ef03f84c23a5b9dd45cb7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 21 Apr 2021 12:45:31 +0200 Subject: [PATCH 072/262] final fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../well-known-annotations.md | 6 +- plugins/code-coverage-backend/README.md | 16 +- .../migrations/20210302_init.js | 25 +++- plugins/code-coverage-backend/package.json | 13 +- plugins/code-coverage-backend/src/index.ts | 2 - .../src/service/CodeCoverageDatabase.test.ts | 14 +- .../src/service/CodeCoverageDatabase.ts | 22 ++- .../src/service/CoverageUtils.ts | 6 +- .../src/service/converter/Converter.ts | 2 +- .../src/service/converter/cobertura.ts | 4 +- .../src/service/converter/jacoco.ts | 6 +- .../src/service/router.ts | 9 +- .../src/service/standaloneServer.ts | 20 ++- .../{jsoncoverage-types.ts => types.ts} | 0 plugins/code-coverage/README.md | 12 +- plugins/code-coverage/package.json | 10 +- plugins/code-coverage/src/api.ts | 29 +--- .../CoverageHistoryChart.tsx | 31 ++-- .../{CoverageRow.tsx => CodeRow.tsx} | 8 +- .../components/FileExplorer/FileContent.tsx | 15 +- .../components/FileExplorer/FileExplorer.tsx | 10 +- plugins/code-coverage/src/types.ts | 71 +++++++++ yarn.lock | 138 +----------------- 23 files changed, 205 insertions(+), 264 deletions(-) rename plugins/code-coverage-backend/src/service/{jsoncoverage-types.ts => types.ts} (100%) rename plugins/code-coverage/src/components/FileExplorer/{CoverageRow.tsx => CodeRow.tsx} (98%) create mode 100644 plugins/code-coverage/src/types.ts diff --git a/docs/features/software-catalog/well-known-annotations.md b/docs/features/software-catalog/well-known-annotations.md index 5cfe8f39ef..67b92bd941 100644 --- a/docs/features/software-catalog/well-known-annotations.md +++ b/docs/features/software-catalog/well-known-annotations.md @@ -283,9 +283,9 @@ metadata: ``` The value of this annotation controls the code-coverage backstage plugin. If set -to smc-only the plugin will only take into account files stored in source -control (e.g. ignoring generated code). If set to any other non-false:y value -all files covered by a coverage report will be taken into account. +to `scm-only`, the plugin will only take into account files stored in source +control (e.g. ignoring generated code). If set to `enabled`, all files covered +by a coverage report will be taken into account. ## Deprecated Annotations diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index 8d1491ef14..101bee3e3f 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -1,19 +1,23 @@ -# code-coverage +# code-coverage-backend -This is the backend part of the code-coverage plugin. It takes care of processing various coverage formats and standardizing them into a single json format, used by the frontend. +This is the backend part of the `code-coverage` plugin. It takes care of processing various coverage formats and standardizing them into a single json format, used by the frontend. ## Configuring your entity In order to use this plugin, you must set the `backstage.io/code-coverage` annotation. ```yaml -backstage.io/code-coverage: enabled +metadata: + annotations: + backstage.io/code-coverage: enabled ``` There's a feature to only include files that are in VCS in the coverage report, this is helpful to not count generated files for example. To enable this set the `backstage.io/code-coverage` annotation to `scm-only`. ```yaml -backstage.io/code-coverage: scm-only +metadata: + annotations: + backstage.io/code-coverage: scm-only ``` Note: It may be required to set the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location), however this should generally not be needed. @@ -31,7 +35,7 @@ Example: { "links": [ { - "href": "http://localhost:7000/api/code-coverage/Component/default/entity-name", + "href": "http://localhost:7000/api/code-coverage/report?entity=component:default/entity-name", "rel": "coverage" } ] @@ -49,7 +53,7 @@ Example: { "links": [ { - "href": "http://localhost:7000/api/code-coverage/Component/default/entity-name", + "href": "http://localhost:7000/api/code-coverage/report?entity=component:default/entity-name", "rel": "coverage" } ] diff --git a/plugins/code-coverage-backend/migrations/20210302_init.js b/plugins/code-coverage-backend/migrations/20210302_init.js index b156a9d08d..538f658948 100644 --- a/plugins/code-coverage-backend/migrations/20210302_init.js +++ b/plugins/code-coverage-backend/migrations/20210302_init.js @@ -20,14 +20,23 @@ * @param {import('knex').Knex} knex */ exports.up = async function up(knex) { + // Note for the reader: the knex increments types automatically make it a + // primary column, whether you like it or not. That's why the id column is + // not marked as primary as one might have expected; it's only used for + // lookups by ID. Because, SQLite and MySQL don't return RETURNING on + // inserts ... so we want a manually generated key for lookups (an uuid), + // and also an index for ordering guarantees :) await knex.schema.createTable('code_coverage', table => { table.comment('The table of code coverage'); table - .uuid('id') - .primary() + .bigIncrements('index') .notNullable() - .comment('The ID of the code coverage'); - table.text('entity').notNullable().comment('entity string reference'); + .comment('An insert counter to ensure ordering'); + table.uuid('id').notNullable().comment('The ID of the code coverage'); + table + .text('entity') + .notNullable() + .comment('The entity ref that this code coverage applies to'); table .text('coverage') .notNullable() @@ -37,6 +46,9 @@ exports.up = async function up(knex) { .defaultTo(knex.fn.now()) .notNullable() .comment('The timestamp when this entry was created'); + table.index('index', 'code_coverage_index_idx'); + table.index('id', 'code_coverage_id_idx'); + table.index('entity', 'code_coverage_entity_idx'); }); }; @@ -44,5 +56,10 @@ exports.up = async function up(knex) { * @param {import('knex').Knex} knex */ exports.down = async function down(knex) { + await knex.schema.alterTable('code_coverage', table => { + table.dropIndex([], 'code_coverage_index_idx'); + table.dropIndex([], 'code_coverage_id_idx'); + table.dropIndex([], 'code_coverage_entity_idx'); + }); await knex.schema.dropTable('code_coverage'); }; diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 8bcce8784d..1e7903b016 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -19,13 +19,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.5.4", - "@backstage/catalog-client": "^0.3.6", - "@backstage/catalog-model": "^0.7.2", - "@backstage/config": "^0.1.3", + "@backstage/backend-common": "^0.6.2", + "@backstage/catalog-client": "^0.3.10", + "@backstage/catalog-model": "^0.7.7", + "@backstage/config": "^0.1.4", "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.5.0", - "@backstage/plugin-catalog-backend": "^0.6.5", + "@backstage/integration": "^0.5.1", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", "express": "^4.17.1", @@ -37,7 +36,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.2", + "@backstage/cli": "^0.6.8", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.21.2", diff --git a/plugins/code-coverage-backend/src/index.ts b/plugins/code-coverage-backend/src/index.ts index 12de31b541..7612c392a2 100644 --- a/plugins/code-coverage-backend/src/index.ts +++ b/plugins/code-coverage-backend/src/index.ts @@ -15,5 +15,3 @@ */ export * from './service/router'; - -export * from './service/jsoncoverage-types'; diff --git a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts index 108146287d..688eeb4ba2 100644 --- a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts +++ b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.test.ts @@ -13,17 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - getVoidLogger, - SingleConnectionDatabaseManager, -} from '@backstage/backend-common'; +import { SingleConnectionDatabaseManager } from '@backstage/backend-common'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import { CodeCoverageDatabase, CodeCoverageStore, } from './CodeCoverageDatabase'; -import { JsonCodeCoverage } from './jsoncoverage-types'; +import { JsonCodeCoverage } from './types'; const db = SingleConnectionDatabaseManager.fromConfig( new ConfigReader({ @@ -103,10 +100,9 @@ let database: CodeCoverageStore; describe('CodeCoverageDatabase', () => { beforeAll(async () => { const client = await db.getClient(); - database = await CodeCoverageDatabase.create(client, getVoidLogger()); - database.insertCodeCoverage(coverage[0]); - await new Promise(r => setTimeout(r, 1000)); - database.insertCodeCoverage(coverage[1]); + database = await CodeCoverageDatabase.create(client); + await database.insertCodeCoverage(coverage[0]); + await database.insertCodeCoverage(coverage[1]); }); describe('insertCodeCoverage', () => { diff --git a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts index cb83c2f606..390fd815f1 100644 --- a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts +++ b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts @@ -18,15 +18,15 @@ import { NotFoundError } from '@backstage/errors'; import { parseEntityName, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; -import { Logger } from 'winston'; import { aggregateCoverage } from './CoverageUtils'; -import { JsonCodeCoverage, JsonCoverageHistory } from './jsoncoverage-types'; +import { JsonCodeCoverage, JsonCoverageHistory } from './types'; export type RawDbCoverageRow = { id: string; entity: string; coverage: string; }; + export interface CodeCoverageStore { insertCodeCoverage( coverage: JsonCodeCoverage, @@ -39,44 +39,49 @@ const migrationsDir = resolvePackagePath( '@backstage/plugin-code-coverage-backend', 'migrations', ); + export class CodeCoverageDatabase implements CodeCoverageStore { - static async create(knex: Knex, logger: Logger): Promise<CodeCoverageStore> { + static async create(knex: Knex): Promise<CodeCoverageStore> { await knex.migrate.latest({ directory: migrationsDir, }); - return new CodeCoverageDatabase(knex, logger); + return new CodeCoverageDatabase(knex); } - constructor(private readonly db: Knex, private readonly logger: Logger) {} + constructor(private readonly db: Knex) {} async insertCodeCoverage( coverage: JsonCodeCoverage, ): Promise<{ codeCoverageId: string }> { const codeCoverageId = uuid(); - this.logger.error(JSON.stringify(coverage.entity)); const entity = stringifyEntityRef({ kind: coverage.entity.kind, namespace: coverage.entity.namespace, name: coverage.entity.name, }); + await this.db<RawDbCoverageRow>('code_coverage').insert({ id: codeCoverageId, entity: entity, coverage: JSON.stringify(coverage), }); + return { codeCoverageId }; } + async getCodeCoverage(entity: string): Promise<JsonCodeCoverage> { const [result] = await this.db<RawDbCoverageRow>('code_coverage') .where({ entity: entity }) - .orderBy('created_at', 'desc') + .orderBy('index', 'desc') .limit(1) .select(); + if (!result) { throw new NotFoundError( `No coverage for entity '${JSON.stringify(entity)}' found`, ); } + try { return JSON.parse(result.coverage); } catch (error) { @@ -90,7 +95,7 @@ export class CodeCoverageDatabase implements CodeCoverageStore { ): Promise<JsonCoverageHistory> { const res = await this.db<RawDbCoverageRow>('code_coverage') .where({ entity: entity }) - .orderBy('created_at', 'desc') + .orderBy('index', 'desc') .limit(limit) .select(); @@ -99,6 +104,7 @@ export class CodeCoverageDatabase implements CodeCoverageStore { .map(c => aggregateCoverage(c)); const entityName = parseEntityName(entity); + return { entity: { name: entityName.name, diff --git a/plugins/code-coverage-backend/src/service/CoverageUtils.ts b/plugins/code-coverage-backend/src/service/CoverageUtils.ts index 4850ac9b1b..f41a1d05a0 100644 --- a/plugins/code-coverage-backend/src/service/CoverageUtils.ts +++ b/plugins/code-coverage-backend/src/service/CoverageUtils.ts @@ -22,11 +22,7 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { ScmIntegration, ScmIntegrations } from '@backstage/integration'; -import { - AggregateCoverage, - FileEntry, - JsonCodeCoverage, -} from './jsoncoverage-types'; +import { AggregateCoverage, FileEntry, JsonCodeCoverage } from './types'; export const calculatePercentage = ( available: number, diff --git a/plugins/code-coverage-backend/src/service/converter/Converter.ts b/plugins/code-coverage-backend/src/service/converter/Converter.ts index 20c6920c99..43d9855e61 100644 --- a/plugins/code-coverage-backend/src/service/converter/Converter.ts +++ b/plugins/code-coverage-backend/src/service/converter/Converter.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { FileEntry } from '../jsoncoverage-types'; +import { FileEntry } from '../types'; export interface Converter { convert(xml: unknown, scmFiles: Array<string>): Array<FileEntry>; diff --git a/plugins/code-coverage-backend/src/service/converter/cobertura.ts b/plugins/code-coverage-backend/src/service/converter/cobertura.ts index fd3cfe9c01..02ac187387 100644 --- a/plugins/code-coverage-backend/src/service/converter/cobertura.ts +++ b/plugins/code-coverage-backend/src/service/converter/cobertura.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BranchHit, FileEntry } from '../jsoncoverage-types'; +import { BranchHit, FileEntry } from '../types'; import { CoberturaXML, InnerClass, LineHit } from './types'; import { Logger } from 'winston'; import { Converter } from './Converter'; @@ -63,7 +63,7 @@ export class Cobertura implements Converter { }); const currentFile = scmFiles.find(f => f.endsWith(packageAndFilename)); - this.logger.info(`matched ${packageAndFilename} to ${currentFile}`); + this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`); if ( scmFiles.length === 0 || (Object.keys(lineHits).length > 0 && currentFile) diff --git a/plugins/code-coverage-backend/src/service/converter/jacoco.ts b/plugins/code-coverage-backend/src/service/converter/jacoco.ts index 8dfcf0cb51..4c554fec91 100644 --- a/plugins/code-coverage-backend/src/service/converter/jacoco.ts +++ b/plugins/code-coverage-backend/src/service/converter/jacoco.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BranchHit, FileEntry } from '../jsoncoverage-types'; +import { BranchHit, FileEntry } from '../types'; import { JacocoSourceFile, JacocoXML } from './types'; import { Logger } from 'winston'; import { Converter } from './Converter'; @@ -35,7 +35,7 @@ export class Jacoco implements Converter { * Converts jacoco into shared json coverage format * * @param xml jacoco xml object - * @param scmFiles list of files that are commited to SCM + * @param scmFiles list of files that are committed to SCM */ convert(xml: JacocoXML, scmFiles: Array<string>): Array<FileEntry> { const jscov: Array<FileEntry> = []; @@ -64,7 +64,7 @@ export class Jacoco implements Converter { const packageAndFilename = `${packageName}/${fileName}`; const currentFile = scmFiles.find(f => f.endsWith(packageAndFilename)); - this.logger.info(`matched ${packageAndFilename} to ${currentFile}`); + this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`); if (Object.keys(lineHits).length > 0 && currentFile) { jscov.push({ filename: currentFile, diff --git a/plugins/code-coverage-backend/src/service/router.ts b/plugins/code-coverage-backend/src/service/router.ts index f2e34cd07a..78aeab313c 100644 --- a/plugins/code-coverage-backend/src/service/router.ts +++ b/plugins/code-coverage-backend/src/service/router.ts @@ -58,7 +58,6 @@ export const makeRouter = async ( const codeCoverageDatabase = await CodeCoverageDatabase.create( await database.getClient(), - logger, ); const codecovUrl = await discovery.getExternalBaseUrl('code-coverage'); const catalogApi = new CatalogClient({ discoveryApi: discovery }); @@ -147,8 +146,8 @@ export const makeRouter = async ( const scmTree = await urlReader.readTree(sourceLocation.target); const scmFile = (await scmTree.files()).find(f => f.path === path); if (!scmFile) { - res.status(400).json({ - message: "couldn't find file in SCM", + res.status(404).json({ + message: "Couldn't find file in SCM", file: path, scm: vcs.title, }); @@ -157,7 +156,7 @@ export const makeRouter = async ( const content = await scmFile?.content(); if (!content) { res.status(400).json({ - message: "couldn't process content of file in SCM", + message: "Couldn't process content of file in SCM", file: path, scm: vcs.title, }); @@ -187,7 +186,7 @@ export const makeRouter = async ( } else if (coverageType === 'cobertura') { converter = new Cobertura(logger); } else { - throw new NotFoundError(`unsupported coverage type '${coverageType}`); + throw new InputError(`Unsupported coverage type '${coverageType}`); } const { diff --git a/plugins/code-coverage-backend/src/service/standaloneServer.ts b/plugins/code-coverage-backend/src/service/standaloneServer.ts index 8a3c4eaea1..2fb9627936 100644 --- a/plugins/code-coverage-backend/src/service/standaloneServer.ts +++ b/plugins/code-coverage-backend/src/service/standaloneServer.ts @@ -22,9 +22,9 @@ import { useHotMemoize, } from '@backstage/backend-common'; import { Server } from 'http'; +import knexFactory from 'knex'; import { Logger } from 'winston'; import { createRouter } from './router'; -import { DatabaseManager } from '@backstage/plugin-catalog-backend'; export interface ServerOptions { port: number; @@ -38,13 +38,23 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'code-coverage-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const db = useHotMemoize(module, () => - DatabaseManager.createInMemoryDatabaseConnection(), - ); + const db = useHotMemoize(module, () => { + const knex = knexFactory({ + client: 'sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }); + + knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { + resource.run('PRAGMA foreign_keys = ON', () => {}); + }); + + return knex; + }); logger.debug('Starting application server...'); const router = await createRouter({ - database: { getClient: () => db }, + database: { getClient: async () => db }, config, discovery: SingleHostDiscovery.fromConfig(config), urlReader: UrlReaders.default({ logger, config }), diff --git a/plugins/code-coverage-backend/src/service/jsoncoverage-types.ts b/plugins/code-coverage-backend/src/service/types.ts similarity index 100% rename from plugins/code-coverage-backend/src/service/jsoncoverage-types.ts rename to plugins/code-coverage-backend/src/service/types.ts diff --git a/plugins/code-coverage/README.md b/plugins/code-coverage/README.md index c271b9ff36..8903668507 100644 --- a/plugins/code-coverage/README.md +++ b/plugins/code-coverage/README.md @@ -1,19 +1,23 @@ # code-coverage -This is the frontend part of the code-coverage plugin. It takes care of processing various coverage formats and standardizing them into a single json format, used by the frontend. +This is the frontend part of the code-coverage plugin. It displays code coverage summaries for your entities. ## Configuring your entity -In order to use this plugin, you must set the `backstage.io/code-coverage` annotation. +In order to use this plugin, you must set the `backstage.io/code-coverage` annotation on entities for which coverage ingestion has been enabled. ```yaml -backstage.io/code-coverage: enabled +metadata: + annotations: + backstage.io/code-coverage: enabled ``` There's a feature to only include files that are in VCS in the coverage report, this is helpful to not count generated files for example. To enable this set the `backstage.io/code-coverage` annotation to `scm-only`. ```yaml -backstage.io/code-coverage: scm-only +metadata: + annotations: + backstage.io/code-coverage: scm-only ``` Note: It may be required to set the [`backstage.io/source-location` annotation](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location), however this should generally not be needed. diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 974e93e430..1d02da3dea 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -20,13 +20,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.7.2", - "@backstage/config": "^0.1.3", + "@backstage/catalog-model": "^0.7.7", + "@backstage/config": "^0.1.4", "@backstage/core": "^0.7.5", - "@backstage/core-api": "^0.2.12", - "@backstage/errors": "^0.1.0", - "@backstage/plugin-catalog-react": "^0.1.0", - "@backstage/plugin-code-coverage-backend": "^0.1.0", + "@backstage/errors": "^0.1.1", + "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/code-coverage/src/api.ts b/plugins/code-coverage/src/api.ts index d168f50d95..6331f8020f 100644 --- a/plugins/code-coverage/src/api.ts +++ b/plugins/code-coverage/src/api.ts @@ -14,27 +14,10 @@ * limitations under the License. */ -import { createApiRef, DiscoveryApi } from '@backstage/core'; import { EntityName, stringifyEntityRef } from '@backstage/catalog-model'; -import { - JsonCodeCoverage, - JsonCoverageHistory, -} from '@backstage/plugin-code-coverage-backend'; +import { createApiRef, DiscoveryApi } from '@backstage/core'; import { ResponseError } from '@backstage/errors'; - -export class FetchError extends Error { - get name(): string { - return this.constructor.name; - } - - static async forResponse(resp: Response): Promise<FetchError> { - return new FetchError( - `Request failed with status code ${ - resp.status - }.\nReason: ${await resp.text()}`, - ); - } -} +import { JsonCodeCoverage, JsonCoverageHistory } from './types'; export type CodeCoverageApi = { discovery: DiscoveryApi; @@ -79,7 +62,7 @@ export class CodeCoverageRestApi implements CodeCoverageApi { async getCoverageForEntity( entityName: EntityName, ): Promise<JsonCodeCoverage> { - const entity = encodeURI(stringifyEntityRef(entityName)); + const entity = encodeURIComponent(stringifyEntityRef(entityName)); return (await this.fetch<JsonCodeCoverage>( `/report?entity=${entity}`, )) as JsonCodeCoverage; @@ -89,7 +72,7 @@ export class CodeCoverageRestApi implements CodeCoverageApi { entityName: EntityName, filePath: string, ): Promise<string> { - const entity = encodeURI(stringifyEntityRef(entityName)); + const entity = encodeURIComponent(stringifyEntityRef(entityName)); return await this.fetch<string>( `/file-content?entity=${entity}&path=${encodeURI(filePath)}`, ); @@ -99,11 +82,11 @@ export class CodeCoverageRestApi implements CodeCoverageApi { entityName: EntityName, limit?: number, ): Promise<JsonCoverageHistory> { - const entity = encodeURI(stringifyEntityRef(entityName)); + const entity = encodeURIComponent(stringifyEntityRef(entityName)); const hasValidLimit = limit && limit > 0; return (await this.fetch<JsonCoverageHistory>( `/history?entity=${entity}${ - hasValidLimit ? `&limit=${encodeURI(`${limit}`)}` : '' + hasValidLimit ? `&limit=${encodeURIComponent(String(limit))}` : '' }`, )) as JsonCoverageHistory; } diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx index f9927a17d3..7bb4648f6f 100644 --- a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx @@ -14,7 +14,9 @@ * limitations under the License. */ -import React from 'react'; +import { Progress, ResponseErrorPanel, useApi } from '@backstage/core'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { BackstageTheme } from '@backstage/theme'; import { Box, Card, @@ -23,27 +25,24 @@ import { makeStyles, Typography, } from '@material-ui/core'; +import TrendingDownIcon from '@material-ui/icons/TrendingDown'; +import TrendingFlatIcon from '@material-ui/icons/TrendingFlat'; +import TrendingUpIcon from '@material-ui/icons/TrendingUp'; +import { Alert } from '@material-ui/lab'; +import { ClassNameMap } from '@material-ui/styles'; +import React from 'react'; +import { useAsync } from 'react-use'; import { - LineChart, - XAxis, - YAxis, - Tooltip, + CartesianGrid, Legend, Line, - CartesianGrid, + LineChart, ResponsiveContainer, + Tooltip, + XAxis, + YAxis, } from 'recharts'; -import { useAsync } from 'react-use'; -import { useApi } from '@backstage/core-api'; -import { useEntity } from '@backstage/plugin-catalog-react'; import { codeCoverageApiRef } from '../../api'; -import { Progress, ResponseErrorPanel } from '@backstage/core'; -import { Alert } from '@material-ui/lab'; -import TrendingDownIcon from '@material-ui/icons/TrendingDown'; -import TrendingUpIcon from '@material-ui/icons/TrendingUp'; -import TrendingFlatIcon from '@material-ui/icons/TrendingFlat'; -import { BackstageTheme } from '@backstage/theme'; -import { ClassNameMap } from '@material-ui/styles'; type Coverage = 'line' | 'branch'; diff --git a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx b/plugins/code-coverage/src/components/FileExplorer/CodeRow.tsx similarity index 98% rename from plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx rename to plugins/code-coverage/src/components/FileExplorer/CodeRow.tsx index 8b9da9d9e8..bd982b0f6b 100644 --- a/plugins/code-coverage/src/components/FileExplorer/CoverageRow.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/CodeRow.tsx @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -// styles +import React from 'react'; import { makeStyles } from '@material-ui/core'; const useStyles = makeStyles(theme => ({ @@ -64,7 +63,8 @@ type CodeRowProps = { lineContent: string; lineHits?: number | null; }; -const CodeRow = ({ + +export const CodeRow = ({ lineNumber, lineContent, lineHits = null, @@ -98,5 +98,3 @@ const CodeRow = ({ </tr> ); }; - -export default CodeRow; diff --git a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx index afaff61340..b43874123d 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileContent.tsx @@ -14,17 +14,16 @@ * limitations under the License. */ -import React from 'react'; -import { useApi } from '@backstage/core-api'; +import { Progress, ResponseErrorPanel, useApi } from '@backstage/core'; import { useEntity } from '@backstage/plugin-catalog-react'; +import { makeStyles, Paper } from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import React from 'react'; import { useAsync } from 'react-use'; import { codeCoverageApiRef } from '../../api'; -import { Progress, ResponseErrorPanel } from '@backstage/core'; -import { Alert } from '@material-ui/lab'; -import { makeStyles, Paper } from '@material-ui/core'; +import { FileEntry } from '../../types'; +import { CodeRow } from './CodeRow'; import { highlightLines } from './Highlighter'; -import CoverageRow from './CoverageRow'; -import { FileEntry } from '@backstage/plugin-code-coverage-backend'; type Props = { filename: string; @@ -61,7 +60,7 @@ const FormattedLines = ({ {highlightedLines.map((lineContent, idx) => { const line = idx + 1; return ( - <CoverageRow + <CodeRow key={line} lineNumber={line} lineContent={lineContent} diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx index 704edcdf15..b49b78c5dc 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx @@ -14,14 +14,14 @@ * limitations under the License. */ -import { useApi } from '@backstage/core-api'; -import { useEntity } from '@backstage/plugin-catalog-react'; import { Progress, ResponseErrorPanel, Table, TableColumn, + useApi, } from '@backstage/core'; +import { useEntity } from '@backstage/plugin-catalog-react'; import { Box, Card, @@ -30,13 +30,13 @@ import { Modal, Tooltip, } from '@material-ui/core'; +import DescriptionIcon from '@material-ui/icons/Description'; +import { Alert } from '@material-ui/lab'; import React, { Fragment, useEffect, useState } from 'react'; import { useAsync } from 'react-use'; import { codeCoverageApiRef } from '../../api'; -import DescriptionIcon from '@material-ui/icons/Description'; +import { FileEntry } from '../../types'; import { FileContent } from './FileContent'; -import { Alert } from '@material-ui/lab'; -import { FileEntry } from '@backstage/plugin-code-coverage-backend'; type FileStructureObject = Record<string, any>; diff --git a/plugins/code-coverage/src/types.ts b/plugins/code-coverage/src/types.ts new file mode 100644 index 0000000000..34fcf57968 --- /dev/null +++ b/plugins/code-coverage/src/types.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { EntityName } from '@backstage/catalog-model'; + +export type JsonCodeCoverage = { + metadata: CoverageMetadata; + entity: EntityName; + files: Array<FileEntry>; +}; + +export type JsonCoverageHistory = { + entity: EntityName; + history: Array<AggregateCoverage>; +}; + +export type CoverageHistory = { + line: { + available: number; + covered: number; + }; + branch: BranchHit; +}; + +export type CoverageMetadata = { + vcs: { + type: string; + location: string; + }; + generationTime: number; +}; + +export type BranchHit = { + covered: number; + missed: number; + available: number; +}; + +export type FileEntry = { + filename: string; + lineHits: Record<number, number>; + branchHits: Record<number, BranchHit>; +}; + +export type AggregateCoverage = { + timestamp: number; + line: { + available: number; + covered: number; + missed: number; + percentage: number; + }; + branch: { + available: number; + covered: number; + missed: number; + percentage: number; + }; +}; diff --git a/yarn.lock b/yarn.lock index 79f7d85b38..f614a7713a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1616,7 +1616,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.13.10" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== @@ -1679,95 +1679,6 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@backstage/backend-common@^0.5.4": - version "0.5.6" - resolved "https://registry.npmjs.org/@backstage/backend-common/-/backend-common-0.5.6.tgz#e49840eaa6738f6697319ccdfff04ce40cc54b72" - integrity sha512-BzKlcTZLAVDpH87fi2TCWIFO9DfVdaPIIZ8gZSorCuLLErG4X7CS/zQiujJZ/zD5HGtO2QB57fuRkwjBMhJhhw== - dependencies: - "@backstage/cli-common" "^0.1.1" - "@backstage/config" "^0.1.2" - "@backstage/config-loader" "^0.5.1" - "@backstage/integration" "^0.5.1" - "@octokit/rest" "^18.0.12" - "@types/cors" "^2.8.6" - "@types/dockerode" "^3.2.1" - "@types/express" "^4.17.6" - archiver "^5.0.2" - compression "^1.7.4" - concat-stream "^2.0.0" - cors "^2.8.5" - cross-fetch "^3.0.6" - dockerode "^3.2.1" - express "^4.17.1" - express-promise-router "^3.0.3" - fs-extra "^9.0.1" - git-url-parse "^11.4.4" - helmet "^4.0.0" - isomorphic-git "^1.8.0" - knex "^0.95.1" - lodash "^4.17.15" - logform "^2.1.1" - minimatch "^3.0.4" - minimist "^1.2.5" - morgan "^1.10.0" - selfsigned "^1.10.7" - stoppable "^1.1.0" - tar "^6.0.5" - unzipper "^0.10.11" - winston "^3.2.1" - -"@backstage/config-loader@^0.5.1": - version "0.5.1" - resolved "https://registry.npmjs.org/@backstage/config-loader/-/config-loader-0.5.1.tgz#a80f2047e209d2f41b17ad715c632ab142385b39" - integrity sha512-PmwXERs5BIf77sUIg3Fhp/elkR6ELj0czmpUgP4cuEdtazi0WcmdjCUC2DjgsKJWvYggsL1o372QKHh/M5AMTQ== - dependencies: - "@backstage/cli-common" "^0.1.1" - "@backstage/config" "^0.1.1" - ajv "^7.0.3" - fs-extra "^9.0.0" - json-schema "^0.2.5" - json-schema-merge-allof "^0.7.0" - typescript-json-schema "^0.47.0" - yaml "^1.9.2" - yup "^0.29.3" - -"@backstage/plugin-catalog-backend@^0.6.5": - version "0.6.7" - resolved "https://registry.npmjs.org/@backstage/plugin-catalog-backend/-/plugin-catalog-backend-0.6.7.tgz#97d0ed6db6aeb04e09ed0fee05e76bacf66cc179" - integrity sha512-Ey9PXyUjmi8IxQNSXBhF6Sl2SmZ/iXCFHXnffH8XCdBFTZS8HDRE2tSOlIIU4XQKd6lJVuAGTekas2DkaS9/lA== - dependencies: - "@azure/msal-node" "^1.0.0-beta.3" - "@backstage/backend-common" "^0.6.0" - "@backstage/catalog-model" "^0.7.4" - "@backstage/config" "^0.1.4" - "@backstage/errors" "^0.1.1" - "@backstage/integration" "^0.5.1" - "@backstage/plugin-search-backend-node" "^0.1.2" - "@backstage/search-common" "^0.1.1" - "@octokit/graphql" "^4.5.8" - "@types/express" "^4.17.6" - "@types/ldapjs" "^1.0.9" - aws-sdk "^2.840.0" - codeowners-utils "^1.0.2" - core-js "^3.6.5" - cross-fetch "^3.0.6" - express "^4.17.1" - express-promise-router "^4.1.0" - fs-extra "^9.0.0" - git-url-parse "^11.4.4" - glob "^7.1.6" - knex "^0.95.1" - ldapjs "^2.2.0" - lodash "^4.17.15" - morgan "^1.10.0" - p-limit "^3.0.2" - qs "^6.9.4" - uuid "^8.0.0" - winston "^3.2.1" - yaml "^1.9.2" - yn "^4.0.0" - yup "^0.29.3" - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -5609,20 +5520,6 @@ lz-string "^1.4.4" pretty-format "^26.6.2" -"@testing-library/dom@^7.22.3": - version "7.30.3" - resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-7.30.3.tgz#779ea9bbb92d63302461800a388a5a890ac22519" - integrity sha512-7JhIg2MW6WPwyikH2iL3o7z+FTVgSOd2jqCwTAHqK7Qal2gRRYiUQyURAxtbK9VXm/UTyG9bRihv8C5Tznr2zw== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/runtime" "^7.12.5" - "@types/aria-query" "^4.2.0" - aria-query "^4.2.2" - chalk "^4.1.0" - dom-accessibility-api "^0.5.4" - lz-string "^1.4.4" - pretty-format "^26.6.2" - "@testing-library/jest-dom@^5.10.1": version "5.11.9" resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.9.tgz#e6b3cd687021f89f261bd53cbe367041fbd3e975" @@ -5653,14 +5550,6 @@ "@babel/runtime" "^7.5.4" "@types/testing-library__react-hooks" "^3.4.0" -"@testing-library/react@^10.4.1": - version "10.4.9" - resolved "https://registry.npmjs.org/@testing-library/react/-/react-10.4.9.tgz#9faa29c6a1a217bf8bbb96a28bd29d7a847ca150" - integrity sha512-pHZKkqUy0tmiD81afs8xfiuseXfU/N7rAX3iKjeZYje86t9VaB0LrxYVa+OOsvkrveX5jCK3IjajVn2MbePvqA== - dependencies: - "@babel/runtime" "^7.10.3" - "@testing-library/dom" "^7.22.3" - "@testing-library/react@^11.2.5": version "11.2.6" resolved "https://registry.npmjs.org/@testing-library/react/-/react-11.2.6.tgz#586a23adc63615985d85be0c903f374dab19200b" @@ -6439,11 +6328,6 @@ resolved "https://registry.npmjs.org/@types/node/-/node-10.17.35.tgz#58058f29b870e6ae57b20e4f6e928f02b7129f56" integrity sha512-gXx7jAWpMddu0f7a+L+txMplp3FnHl53OhQIF9puXKq3hDGY/GjH+MF04oWnV/adPSCrbtHumDCFwzq2VhltWA== -"@types/node@^12.0.0": - version "12.20.10" - resolved "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz#4dcb8a85a8f1211acafb88d72fafc7e3d2685583" - integrity sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw== - "@types/node@^12.7.1": version "12.12.58" resolved "https://registry.npmjs.org/@types/node/-/node-12.12.58.tgz#46dae9b2b9ee5992818c8f7cee01ff4ce03ab44c" @@ -12975,15 +12859,6 @@ expect@^26.6.2: jest-message-util "^26.6.2" jest-regex-util "^26.0.0" -express-promise-router@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/express-promise-router/-/express-promise-router-3.0.3.tgz#5e6d22a5a3f013d71833172fe8d7ab780c3f6b70" - integrity sha1-Xm0ipaPwE9cYMxcv6NereAw/a3A= - dependencies: - is-promise "^2.1.0" - lodash.flattendeep "^4.0.0" - methods "^1.0.0" - express-promise-router@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/express-promise-router/-/express-promise-router-4.1.0.tgz#79160e145c27610ba411bceb0552a36f11dbab4f" @@ -25778,17 +25653,6 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-json-schema@^0.47.0: - version "0.47.0" - resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.47.0.tgz#84dde5460b127c6774da81bf70b23c7e04857b13" - integrity sha512-A6NVwSOTSsNDHfaqDcDeKwwyXEeKqBHoAr20jcetnYj4e8C6zVFofAVhAuwsBXCRYiWEE/lyHrcxpsSpbIk0Mg== - dependencies: - "@types/json-schema" "^7.0.6" - glob "^7.1.6" - json-stable-stringify "^1.0.1" - typescript "^4.1.3" - yargs "^16.2.0" - typescript-json-schema@^0.49.0: version "0.49.0" resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.49.0.tgz#442f6347ca85fb0d9811f217fb0d6537b68734b3" From 87c4f59deaab876d159661250319f859feb83890 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Wed, 21 Apr 2021 15:18:49 +0200 Subject: [PATCH 073/262] Add low german greeting Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/new-shirts-move.md | 5 +++++ .../CatalogPage/utils/locales/goodAfternoon.locales.json | 1 + .../CatalogPage/utils/locales/goodEvening.locales.json | 1 + .../CatalogPage/utils/locales/goodMorning.locales.json | 1 + 4 files changed, 8 insertions(+) create mode 100644 .changeset/new-shirts-move.md diff --git a/.changeset/new-shirts-move.md b/.changeset/new-shirts-move.md new file mode 100644 index 0000000000..3896c85bbb --- /dev/null +++ b/.changeset/new-shirts-move.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Add low german greeting diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json index 4d48666666..1c5f5fd2b0 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json @@ -68,6 +68,7 @@ "Latvian": "Labdien", "Limburgish": "Gojemiddig", "Lithuanian": "Laba diena", + "Low German": "Moin", "Lozi": "Ki musihali", "Lule Sámi": "Buorre biejvve", "Luxembourgish": "Gudde Mëtteg", diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json index 36d48eaf39..b8ec898a56 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json @@ -56,6 +56,7 @@ "Kurdish": "Evarbash", "Latvian": "Labvakar", "Lithuanian": "Labas vakaras", + "Low German": "Moin", "Luganda": "Osiibye otya nno", "Luo": "Oimore", "Luxembourgish": "Gudden Owend", diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json b/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json index febbc32c49..27ac91daaa 100644 --- a/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json +++ b/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json @@ -32,6 +32,7 @@ "Kazakh": "Kayırlı tan", "Kurdish": "Beyanî baş", "Lithuanian": "Labas rytas", + "Low German": "Moin", "Macedonian": "Добро утро", "Malay": "Selamat pagi", "Maltese": "Bonġu", From 5fe62f124e05e16298659cd9990db3bfc7d54aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Tue, 20 Apr 2021 20:19:35 +0200 Subject: [PATCH 074/262] Fix the schema / code mismatch in LDAP `set` config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .changeset/light-fireants-flow.md | 5 +++++ .../ingestion/processors/ldap/config.test.ts | 14 +++++++------- .../src/ingestion/processors/ldap/config.ts | 17 +++++++---------- .../src/ingestion/processors/ldap/read.ts | 6 +++--- 4 files changed, 22 insertions(+), 20 deletions(-) create mode 100644 .changeset/light-fireants-flow.md diff --git a/.changeset/light-fireants-flow.md b/.changeset/light-fireants-flow.md new file mode 100644 index 0000000000..a8f7b09278 --- /dev/null +++ b/.changeset/light-fireants-flow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Fix the schema / code mismatch in LDAP `set` config diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts index aac9a091b8..607581e153 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts @@ -88,7 +88,7 @@ describe('readLdapConfig', () => { filter: 'f', paged: true, }, - set: [{ path: 'p', value: 'v' }], + set: { p: 'v' }, map: { rdn: 'u', name: 'v', @@ -107,7 +107,7 @@ describe('readLdapConfig', () => { filter: 'f', paged: true, }, - set: [{ path: 'p', value: 'v' }], + set: { p: 'v' }, map: { rdn: 'u', name: 'v', @@ -136,7 +136,7 @@ describe('readLdapConfig', () => { filter: 'f', paged: true, }, - set: [{ path: 'p', value: 'v' }], + set: { p: 'v' }, map: { rdn: 'u', name: 'v', @@ -155,7 +155,7 @@ describe('readLdapConfig', () => { filter: 'f', paged: true, }, - set: [{ path: 'p', value: 'v' }], + set: { p: 'v' }, map: { rdn: 'u', name: 'v', @@ -182,9 +182,9 @@ describe('readLdapConfig', () => { dn: 'udn', options: { filter: ` - (| - (cn=foo bar) - (cn=bar) + (| + (cn=foo bar) + (cn=bar) ) `, }, diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts index 625282ca05..aca02e6e10 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts @@ -57,7 +57,7 @@ export type UserConfig = { // default is scope "one" and attributes "*" and "+". options: SearchOptions; // JSON paths (on a.b.c form) and hard coded values to set on those paths - set?: { path: string; value: JsonValue }[]; + set?: { [path: string]: JsonValue }; // Mappings from well known entity fields, to LDAP attribute names map: { // The name of the attribute that holds the relative distinguished name of @@ -94,7 +94,7 @@ export type GroupConfig = { // Only the scope, filter, attributes, and paged fields are supported. options: SearchOptions; // JSON paths (on a.b.c form) and hard coded values to set on those paths - set?: { path: string; value: JsonValue }[]; + set?: { [path: string]: JsonValue }; // Mappings from well known entity fields, to LDAP attribute names map: { // The name of the attribute that holds the relative distinguished name of @@ -189,15 +189,12 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { } function readSetConfig( - c: Config[] | undefined, - ): { path: string; value: JsonValue }[] | undefined { + c: Config | undefined, + ): { [path: string]: JsonValue } | undefined { if (!c) { return undefined; } - return c.map(entry => ({ - path: entry.getString('path'), - value: entry.get('value'), - })); + return Object.fromEntries(c.keys().map(path => [path, c.get(path)])); } function readUserMapConfig( @@ -244,7 +241,7 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { return { dn: c.getString('dn'), options: readOptionsConfig(c.getOptionalConfig('options')), - set: readSetConfig(c.getOptionalConfigArray('set')), + set: readSetConfig(c.getOptionalConfig('set')), map: readUserMapConfig(c.getOptionalConfig('map')), }; } @@ -255,7 +252,7 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { return { dn: c.getString('dn'), options: readOptionsConfig(c.getOptionalConfig('options')), - set: readSetConfig(c.getOptionalConfigArray('set')), + set: readSetConfig(c.getOptionalConfig('set')), map: readGroupMapConfig(c.getOptionalConfig('map')), }; } diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/read.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/read.ts index 3162fbd01c..68542b5b30 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/read.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/read.ts @@ -15,6 +15,7 @@ */ import { GroupEntity, UserEntity } from '@backstage/catalog-model'; +import { SearchEntry } from 'ldapjs'; import lodashSet from 'lodash/set'; import { buildOrgHierarchy } from '../util/org'; import { LdapClient } from './client'; @@ -25,7 +26,6 @@ import { LDAP_UUID_ANNOTATION, } from './constants'; import { LdapVendor } from './vendors'; -import { SearchEntry } from 'ldapjs'; /** * Reads users out of an LDAP provider. @@ -63,7 +63,7 @@ export async function readLdapUsers( }; if (set) { - for (const { path, value } of set) { + for (const [path, value] of Object.entries(set)) { lodashSet(entity, path, value); } } @@ -142,7 +142,7 @@ export async function readLdapGroups( }; if (set) { - for (const { path, value } of set) { + for (const [path, value] of Object.entries(set)) { lodashSet(entity, path, value); } } From d0addca8602ad42133415786693765d88e900317 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Wed, 21 Apr 2021 13:14:46 -0400 Subject: [PATCH 075/262] [code-coverage] fix so tests work in windows Use path.resolve, and trim end of scmFiles Signed-off-by: alde <r.dybeck@gmail.com> --- .../src/service/converter/cobertura.test.ts | 22 ++++++++++++++++--- .../src/service/converter/cobertura.ts | 4 +++- .../src/service/converter/jacoco.test.ts | 13 ++++++++--- .../src/service/converter/jacoco.ts | 4 +++- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/plugins/code-coverage-backend/src/service/converter/cobertura.test.ts b/plugins/code-coverage-backend/src/service/converter/cobertura.test.ts index 72d4018f94..0e67d35d7a 100644 --- a/plugins/code-coverage-backend/src/service/converter/cobertura.test.ts +++ b/plugins/code-coverage-backend/src/service/converter/cobertura.test.ts @@ -15,6 +15,7 @@ */ import { parseString } from 'xml2js'; import fs from 'fs'; +import path from 'path'; import { Cobertura } from './cobertura'; import { CoberturaXML } from './types'; import { getVoidLogger } from '@backstage/backend-common'; @@ -27,7 +28,12 @@ describe('convert cobertura', () => { let fixture: CoberturaXML; parseString( fs.readFileSync( - `${__dirname}/../__fixtures__/cobertura-testdata-${idx}.xml`, + path.resolve( + __dirname, + '..', + '__fixtures__', + `cobertura-testdata-${idx}.xml`, + ), ), (_e, r) => { fixture = r; @@ -36,13 +42,23 @@ describe('convert cobertura', () => { const expected = JSON.parse( fs .readFileSync( - `${__dirname}/../__fixtures__/cobertura-jsoncoverage-files-${idx}.json`, + path.resolve( + __dirname, + '..', + '__fixtures__', + `cobertura-jsoncoverage-files-${idx}.json`, + ), ) .toString(), ); const scmFiles = fs .readFileSync( - `${__dirname}/../__fixtures__/cobertura-sourcefiles-${idx}.txt`, + path.resolve( + __dirname, + '..', + '__fixtures__', + `cobertura-sourcefiles-${idx}.txt`, + ), ) .toString() .split('\n'); diff --git a/plugins/code-coverage-backend/src/service/converter/cobertura.ts b/plugins/code-coverage-backend/src/service/converter/cobertura.ts index 02ac187387..fcaea839ee 100644 --- a/plugins/code-coverage-backend/src/service/converter/cobertura.ts +++ b/plugins/code-coverage-backend/src/service/converter/cobertura.ts @@ -62,7 +62,9 @@ export class Cobertura implements Converter { } }); - const currentFile = scmFiles.find(f => f.endsWith(packageAndFilename)); + const currentFile = scmFiles + .map(f => f.trimEnd()) + .find(f => f.endsWith(packageAndFilename)); this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`); if ( scmFiles.length === 0 || diff --git a/plugins/code-coverage-backend/src/service/converter/jacoco.test.ts b/plugins/code-coverage-backend/src/service/converter/jacoco.test.ts index 48202748da..0507cf3a98 100644 --- a/plugins/code-coverage-backend/src/service/converter/jacoco.test.ts +++ b/plugins/code-coverage-backend/src/service/converter/jacoco.test.ts @@ -15,6 +15,7 @@ */ import { parseString } from 'xml2js'; import fs from 'fs'; +import path from 'path'; import { Jacoco } from './jacoco'; import { JacocoXML } from './types'; import { getVoidLogger } from '@backstage/backend-common'; @@ -25,7 +26,9 @@ describe('convert jacoco', () => { const converter = new Jacoco(getVoidLogger()); let fixture: JacocoXML; parseString( - fs.readFileSync(`${__dirname}/../__fixtures__/jacoco-testdata-1.xml`), + fs.readFileSync( + path.resolve(`${__dirname}/../__fixtures__/jacoco-testdata-1.xml`), + ), (_e, r) => { fixture = r; }, @@ -33,12 +36,16 @@ describe('convert jacoco', () => { const expected = JSON.parse( fs .readFileSync( - `${__dirname}/../__fixtures__/jacoco-jsoncoverage-files-1.json`, + path.resolve( + `${__dirname}/../__fixtures__/jacoco-jsoncoverage-files-1.json`, + ), ) .toString(), ); const scmFiles = fs - .readFileSync(`${__dirname}/../__fixtures__/jacoco-sourcefiles-1.txt`) + .readFileSync( + path.resolve(`${__dirname}/../__fixtures__/jacoco-sourcefiles-1.txt`), + ) .toString() .split('\n'); diff --git a/plugins/code-coverage-backend/src/service/converter/jacoco.ts b/plugins/code-coverage-backend/src/service/converter/jacoco.ts index 4c554fec91..e4a41f8bc4 100644 --- a/plugins/code-coverage-backend/src/service/converter/jacoco.ts +++ b/plugins/code-coverage-backend/src/service/converter/jacoco.ts @@ -63,7 +63,9 @@ export class Jacoco implements Converter { }); const packageAndFilename = `${packageName}/${fileName}`; - const currentFile = scmFiles.find(f => f.endsWith(packageAndFilename)); + const currentFile = scmFiles + .map(f => f.trimEnd()) + .find(f => f.endsWith(packageAndFilename)); this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`); if (Object.keys(lineHits).length > 0 && currentFile) { jscov.push({ From 55b2fc0c0f02c46a7be0122769f97a5f3cdfa240 Mon Sep 17 00:00:00 2001 From: alde <r.dybeck@gmail.com> Date: Wed, 21 Apr 2021 14:59:56 -0400 Subject: [PATCH 076/262] create changeset Signed-off-by: alde <r.dybeck@gmail.com> --- .changeset/rotten-cups-bow.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/rotten-cups-bow.md diff --git a/.changeset/rotten-cups-bow.md b/.changeset/rotten-cups-bow.md new file mode 100644 index 0000000000..967681171d --- /dev/null +++ b/.changeset/rotten-cups-bow.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-code-coverage': patch +'@backstage/plugin-code-coverage-backend': patch +--- + +Update tests to function in windows From 938b266b863271f87d416d60b0360b228c25d7de Mon Sep 17 00:00:00 2001 From: Tim Hansen <timbonicus@gmail.com> Date: Wed, 21 Apr 2021 15:32:36 -0600 Subject: [PATCH 077/262] Template `spec.type` is not optional Signed-off-by: Tim Hansen <timbonicus@gmail.com> --- .../software-catalog/descriptor-format.md | 19 ++++--------------- .../kinds/Template.v1alpha1.schema.json | 2 +- .../schema/kinds/Template.v1beta2.schema.json | 2 +- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index f4e1f86dd8..d3b14dd888 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -639,22 +639,11 @@ A list of strings that can be associated with the template, e.g. This list will also be used in the frontend to display to the user so you can potentially search and group templates by these tags. -### `spec.type` [optional] +### `spec.type` [required] -The type of component as a string, e.g. `website`. This field is optional but -recommended. - -The software catalog accepts any type value, but an organization should take -great care to establish a proper taxonomy for these. Tools including Backstage -itself may read this field and behave differently depending on its value. For -example, a website type component may present tooling in the Backstage interface -that is specific to just websites. - -The current set of well-known and common values for this field is: - -- `service` - a backend service, typically exposing an API -- `website` - a website -- `library` - a software library, such as an npm module or a Java library +The type of component created by the template, e.g. `website`. This is used for +filtering templates, and should ideally match the Component +[spec.type](#spectype-required) created by the template. ### `spec.parameters` [required] diff --git a/packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json index 5bb83d116b..53109ac7ee 100644 --- a/packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json @@ -66,7 +66,7 @@ "properties": { "type": { "type": "string", - "description": "The type of component. This field is optional but recommended. The software catalog accepts any type value, but an organization should take great care to establish a proper taxonomy for these. Tools including Backstage itself may read this field and behave differently depending on its value. For example, a website type component may present tooling in the Backstage interface that is specific to just websites.", + "description": "The type of component created by the template. The software catalog accepts any type value, but an organization should take great care to establish a proper taxonomy for these. Tools including Backstage itself may read this field and behave differently depending on its value. For example, a website type component may present tooling in the Backstage interface that is specific to just websites.", "examples": ["service", "website", "library"], "minLength": 1 }, diff --git a/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json b/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json index ba3ccb9d1d..1e0b7d0ded 100644 --- a/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json +++ b/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json @@ -85,7 +85,7 @@ "properties": { "type": { "type": "string", - "description": "The type of component. This field is optional but recommended. The software catalog accepts any type value, but an organization should take great care to establish a proper taxonomy for these. Tools including Backstage itself may read this field and behave differently depending on its value. For example, a website type component may present tooling in the Backstage interface that is specific to just websites.", + "description": "The type of component created by the template. The software catalog accepts any type value, but an organization should take great care to establish a proper taxonomy for these. Tools including Backstage itself may read this field and behave differently depending on its value. For example, a website type component may present tooling in the Backstage interface that is specific to just websites.", "examples": ["service", "website", "library"], "minLength": 1 }, From b9028d0f0c36726a738fd83269274136d409c86d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Apr 2021 04:32:34 +0000 Subject: [PATCH 078/262] chore(deps-dev): bump @types/jest from 26.0.15 to 26.0.22 Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 26.0.15 to 26.0.22. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 46 +++++----------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/yarn.lock b/yarn.lock index f614a7713a..dfa07a5397 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2955,17 +2955,6 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@jest/types@^26.6.1": - version "26.6.1" - resolved "https://registry.npmjs.org/@jest/types/-/types-26.6.1.tgz#2638890e8031c0bc8b4681e0357ed986e2f866c5" - integrity sha512-ywHavIKNpAVrStiRY5wiyehvcktpijpItvGiK72RAn5ctqmzvPk8OvKnvHeBqa1XdQr959CTWAJMqxI8BTibyg== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^15.0.0" - chalk "^4.0.0" - "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -6102,9 +6091,9 @@ "@types/jest" "*" "@types/jest@*", "@types/jest@^26.0.7": - version "26.0.15" - resolved "https://registry.npmjs.org/@types/jest/-/jest-26.0.15.tgz#12e02c0372ad0548e07b9f4e19132b834cb1effe" - integrity sha512-s2VMReFXRg9XXxV+CW9e5Nz8fH2K1aEhwgjUqPPbQd7g95T0laAcvLv032EhFHIa5GHsZ8W7iJEQVaJq6k3Gog== + version "26.0.22" + resolved "https://registry.npmjs.org/@types/jest/-/jest-26.0.22.tgz#8308a1debdf1b807aa47be2838acdcd91e88fbe6" + integrity sha512-eeWwWjlqxvBxc4oQdkueW5OF/gtfSceKk4OnOAGlUSwS/liBRtZppbJuz1YkgbrbfGOoeBHun9fOvXnjNwrSOw== dependencies: jest-diff "^26.0.0" pretty-format "^26.0.0" @@ -11513,11 +11502,6 @@ diff-sequences@^24.9.0: resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== -diff-sequences@^26.5.0: - version "26.5.0" - resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz#ef766cf09d43ed40406611f11c6d8d9dd8b2fefd" - integrity sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q== - diff-sequences@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" @@ -16241,17 +16225,7 @@ jest-diff@^24.9.0: jest-get-type "^24.9.0" pretty-format "^24.9.0" -jest-diff@^26.0.0: - version "26.6.1" - resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.1.tgz#38aa194979f454619bb39bdee299fb64ede5300c" - integrity sha512-BBNy/zin2m4kG5In126O8chOBxLLS/XMTuuM2+YhgyHk87ewPzKTuTJcqj3lOWOi03NNgrl+DkMeV/exdvG9gg== - dependencies: - chalk "^4.0.0" - diff-sequences "^26.5.0" - jest-get-type "^26.3.0" - pretty-format "^26.6.1" - -jest-diff@^26.6.2: +jest-diff@^26.0.0, jest-diff@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== @@ -21320,17 +21294,7 @@ pretty-format@^24.9.0: ansi-styles "^3.2.0" react-is "^16.8.4" -pretty-format@^26.0.0, pretty-format@^26.6.1: - version "26.6.1" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.1.tgz#af9a2f63493a856acddeeb11ba6bcf61989660a8" - integrity sha512-MeqqsP5PYcRBbGMvwzsyBdmAJ4EFX7pWFyl7x4+dMVg5pE0ZDdBIvEH2ergvIO+Gvwv1wh64YuOY9y5LuyY/GA== - dependencies: - "@jest/types" "^26.6.1" - ansi-regex "^5.0.0" - ansi-styles "^4.0.0" - react-is "^17.0.1" - -pretty-format@^26.6.2: +pretty-format@^26.0.0, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== From 0d9d875bc91a1e7673a9a1714959cc95ae3f6528 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Apr 2021 04:33:43 +0000 Subject: [PATCH 079/262] chore(deps-dev): bump @graphql-codegen/typescript from 1.21.1 to 1.22.0 Bumps [@graphql-codegen/typescript](https://github.com/dotansimha/graphql-code-generator/tree/HEAD/packages/plugins/typescript/typescript) from 1.21.1 to 1.22.0. - [Release notes](https://github.com/dotansimha/graphql-code-generator/releases) - [Changelog](https://github.com/dotansimha/graphql-code-generator/blob/master/packages/plugins/typescript/typescript/CHANGELOG.md) - [Commits](https://github.com/dotansimha/graphql-code-generator/commits/@graphql-codegen/typescript@1.22.0/packages/plugins/typescript/typescript) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 92 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/yarn.lock b/yarn.lock index f614a7713a..376441c31b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2330,27 +2330,16 @@ "@graphql-tools/utils" "^6" tslib "~2.0.1" -"@graphql-codegen/plugin-helpers@^1.18.2", "@graphql-codegen/plugin-helpers@^1.18.3": - version "1.18.3" - resolved "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.18.3.tgz#607a8bc16d80b30d59cd07d70de2ba803b57bc4a" - integrity sha512-+LVxWFlcZW+FB32CyvkdaMN/tIMajO42pCg0Cy8Z8ZZtGutXW1w6UggrvrEUzMZc9GHZQe49q+w7QQxeooaIlA== +"@graphql-codegen/plugin-helpers@^1.18.2", "@graphql-codegen/plugin-helpers@^1.18.4", "@graphql-codegen/plugin-helpers@^1.18.5": + version "1.18.5" + resolved "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.18.5.tgz#e1d875cfb6a2f7bf4b4318135f7fee6e1200f3b0" + integrity sha512-xY8dWdU4+mm+253esLYcKQIgWZEgI3spKPmMRQ+oAxlrCn9oIcdhhiMqNxa9rHS20xpZtlAjozxHulrqjFLuyA== dependencies: "@graphql-tools/utils" "^7.0.0" common-tags "1.8.0" import-from "3.0.0" lodash "~4.17.20" - tslib "~2.1.0" - -"@graphql-codegen/plugin-helpers@^1.18.4": - version "1.18.4" - resolved "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.18.4.tgz#0adc4c0f88386a50b7a69d358080b6ee54fc3b16" - integrity sha512-dpfhUmn9GOS8ByoOPIN3V4Nn9HX7sl9NR7Hf26TgN6Clg7cQvkT6XjHdS2e56Q3kWrxZT1zJ1sEa67D3tj9ZtQ== - dependencies: - "@graphql-tools/utils" "^7.0.0" - common-tags "1.8.0" - import-from "3.0.0" - lodash "~4.17.20" - tslib "~2.1.0" + tslib "~2.2.0" "@graphql-codegen/typescript-resolvers@^1.17.7": version "1.18.2" @@ -2365,30 +2354,30 @@ tslib "~2.1.0" "@graphql-codegen/typescript@^1.17.7", "@graphql-codegen/typescript@^1.21.0": - version "1.21.1" - resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-1.21.1.tgz#9bce3254b8ef30a6bf64e57ba3991f9be7a19b53" - integrity sha512-JF6Vsu5HSv3dAoS2ca3PFLUN0qVxotex/+BgWw/6SKhtd83MUPnzJ/RU3lACg4vuNTCWeQSeGvg8x5qrw9Go9w== + version "1.22.0" + resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-1.22.0.tgz#d05be3a971e5d75a076a43e123b6330f4366a6ab" + integrity sha512-YzN/3MBYHrP110m8JgUWQIHt7Ivi3JXiq0RT5XNx/F9mVOSbZz6Ezbaji8YJA3y04Gl2f6ZgtdGazWANUvcOcg== dependencies: - "@graphql-codegen/plugin-helpers" "^1.18.3" - "@graphql-codegen/visitor-plugin-common" "^1.19.0" + "@graphql-codegen/plugin-helpers" "^1.18.5" + "@graphql-codegen/visitor-plugin-common" "^1.20.0" auto-bind "~4.0.0" - tslib "~2.1.0" + tslib "~2.2.0" -"@graphql-codegen/visitor-plugin-common@^1.18.3", "@graphql-codegen/visitor-plugin-common@^1.19.0": - version "1.19.0" - resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.19.0.tgz#e302dd1ba55cf220079c40fa840a355dcf81526d" - integrity sha512-Vsh9FwB90SBLnSr4KTFY8cuwjC//JBVyqn4k4usBZHFLWLkPwWzdkUKABFg6ET2gnL2L1rSU/gM30eEBrLRXFA== +"@graphql-codegen/visitor-plugin-common@^1.18.3", "@graphql-codegen/visitor-plugin-common@^1.20.0": + version "1.20.0" + resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.20.0.tgz#38d829eab7370c79aa5229190788f94adcae8f76" + integrity sha512-AYrpy8NA3DpvhDLqYGerQRv44S+YAMPKtwT8x9GNVjzP0gVfmqi3gG1bDWbP5sm6kOZKvDC0kTxGePuBSZerxw== dependencies: - "@graphql-codegen/plugin-helpers" "^1.18.3" + "@graphql-codegen/plugin-helpers" "^1.18.5" "@graphql-tools/optimize" "^1.0.1" "@graphql-tools/relay-operation-optimizer" "^6" array.prototype.flatmap "^1.2.4" auto-bind "~4.0.0" - change-case-all "^1.0.12" + change-case-all "1.0.14" dependency-graph "^0.11.0" graphql-tag "^2.11.0" parse-filepath "^1.0.2" - tslib "~2.1.0" + tslib "~2.2.0" "@graphql-modules/core@^0.7.17": version "0.7.17" @@ -9406,7 +9395,7 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -change-case-all@1.0.12, change-case-all@^1.0.12: +change-case-all@1.0.12: version "1.0.12" resolved "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.12.tgz#ae3e0faf5e610e8e25c5d5eaa4a6d5c2f1d68797" integrity sha512-zdQus7R0lkprF99lrWUC5bFj6Nog4Xt4YCEjQ/vM4vbc6b5JHFBQMxRPAjfx+HJH8WxMzH0E+lQ8yQJLgmPCBg== @@ -9422,7 +9411,23 @@ change-case-all@1.0.12, change-case-all@^1.0.12: upper-case "^2.0.1" upper-case-first "^2.0.1" -change-case@^4.1.1: +change-case-all@1.0.14: + version "1.0.14" + resolved "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1" + integrity sha512-CWVm2uT7dmSHdO/z1CXT/n47mWonyypzBbuCy5tN7uMg22BsfkhwT6oHmFCAk+gL1LOOxhdbB9SZz3J1KTY3gA== + dependencies: + change-case "^4.1.2" + is-lower-case "^2.0.2" + is-upper-case "^2.0.2" + lower-case "^2.0.2" + lower-case-first "^2.0.2" + sponge-case "^1.0.1" + swap-case "^2.0.2" + title-case "^3.0.3" + upper-case "^2.0.2" + upper-case-first "^2.0.2" + +change-case@^4.1.1, change-case@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== @@ -15715,7 +15720,7 @@ is-lambda@^1.0.1: resolved "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= -is-lower-case@^2.0.1: +is-lower-case@^2.0.1, is-lower-case@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz#1c0884d3012c841556243483aa5d522f47396d2a" integrity sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ== @@ -15975,7 +15980,7 @@ is-unicode-supported@^0.1.0: resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-upper-case@^2.0.1: +is-upper-case@^2.0.1, is-upper-case@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" integrity sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ== @@ -17880,7 +17885,7 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lower-case-first@^2.0.1: +lower-case-first@^2.0.1, lower-case-first@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz#64c2324a2250bf7c37c5901e76a5b5309301160b" integrity sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg== @@ -24062,7 +24067,7 @@ split@^1.0.0: dependencies: through "2" -sponge-case@^1.0.0: +sponge-case@^1.0.0, sponge-case@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz#260833b86453883d974f84854cdb63aecc5aef4c" integrity sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA== @@ -24811,7 +24816,7 @@ swagger-ui-react@^3.37.2: xml-but-prettier "^1.0.1" zenscroll "^4.0.2" -swap-case@^2.0.1: +swap-case@^2.0.1, swap-case@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz#671aedb3c9c137e2985ef51c51f9e98445bf70d9" integrity sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw== @@ -25193,7 +25198,7 @@ tinycolor2@^1.4.1: resolved "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g= -title-case@^3.0.2: +title-case@^3.0.2, title-case@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" integrity sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA== @@ -25509,16 +25514,21 @@ tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== +tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@~2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" + integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== tslib@~2.0.0, tslib@~2.0.1: version "2.0.3" resolved "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== +tslib@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" + integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" From 49574a8a3e7365a3c1474b787685d5956b1730cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Thu, 22 Apr 2021 09:15:36 +0200 Subject: [PATCH 080/262] Fix some spleling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .changeset/great-years-battle.md | 14 ++++++++++++++ plugins/config-schema/dev/example-schema.json | 8 ++++---- plugins/rollbar-backend/config.d.ts | 2 +- plugins/scaffolder-backend/config.d.ts | 6 +++--- .../scaffolder/actions/builtin/publish/azure.ts | 2 +- .../actions/builtin/publish/bitbucket.ts | 4 ++-- .../scaffolder/actions/builtin/publish/github.ts | 6 +++--- .../scaffolder/actions/builtin/publish/gitlab.ts | 4 ++-- 8 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 .changeset/great-years-battle.md diff --git a/.changeset/great-years-battle.md b/.changeset/great-years-battle.md new file mode 100644 index 0000000000..a2d61be11a --- /dev/null +++ b/.changeset/great-years-battle.md @@ -0,0 +1,14 @@ +--- +'@backstage/plugin-rollbar-backend': patch +'@backstage/plugin-scaffolder-backend': minor +--- + +Fix some `spleling`. + +The `scaffolder-backend` has a configuration schema change that may be breaking +in rare circumstances. Due to a typo in the schema, the +`scaffolder.github.visibility`, `scaffolder.gitlab.visibility`, and +`scaffolder.bitbucket.visibility` did not get proper validation that the value +is one of the supported strings (`public`, `internal` (not available for +Bitbucket), and `private`). If you had a value that was not one of these three, +you may have to adjust your config. diff --git a/plugins/config-schema/dev/example-schema.json b/plugins/config-schema/dev/example-schema.json index d1e577ff6f..ac5c2ad347 100644 --- a/plugins/config-schema/dev/example-schema.json +++ b/plugins/config-schema/dev/example-schema.json @@ -1247,7 +1247,7 @@ "required": ["accountToken"], "properties": { "accountToken": { - "description": "The autentication token for accessing the Rollbar API", + "description": "The authentication token for accessing the Rollbar API", "type": "string" }, "organization": { @@ -1320,7 +1320,7 @@ "type": "string" }, "properties": { - "visiblity": { + "visibility": { "description": "The visibility to set on created repositories.", "enum": ["internal", "private", "public"], "type": "string" @@ -1337,7 +1337,7 @@ "type": "string" } }, - "visiblity": { + "visibility": { "description": "The visibility to set on created repositories.", "enum": ["internal", "private", "public"], "type": "string" @@ -1369,7 +1369,7 @@ "type": "string" } }, - "visiblity": { + "visibility": { "description": "The visibility to set on created repositories.", "enum": ["private", "public"], "type": "string" diff --git a/plugins/rollbar-backend/config.d.ts b/plugins/rollbar-backend/config.d.ts index 473b27a506..bb48f38cf2 100644 --- a/plugins/rollbar-backend/config.d.ts +++ b/plugins/rollbar-backend/config.d.ts @@ -18,7 +18,7 @@ export interface Config { /** Configuration options for the rollbar-backend plugin */ rollbar?: { /** - * The autentication token for accessing the Rollbar API + * The authentication token for accessing the Rollbar API * @see https://explorer.docs.rollbar.com/#section/Authentication */ accountToken: string; diff --git a/plugins/scaffolder-backend/config.d.ts b/plugins/scaffolder-backend/config.d.ts index 3b31b4f951..aefa6154ca 100644 --- a/plugins/scaffolder-backend/config.d.ts +++ b/plugins/scaffolder-backend/config.d.ts @@ -22,14 +22,14 @@ export interface Config { /** * The visibility to set on created repositories. */ - visiblity?: 'public' | 'internal' | 'private'; + visibility?: 'public' | 'internal' | 'private'; }; gitlab?: { api: { [key: string]: string }; /** * The visibility to set on created repositories. */ - visiblity?: 'public' | 'internal' | 'private'; + visibility?: 'public' | 'internal' | 'private'; }; azure?: { baseUrl: string; @@ -40,7 +40,7 @@ export interface Config { /** * The visibility to set on created repositories. */ - visiblity?: 'public' | 'private'; + visibility?: 'public' | 'private'; }; }; } diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index e1a064b3e6..36f5341bbb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -50,7 +50,7 @@ export function createPublishAzureAction(options: { }, sourcePath: { title: - 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the respository.', + 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index 13f639d745..243e515b19 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -184,13 +184,13 @@ export function createPublishBitbucketAction(options: { type: 'string', }, repoVisibility: { - title: 'Repository Visiblity', + title: 'Repository Visibility', type: 'string', enum: ['private', 'public'], }, sourcePath: { title: - 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the respository.', + 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index e58f2c68aa..3ae43c5763 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -67,13 +67,13 @@ export function createPublishGithubAction(options: { type: 'string', }, repoVisibility: { - title: 'Repository Visiblity', + title: 'Repository Visibility', type: 'string', enum: ['private', 'public', 'internal'], }, sourcePath: { title: - 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the respository.', + 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, collaborators: { @@ -180,7 +180,7 @@ export function createPublishGithubAction(options: { repo, permission: 'admin', }); - // no need to add access if it's the person who own's the personal account + // No need to add access if it's the person who owns the personal account } else if (access && access !== owner) { await client.repos.addCollaborator({ owner, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 37074d6f57..0605f88983 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -44,13 +44,13 @@ export function createPublishGitlabAction(options: { type: 'string', }, repoVisibility: { - title: 'Repository Visiblity', + title: 'Repository Visibility', type: 'string', enum: ['private', 'public', 'internal'], }, sourcePath: { title: - 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the respository.', + 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, }, From d8cc7e67a3b078d3659ce444cdaba6447cb354aa Mon Sep 17 00:00:00 2001 From: Jussi Hallila <jussi@hallila.com> Date: Fri, 19 Feb 2021 09:47:00 +0100 Subject: [PATCH 081/262] Exposing Material-UI extension point from tab components on HeaderTabs so additional information can be added to them Signed-off-by: Jussi Hallila <jussi@hallila.com> --- .changeset/eighty-crews-rhyme.md | 5 +++ .../components/TabbedLayout/RoutedTabs.tsx | 7 +++- .../components/TabbedLayout/TabbedLayout.tsx | 6 ++-- .../core/src/components/TabbedLayout/types.ts | 4 +++ .../src/layout/HeaderTabs/HeaderTabs.test.tsx | 32 +++++++++++++++++++ .../core/src/layout/HeaderTabs/HeaderTabs.tsx | 4 ++- 6 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 .changeset/eighty-crews-rhyme.md diff --git a/.changeset/eighty-crews-rhyme.md b/.changeset/eighty-crews-rhyme.md new file mode 100644 index 0000000000..5a8379acb6 --- /dev/null +++ b/.changeset/eighty-crews-rhyme.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Exposing Material UI extension point for tabs to be able to add additional information to them diff --git a/packages/core/src/components/TabbedLayout/RoutedTabs.tsx b/packages/core/src/components/TabbedLayout/RoutedTabs.tsx index b17c8afb3b..6b7b39329b 100644 --- a/packages/core/src/components/TabbedLayout/RoutedTabs.tsx +++ b/packages/core/src/components/TabbedLayout/RoutedTabs.tsx @@ -48,7 +48,12 @@ export const RoutedTabs = ({ routes }: { routes: SubRoute[] }) => { const navigate = useNavigate(); const { index, route, element } = useSelectedSubRoute(routes); const headerTabs = useMemo( - () => routes.map(t => ({ id: t.path, label: t.title })), + () => + routes.map(t => ({ + id: t.path, + label: t.title, + tabProps: t.tabProps, + })), [routes], ); diff --git a/packages/core/src/components/TabbedLayout/TabbedLayout.tsx b/packages/core/src/components/TabbedLayout/TabbedLayout.tsx index f181ee5980..5a1b190d00 100644 --- a/packages/core/src/components/TabbedLayout/TabbedLayout.tsx +++ b/packages/core/src/components/TabbedLayout/TabbedLayout.tsx @@ -23,11 +23,13 @@ import React, { ReactNode, } from 'react'; import { RoutedTabs } from './RoutedTabs'; +import { TabProps } from '@material-ui/core'; type SubRoute = { path: string; title: string; children: JSX.Element; + tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>; }; const Route: (props: SubRoute) => null = () => null; @@ -60,8 +62,8 @@ export function createSubRoutesFromChildren( throw new Error('Child of TabbedLayout must be an TabbedLayout.Route'); } - const { path, title, children } = child.props; - return [{ path, title, children }]; + const { path, title, children, tabProps } = child.props; + return [{ path, title, children, tabProps }]; }); } diff --git a/packages/core/src/components/TabbedLayout/types.ts b/packages/core/src/components/TabbedLayout/types.ts index 29ade88dc0..24ee011933 100644 --- a/packages/core/src/components/TabbedLayout/types.ts +++ b/packages/core/src/components/TabbedLayout/types.ts @@ -14,8 +14,12 @@ * limitations under the License. */ +import { TabProps } from '@material-ui/core'; +import * as React from 'react'; + export type SubRoute = { path: string; title: string; children: JSX.Element; + tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>; }; diff --git a/packages/core/src/layout/HeaderTabs/HeaderTabs.test.tsx b/packages/core/src/layout/HeaderTabs/HeaderTabs.test.tsx index 81d2123049..9a5093f6e9 100644 --- a/packages/core/src/layout/HeaderTabs/HeaderTabs.test.tsx +++ b/packages/core/src/layout/HeaderTabs/HeaderTabs.test.tsx @@ -17,6 +17,7 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { HeaderTabs } from './'; +import { Badge, makeStyles } from '@material-ui/core'; const mockTabs = [ { id: 'overview', label: 'Overview' }, @@ -46,4 +47,35 @@ describe('<HeaderTabs />', () => { 'true', ); }); + it('should render extension component to tab if one present', async () => { + const useStyles = makeStyles(() => ({ + badge: { + margin: '20px 20px 0 0', + }, + })); + + const TextualBadge = React.forwardRef<HTMLSpanElement>((props, ref) => ( + <Badge + classes={useStyles()} + color="secondary" + badgeContent="three new alarms" + > + <span ref={ref} {...props}> + {props.children} + </span> + </Badge> + )); + const iconTab = [ + { + id: 'icon-tab', + label: 'Alarms', + tabProps: { component: TextualBadge }, + }, + ]; + + const rendered = await renderInTestApp(<HeaderTabs tabs={iconTab} />); + + expect(rendered.getByText('Alarms')).toBeInTheDocument(); + expect(rendered.getByText('three new alarms')).toBeInTheDocument(); + }); }); diff --git a/packages/core/src/layout/HeaderTabs/HeaderTabs.tsx b/packages/core/src/layout/HeaderTabs/HeaderTabs.tsx index 718a103f00..1fd4a18ba3 100644 --- a/packages/core/src/layout/HeaderTabs/HeaderTabs.tsx +++ b/packages/core/src/layout/HeaderTabs/HeaderTabs.tsx @@ -18,7 +18,7 @@ // This is just a temporary solution to implementing tabs for now import React, { useState, useEffect } from 'react'; -import { makeStyles, Tabs, Tab as TabUI } from '@material-ui/core'; +import { makeStyles, Tabs, Tab as TabUI, TabProps } from '@material-ui/core'; const useStyles = makeStyles(theme => ({ tabsWrapper: { @@ -41,6 +41,7 @@ const useStyles = makeStyles(theme => ({ export type Tab = { id: string; label: string; + tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>; }; type HeaderTabsProps = { @@ -82,6 +83,7 @@ export const HeaderTabs = ({ > {tabs.map((tab, index) => ( <TabUI + {...tab.tabProps} label={tab.label} key={tab.id} value={index} From 6eaecbd81d1a9e2ea61f2b8b101c2fd4aedee95a Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 13:21:33 +0200 Subject: [PATCH 082/262] Fix owner references to guest user If the user guest is used as an example value of the owner field, we should make sure to specify it as user:guest instead as the default is group. Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/thirty-humans-knock.md | 5 +++++ .../components/EmptyState/MissingAnnotationEmptyState.tsx | 2 +- .../src/ingestion/processors/util/parse.test.ts | 4 ++-- plugins/github-actions/README.md | 2 +- plugins/github-actions/examples/sample.yaml | 2 +- .../examples/dice-roller/catalog-info.yaml | 2 +- .../sample-templates/pull-request/template/catalog-info.yaml | 2 +- 7 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 .changeset/thirty-humans-knock.md diff --git a/.changeset/thirty-humans-knock.md b/.changeset/thirty-humans-knock.md new file mode 100644 index 0000000000..47545af282 --- /dev/null +++ b/.changeset/thirty-humans-knock.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Improve owner example value in `MissingAnnotationEmptyState`. diff --git a/packages/core/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 377373a06d..6c04b34a90 100644 --- a/packages/core/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -30,7 +30,7 @@ metadata: spec: type: website lifecycle: production - owner: guest`; + owner: user:guest`; type Props = { annotation: string; diff --git a/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts b/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts index 4d6f67de22..1d8e139fb3 100644 --- a/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts @@ -38,7 +38,7 @@ describe('parseEntityYaml', () => { spec: type: website lifecycle: production - owner: guest + owner: user:guest `, 'utf8', ), @@ -60,7 +60,7 @@ describe('parseEntityYaml', () => { spec: { type: 'website', lifecycle: 'production', - owner: 'guest', + owner: 'user:guest', }, }), ]); diff --git a/plugins/github-actions/README.md b/plugins/github-actions/README.md index d47144351e..e1569f16ce 100644 --- a/plugins/github-actions/README.md +++ b/plugins/github-actions/README.md @@ -30,7 +30,7 @@ TBD spec: type: website lifecycle: production - owner: guest + owner: user:guest ``` ### Standalone app requirements diff --git a/plugins/github-actions/examples/sample.yaml b/plugins/github-actions/examples/sample.yaml index a765bd395d..5b347388f7 100644 --- a/plugins/github-actions/examples/sample.yaml +++ b/plugins/github-actions/examples/sample.yaml @@ -9,4 +9,4 @@ metadata: spec: type: website lifecycle: production - owner: guest + owner: user:guest diff --git a/plugins/kubernetes-backend/examples/dice-roller/catalog-info.yaml b/plugins/kubernetes-backend/examples/dice-roller/catalog-info.yaml index a944232224..059b719563 100644 --- a/plugins/kubernetes-backend/examples/dice-roller/catalog-info.yaml +++ b/plugins/kubernetes-backend/examples/dice-roller/catalog-info.yaml @@ -10,4 +10,4 @@ metadata: spec: type: service lifecycle: production - owner: guest + owner: user:guest diff --git a/plugins/scaffolder-backend/sample-templates/pull-request/template/catalog-info.yaml b/plugins/scaffolder-backend/sample-templates/pull-request/template/catalog-info.yaml index dd1e0ebd09..04f055bd46 100644 --- a/plugins/scaffolder-backend/sample-templates/pull-request/template/catalog-info.yaml +++ b/plugins/scaffolder-backend/sample-templates/pull-request/template/catalog-info.yaml @@ -5,4 +5,4 @@ metadata: spec: type: website lifecycle: experimental - owner: guest + owner: user:guest From 23afdba96f4ca6539cbd22ba487eb25ed599eed6 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 13:25:55 +0200 Subject: [PATCH 083/262] Use `EntityRefLink` in header and use relations to reference the owner of the document Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/lovely-wombats-relate.md | 6 +++ .../reader/components/TechDocsPageHeader.tsx | 51 +++++++++---------- 2 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 .changeset/lovely-wombats-relate.md diff --git a/.changeset/lovely-wombats-relate.md b/.changeset/lovely-wombats-relate.md new file mode 100644 index 0000000000..33ed205c89 --- /dev/null +++ b/.changeset/lovely-wombats-relate.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Use `EntityRefLink` in header and use relations to reference the owner of the +document. diff --git a/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx b/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx index 1d4321001d..10df7bff78 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx @@ -14,14 +14,18 @@ * limitations under the License. */ +import { EntityName, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { Header, HeaderLabel, useRouteRef } from '@backstage/core'; +import { + EntityRefLink, + EntityRefLinks, + getEntityRelations, +} from '@backstage/plugin-catalog-react'; +import CodeIcon from '@material-ui/icons/Code'; import React from 'react'; import { AsyncState } from 'react-use/lib/useAsync'; -import CodeIcon from '@material-ui/icons/Code'; -import { EntityName, parseEntityName } from '@backstage/catalog-model'; -import { Header, HeaderLabel, Link, useRouteRef } from '@backstage/core'; -import { TechDocsMetadata } from '../../types'; -import { EntityRefLink, entityRouteRef } from '@backstage/plugin-catalog-react'; import { rootRouteRef } from '../../plugin'; +import { TechDocsMetadata } from '../../types'; type TechDocsPageHeaderProps = { entityId: EntityName; @@ -50,15 +54,12 @@ export const TechDocsPageHeader = ({ const { locationMetadata, - spec: { owner, lifecycle }, + spec: { lifecycle }, } = entityMetadataValues || { spec: {} }; - const componentLink = useRouteRef(entityRouteRef); - - let ownerEntity; - if (owner) { - ownerEntity = parseEntityName(owner, { defaultKind: 'group' }); - } + const ownedByRelations = entityMetadataValues + ? getEntityRelations(entityMetadataValues, RELATION_OWNED_BY) + : []; const docsRootLink = useRouteRef(rootRouteRef)(); @@ -67,27 +68,25 @@ export const TechDocsPageHeader = ({ <HeaderLabel label="Component" value={ - <Link style={{ color: '#fff' }} to={componentLink(entityId)}> - {name} - </Link> + <EntityRefLink + color="inherit" + entityRef={entityId} + defaultKind="Component" + /> } /> - {owner ? ( + {ownedByRelations.length > 0 && ( <HeaderLabel label="Owner" value={ - ownerEntity ? ( - <EntityRefLink - style={{ color: '#fff' }} - entityRef={ownerEntity} - defaultKind="group" - /> - ) : ( - owner - ) + <EntityRefLinks + color="inherit" + entityRefs={ownedByRelations} + defaultKind="group" + /> } /> - ) : null} + )} {lifecycle ? <HeaderLabel label="Lifecycle" value={lifecycle} /> : null} {locationMetadata && locationMetadata.type !== 'dir' && From b9b2b4b7666d37ba650edcd4f4d518207d524151 Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Thu, 22 Apr 2021 15:03:10 +0200 Subject: [PATCH 084/262] [Search] Lunr search engine support (#5290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add lunr package Signed-off-by: Emma Indal <emma.indahl@gmail.com> * add search translator type and search engine interface Signed-off-by: Emma Indal <emma.indahl@gmail.com> * (wip) add support for lunr search engine Signed-off-by: Emma Indal <emma.indahl@gmail.com> * lunr search engine support Signed-off-by: Emma Indal <emma.indahl@gmail.com> * clean up todo comments Signed-off-by: Emma Indal <emma.indahl@gmail.com> * typing and cleanups Signed-off-by: Emma Indal <emma.indahl@gmail.com> * move lunr type package from dev deps to deps Signed-off-by: Emma Indal <emma.indahl@gmail.com> * check if documents exist to index Signed-off-by: Emma Indal <emma.indahl@gmail.com> * test fixup Signed-off-by: Emma Indal <emma.indahl@gmail.com> * changeset Signed-off-by: Emma Indal <emma.indahl@gmail.com> * move LunrSearchEngine.ts to /engines and add tests Signed-off-by: Emma Indal <emma.indahl@gmail.com> * update imports Signed-off-by: Emma Indal <emma.indahl@gmail.com> * update error message Signed-off-by: Emma Indal <emma.indahl@gmail.com> * add comment to index rotation Signed-off-by: Emma Indal <emma.indahl@gmail.com> * Update plugins/search-backend-node/src/types.ts Signed-off-by: Fredrik Adelöw freben@gmail.com Co-authored-by: Fredrik Adelöw <freben@gmail.com> Signed-off-by: Emma Indal <emma.indahl@gmail.com> * Update plugins/search-backend-node/src/engines/LunrSearchEngine.ts Signed-off-by: Emma Indal <emma.indahl@gmail.com> Co-authored-by: Fredrik Adelöw <freben@gmail.com> * Update plugins/search-backend-node/src/engines/LunrSearchEngine.ts Signed-off-by: Emma Indal <emma.indahl@gmail.com> Co-authored-by: Fredrik Adelöw <freben@gmail.com> * fix imports Signed-off-by: Emma Indal <emma.indahl@gmail.com> * use type assertion to specify more specific ConcreteLunrQuery type Signed-off-by: Emma Indal <emma.indahl@gmail.com> * fix imports Signed-off-by: Emma Indal <emma.indahl@gmail.com> * consistent naming Signed-off-by: Emma Indal <emma.indahl@gmail.com> * change search engine to be parameter of constructor in indexBuilder Signed-off-by: Emma Indal <emma.indahl@gmail.com> * make engine required in router options and pass it through in createRouter used in standalone server Signed-off-by: Emma Indal <emma.indahl@gmail.com> * fix tests Signed-off-by: Emma Indal <emma.indahl@gmail.com> * delete import Signed-off-by: Emma Indal <emma.indahl@gmail.com> * add types to SearchQuery interface to make it possible to scope to specific index + test Signed-off-by: Emma Indal <emma.indahl@gmail.com> * clean up tests Signed-off-by: Emma Indal <emma.indahl@gmail.com> * handle case when a filter is added on a field that does not exist on all documents + test Signed-off-by: Emma Indal <emma.indahl@gmail.com> Co-authored-by: Fredrik Adelöw <freben@gmail.com> --- .changeset/dry-carrots-impress.md | 6 + packages/backend/src/plugins/search.ts | 9 +- packages/search-common/src/types.ts | 1 + plugins/search-backend-node/package.json | 4 +- .../search-backend-node/src/IndexBuilder.ts | 19 +- .../src/engines/LunrSearchEngine.test.ts | 325 ++++++++++++++++++ .../src/engines/LunrSearchEngine.ts | 134 ++++++++ .../search-backend-node/src/engines/index.ts | 17 + plugins/search-backend-node/src/index.test.ts | 9 +- plugins/search-backend-node/src/index.ts | 2 + plugins/search-backend-node/src/types.ts | 25 +- plugins/search-backend/package.json | 1 + .../search-backend/src/service/router.test.ts | 10 +- plugins/search-backend/src/service/router.ts | 16 +- .../src/service/standaloneServer.ts | 10 + yarn.lock | 10 + 16 files changed, 582 insertions(+), 16 deletions(-) create mode 100644 .changeset/dry-carrots-impress.md create mode 100644 plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts create mode 100644 plugins/search-backend-node/src/engines/LunrSearchEngine.ts create mode 100644 plugins/search-backend-node/src/engines/index.ts diff --git a/.changeset/dry-carrots-impress.md b/.changeset/dry-carrots-impress.md new file mode 100644 index 0000000000..aa057beb58 --- /dev/null +++ b/.changeset/dry-carrots-impress.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-search-backend': patch +'@backstage/plugin-search-backend-node': patch +--- + +Lunr Search Engine support diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index 7bd473756d..a980661c85 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -15,7 +15,10 @@ */ import { useHotCleanup } from '@backstage/backend-common'; import { createRouter } from '@backstage/plugin-search-backend'; -import { IndexBuilder } from '@backstage/plugin-search-backend-node'; +import { + IndexBuilder, + LunrSearchEngine, +} from '@backstage/plugin-search-backend-node'; import { PluginEnvironment } from '../types'; import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend'; @@ -23,7 +26,8 @@ export default async function createPlugin({ logger, discovery, }: PluginEnvironment) { - const indexBuilder = new IndexBuilder({ logger }); + const searchEngine = new LunrSearchEngine({ logger }); + const indexBuilder = new IndexBuilder({ logger, searchEngine }); indexBuilder.addCollator({ type: 'software-catalog', @@ -38,6 +42,7 @@ export default async function createPlugin({ useHotCleanup(module, () => clearInterval(timerId)); return await createRouter({ + engine: indexBuilder.getSearchEngine(), logger, }); } diff --git a/packages/search-common/src/types.ts b/packages/search-common/src/types.ts index ad784c3b36..daa5823424 100644 --- a/packages/search-common/src/types.ts +++ b/packages/search-common/src/types.ts @@ -18,6 +18,7 @@ import { JsonObject } from '@backstage/config'; export interface SearchQuery { term: string; filters?: JsonObject; + types?: string[]; pageCursor: string; } diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index ab260ada5b..2d1803f4c4 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -20,7 +20,9 @@ }, "dependencies": { "@backstage/search-common": "^0.1.1", - "winston": "^3.2.1" + "winston": "^3.2.1", + "lunr": "^2.3.9", + "@types/lunr": "^2.3.3" }, "devDependencies": { "@backstage/backend-common": "^0.6.0", diff --git a/plugins/search-backend-node/src/IndexBuilder.ts b/plugins/search-backend-node/src/IndexBuilder.ts index 43bf84a59d..0f5a287037 100644 --- a/plugins/search-backend-node/src/IndexBuilder.ts +++ b/plugins/search-backend-node/src/IndexBuilder.ts @@ -16,9 +16,11 @@ import { DocumentCollator, DocumentDecorator } from '@backstage/search-common'; import { Logger } from 'winston'; + import { RegisterCollatorParameters, RegisterDecoratorParameters, + SearchEngine, } from './types'; interface CollatorEnvelope { @@ -27,18 +29,25 @@ interface CollatorEnvelope { } type IndexBuilderOptions = { + searchEngine: SearchEngine; logger: Logger; }; export class IndexBuilder { private collators: Record<string, CollatorEnvelope>; private decorators: Record<string, DocumentDecorator[]>; + private searchEngine: SearchEngine; private logger: Logger; - constructor({ logger }: IndexBuilderOptions) { + constructor({ logger, searchEngine }: IndexBuilderOptions) { this.collators = {}; this.decorators = {}; this.logger = logger; + this.searchEngine = searchEngine; + } + + getSearchEngine(): SearchEngine { + return this.searchEngine; } /** @@ -106,7 +115,13 @@ export class IndexBuilder { documents = await decorators[i].execute(documents); } - // TODO: push documents to a configured search engine. + if (!documents || documents.length === 0) { + this.logger.info(`No documents for type "${type}" to index`); + return; + } + + // pushing documents to index to a configured search engine. + this.searchEngine.index(type, documents); }), ); } diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts new file mode 100644 index 0000000000..6c348235e0 --- /dev/null +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts @@ -0,0 +1,325 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger } from '@backstage/backend-common'; +import { LunrSearchEngine } from './LunrSearchEngine'; +import { SearchEngine } from '../types'; + +describe('LunrSearchEngine', () => { + let testLunrSearchEngine: SearchEngine; + + beforeEach(() => { + testLunrSearchEngine = new LunrSearchEngine({ logger: getVoidLogger() }); + }); + + describe('translator', () => { + it('query translator invoked', async () => { + const translatorSpy = jest.spyOn(testLunrSearchEngine, 'translator'); + + // Translate query and ensure the translator was invoked. + await testLunrSearchEngine.translator({ + term: 'testTerm', + filters: {}, + pageCursor: '', + }); + + expect(translatorSpy).toHaveBeenCalled(); + expect(translatorSpy).toHaveBeenCalledWith({ + term: 'testTerm', + filters: {}, + pageCursor: '', + }); + }); + + it('should return translated query', async () => { + const mockedTranslatedQuery = await testLunrSearchEngine.translator({ + term: 'testTerm', + filters: {}, + pageCursor: '', + }); + + expect(mockedTranslatedQuery).toMatchObject({ + documentTypes: ['*'], + lunrQueryString: 'testTerm', + }); + }); + + it('should return translated query with 1 filter', async () => { + const mockedTranslatedQuery = await testLunrSearchEngine.translator({ + term: 'testTerm', + filters: { kind: 'testKind' }, + pageCursor: '', + }); + + expect(mockedTranslatedQuery).toMatchObject({ + documentTypes: ['*'], + lunrQueryString: 'testTerm +kind:testKind', + }); + }); + + it('should return translated query with multiple filters', async () => { + const mockedTranslatedQuery = await testLunrSearchEngine.translator({ + term: 'testTerm', + filters: { kind: 'testKind', namespace: 'testNameSpace' }, + pageCursor: '', + }); + + expect(mockedTranslatedQuery).toMatchObject({ + documentTypes: ['*'], + lunrQueryString: 'testTerm +kind:testKind +namespace:testNameSpace', + }); + }); + }); + + describe('query', () => { + it('should perform search query', async () => { + const querySpy = jest.spyOn(testLunrSearchEngine, 'query'); + + // Perform search query and ensure the query func was invoked. + const mockedSearchResult = await testLunrSearchEngine.query({ + term: 'testTerm', + filters: {}, + pageCursor: '', + }); + + expect(querySpy).toHaveBeenCalled(); + expect(querySpy).toHaveBeenCalledWith({ + term: 'testTerm', + filters: {}, + pageCursor: '', + }); + + // Should return 0 results as nothing is indexed here + expect(mockedSearchResult).toMatchObject({ results: [] }); + }); + + it('should perform search query and return 0 results on no match', async () => { + const mockDocuments = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + ]; + + // Mock indexing of 1 document + testLunrSearchEngine.index('test-index', mockDocuments); + + // Perform search query + const mockedSearchResult = await testLunrSearchEngine.query({ + term: 'testTerm', + filters: {}, + pageCursor: '', + }); + + // Should return 0 results as we are mocking the indexing of 1 document but with no match on the fields + expect(mockedSearchResult).toMatchObject({ results: [] }); + }); + + it('should perform search query and return search results on match', async () => { + const mockDocuments = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + ]; + + // Mock indexing of 1 document + testLunrSearchEngine.index('test-index', mockDocuments); + + // Perform search query + const mockedSearchResult = await testLunrSearchEngine.query({ + term: 'testTitle', + filters: {}, + pageCursor: '', + }); + + // Should return 1 result as we are mocking the indexing of 1 document with match on the title field + expect(mockedSearchResult).toMatchObject({ + results: [ + { + document: { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + }, + ], + }); + }); + + it('should perform search query and return search results on match with filters', async () => { + const mockDocuments = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + { + title: 'testTitle', + text: 'testText', + location: 'test/location2', + }, + ]; + + // Mock indexing of 2 documents + testLunrSearchEngine.index('test-index', mockDocuments); + + // Perform search query + const mockedSearchResult = await testLunrSearchEngine.query({ + term: 'testTitle', + filters: { location: 'test/location2' }, + pageCursor: '', + }); + + // Should return 1 of 2 results as we are + // 1. Mocking the indexing of 2 documents + // 2. Matching on the location field with the filter { location: 'test/location2' } + expect(mockedSearchResult).toMatchObject({ + results: [ + { + document: { + title: 'testTitle', + text: 'testText', + location: 'test/location2', + }, + }, + ], + }); + }); + + it('should perform search query and return search results on match with filter and not fail on missing field', async () => { + const mockDocuments = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + ]; + + const mockDocuments2 = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location2', + extraField: 'testExtraField', + }, + ]; + + // Mock 2 indices with 1 document each + testLunrSearchEngine.index('test-index', mockDocuments); + testLunrSearchEngine.index('test-index-2', mockDocuments2); + // Perform search query scoped to "test-index-2" with a filter on the field "extraField" + const mockedSearchResult = await testLunrSearchEngine.query({ + term: 'testTitle', + pageCursor: '', + filters: { extraField: 'testExtraField' }, + }); + + expect(mockedSearchResult).toMatchObject({ + results: [ + { + document: { + title: 'testTitle', + text: 'testText', + location: 'test/location2', + extraField: 'testExtraField', + }, + }, + ], + }); + }); + + it('should perform search query and return search results on match, scoped to specific index', async () => { + const mockDocuments = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location', + }, + { + title: 'testTitle', + text: 'testText', + location: 'test/location2', + }, + ]; + + const mockDocuments2 = [ + { + title: 'testTitle', + text: 'testText', + location: 'test/location3', + }, + { + title: 'testTitle', + text: 'testText', + location: 'test/location4', + }, + ]; + + // Mock 2 indices with 2 documents each + testLunrSearchEngine.index('test-index', mockDocuments); + testLunrSearchEngine.index('test-index-2', mockDocuments2); + + // Perform search query scoped to "test-index-2" + const mockedSearchResult = await testLunrSearchEngine.query({ + term: 'testTitle', + types: ['test-index-2'], + pageCursor: '', + }); + + expect(mockedSearchResult).toMatchObject({ + results: [ + { + document: { + location: 'test/location3', + text: 'testText', + title: 'testTitle', + }, + }, + { + document: { + location: 'test/location4', + text: 'testText', + title: 'testTitle', + }, + }, + ], + }); + }); + }); + + describe('index', () => { + it('should index document', async () => { + const indexSpy = jest.spyOn(testLunrSearchEngine, 'index'); + const mockDocuments = [ + { + title: 'testTerm', + text: 'testText', + location: 'test/location', + }, + ]; + + // call index func and ensure the index func was invoked. + testLunrSearchEngine.index('test-index', mockDocuments); + expect(indexSpy).toHaveBeenCalled(); + expect(indexSpy).toHaveBeenCalledWith('test-index', [ + { title: 'testTerm', text: 'testText', location: 'test/location' }, + ]); + }); + }); +}); diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts new file mode 100644 index 0000000000..cc8c5bb982 --- /dev/null +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -0,0 +1,134 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { + SearchQuery, + IndexableDocument, + SearchResultSet, +} from '@backstage/search-common'; +import lunr from 'lunr'; +import { Logger } from 'winston'; +import { SearchEngine, QueryTranslator } from '../types'; + +type ConcreteLunrQuery = { + lunrQueryString: string; + documentTypes: string[]; +}; + +export class LunrSearchEngine implements SearchEngine { + protected lunrIndices: Record<string, lunr.Index> = {}; + protected docStore: Record<string, IndexableDocument>; + protected logger: Logger; + + constructor({ logger }: { logger: Logger }) { + this.logger = logger; + this.docStore = {}; + } + + translator: QueryTranslator = ({ + term, + filters, + types, + }: SearchQuery): ConcreteLunrQuery => { + let lunrQueryFilters; + if (filters) { + lunrQueryFilters = Object.entries(filters) + .map(([key, value]) => ` +${key}:${value}`) + .join(''); + } + + return { + lunrQueryString: `${term}${lunrQueryFilters || ''}`, + documentTypes: types || ['*'], + }; + }; + + index(type: string, documents: IndexableDocument[]): void { + const lunrBuilder = new lunr.Builder(); + // Make this lunr index aware of all relevant fields. + Object.keys(documents[0]).forEach(field => { + lunrBuilder.field(field); + }); + + // Set "location" field as reference field + lunrBuilder.ref('location'); + + documents.forEach((document: IndexableDocument) => { + // Add document to Lunar index + lunrBuilder.add(document); + // Store documents in memory to be able to look up document using the ref during query time + // This is not how you should implement your SearchEngine implementation! Do not copy! + this.docStore[document.location] = document; + }); + + // "Rotate" the index by simply overwriting any existing index of the same name. + this.lunrIndices[type] = lunrBuilder.build(); + } + + query(query: SearchQuery): Promise<SearchResultSet> { + const { lunrQueryString, documentTypes } = this.translator( + query, + ) as ConcreteLunrQuery; + + const results: lunr.Index.Result[] = []; + + if (documentTypes.length === 1 && documentTypes[0] === '*') { + // Iterate over all this.lunrIndex values. + Object.values(this.lunrIndices).forEach(i => { + try { + results.push(...i.search(lunrQueryString)); + } catch (err) { + // if a field does not exist on a index, we can see that as a no-match + if ( + err instanceof lunr.QueryParseError && + err.message.startsWith('unrecognised field') + ) + return; + } + }); + } else { + // Iterate over the filtered list of this.lunrIndex keys. + Object.keys(this.lunrIndices) + .filter(d => documentTypes.includes(d)) + .forEach(d => { + try { + results.push(...this.lunrIndices[d].search(lunrQueryString)); + } catch (err) { + // if a field does not exist on a index, we can see that as a no-match + if ( + err instanceof lunr.QueryParseError && + err.message.startsWith('unrecognised field') + ) + return; + } + }); + } + + // Sort results. + results.sort((doc1, doc2) => { + return doc2.score - doc1.score; + }); + + // Translate results into SearchResultSet + const resultSet: SearchResultSet = { + results: results.map(d => { + return { document: this.docStore[d.ref] }; + }), + }; + + return Promise.resolve(resultSet); + } +} diff --git a/plugins/search-backend-node/src/engines/index.ts b/plugins/search-backend-node/src/engines/index.ts new file mode 100644 index 0000000000..ed7079ef62 --- /dev/null +++ b/plugins/search-backend-node/src/engines/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { LunrSearchEngine } from './LunrSearchEngine'; diff --git a/plugins/search-backend-node/src/index.test.ts b/plugins/search-backend-node/src/index.test.ts index 0941f23540..0c66db372a 100644 --- a/plugins/search-backend-node/src/index.test.ts +++ b/plugins/search-backend-node/src/index.test.ts @@ -21,6 +21,7 @@ import { IndexableDocument, } from '@backstage/search-common'; import { IndexBuilder } from './IndexBuilder'; +import { LunrSearchEngine, SearchEngine } from './index'; class TestDocumentCollator implements DocumentCollator { async execute() { @@ -35,12 +36,18 @@ class TestDocumentDecorator implements DocumentDecorator { } describe('IndexBuilder', () => { + let testSearchEngine: SearchEngine; let testIndexBuilder: IndexBuilder; let testCollator: DocumentCollator; let testDecorator: DocumentDecorator; beforeEach(() => { - testIndexBuilder = new IndexBuilder({ logger: getVoidLogger() }); + const logger = getVoidLogger(); + testSearchEngine = new LunrSearchEngine({ logger }); + testIndexBuilder = new IndexBuilder({ + logger, + searchEngine: testSearchEngine, + }); testCollator = new TestDocumentCollator(); testDecorator = new TestDocumentDecorator(); }); diff --git a/plugins/search-backend-node/src/index.ts b/plugins/search-backend-node/src/index.ts index 924dfbc9dc..a3a0eb855e 100644 --- a/plugins/search-backend-node/src/index.ts +++ b/plugins/search-backend-node/src/index.ts @@ -15,3 +15,5 @@ */ export { IndexBuilder } from './IndexBuilder'; +export { LunrSearchEngine } from './engines'; +export type { SearchEngine } from './types'; diff --git a/plugins/search-backend-node/src/types.ts b/plugins/search-backend-node/src/types.ts index e55faccfb4..4abfa77fb1 100644 --- a/plugins/search-backend-node/src/types.ts +++ b/plugins/search-backend-node/src/types.ts @@ -14,7 +14,13 @@ * limitations under the License. */ -import { DocumentCollator, DocumentDecorator } from '@backstage/search-common'; +import { + DocumentCollator, + DocumentDecorator, + IndexableDocument, + SearchQuery, + SearchResultSet, +} from '@backstage/search-common'; /** * Parameters required to register a collator. @@ -51,3 +57,20 @@ export interface RegisterDecoratorParameters { */ types?: string[]; } + +/** + * A type of function responsible for translating an abstract search query into + * a concrete query relevant to a particular search engine. + */ +export type QueryTranslator = (query: SearchQuery) => unknown; + +/** + * Interface that must be implemented by specific search engines, responsible + * for performing indexing and querying and translating abstract queries into + * concrete, search engine-specific queries. + */ +export interface SearchEngine { + translator: QueryTranslator; + index(type: string, documents: IndexableDocument[]): void; + query(query: SearchQuery): Promise<SearchResultSet>; +} diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index a7d588b4b1..82b72e9506 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -21,6 +21,7 @@ "dependencies": { "@backstage/backend-common": "^0.6.0", "@backstage/search-common": "^0.1.1", + "@backstage/plugin-search-backend-node": "^0.1.2", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index ba7032eb93..9b7cf83ba5 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -15,6 +15,10 @@ */ import { getVoidLogger } from '@backstage/backend-common'; +import { + IndexBuilder, + LunrSearchEngine, +} from '@backstage/plugin-search-backend-node'; import express from 'express'; import request from 'supertest'; @@ -24,8 +28,12 @@ describe('createRouter', () => { let app: express.Express; beforeAll(async () => { + const logger = getVoidLogger(); + const searchEngine = new LunrSearchEngine({ logger }); + const indexBuilder = new IndexBuilder({ logger, searchEngine }); const router = await createRouter({ - logger: getVoidLogger(), + engine: indexBuilder.getSearchEngine(), + logger, }); app = express().use(router); }); diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index 1a0c67bdb8..6b757fee16 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -18,23 +18,24 @@ import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; import { SearchQuery, SearchResultSet } from '@backstage/search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; type RouterOptions = { + engine: SearchEngine; logger: Logger; }; export async function createRouter({ + engine, logger, }: RouterOptions): Promise<express.Router> { const router = Router(); - router.get( '/query', async ( req: express.Request<any, unknown, unknown, SearchQuery>, res: express.Response<SearchResultSet>, ) => { - // TODO: Actually transform req.params into search engine specific query. const { term, filters = {}, pageCursor = '' } = req.query; logger.info( `Search request received: ${term}, ${JSON.stringify( @@ -43,13 +44,12 @@ export async function createRouter({ ); try { - // TODO: Actually query search engine. - // TODO: And actually transform results into frontend-readable result - res.send({ - results: [], - }); + const results = await engine?.query(req.query); + res.send(results); } catch (err) { - throw new Error(`There was a problem performing the search query.`); + throw new Error( + `There was a problem performing the search query. ${err}`, + ); } }, ); diff --git a/plugins/search-backend/src/service/standaloneServer.ts b/plugins/search-backend/src/service/standaloneServer.ts index b0c53a6adc..df42e3dda2 100644 --- a/plugins/search-backend/src/service/standaloneServer.ts +++ b/plugins/search-backend/src/service/standaloneServer.ts @@ -18,6 +18,10 @@ import { createServiceBuilder } from '@backstage/backend-common'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; +import { + LunrSearchEngine, + IndexBuilder, +} from '@backstage/plugin-search-backend-node'; export interface ServerOptions { port: number; @@ -29,8 +33,14 @@ export async function startStandaloneServer( options: ServerOptions, ): Promise<Server> { const logger = options.logger.child({ service: 'search-backend' }); + const searchEngine = new LunrSearchEngine({ logger }); + const indexBuilder = new IndexBuilder({ logger, searchEngine }); logger.debug('Starting application server...'); + + // TODO: stub out some documents/indices? + const router = await createRouter({ + engine: indexBuilder.getSearchEngine(), logger, }); diff --git a/yarn.lock b/yarn.lock index dfa07a5397..df07058f48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6210,6 +6210,11 @@ resolved "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03" integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w== +"@types/lunr@^2.3.3": + version "2.3.3" + resolved "https://registry.npmjs.org/@types/lunr/-/lunr-2.3.3.tgz#ec985618fd2712c010f8edab4f1ae7784ad7c583" + integrity sha512-09sXZZVsB3Ib41U0fC+O1O+4UOZT1bl/e+/QubPxpqDWHNEchvx/DEb1KJMOwq6K3MTNzZFoNSzVdR++o1DVnw== + "@types/luxon@^1.25.0": version "1.26.0" resolved "https://registry.npmjs.org/@types/luxon/-/luxon-1.26.0.tgz#8e783986370ad3bb9f885d93eb1a91caeecaed36" @@ -17927,6 +17932,11 @@ lru-queue@^0.1.0: dependencies: es5-ext "~0.10.2" +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + luxon@1.25.0, luxon@^1.25.0: version "1.25.0" resolved "https://registry.npmjs.org/luxon/-/luxon-1.25.0.tgz#d86219e90bc0102c0eb299d65b2f5e95efe1fe72" From 034998d53756690a2ada42a1a78d79174e52480c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Apr 2021 13:19:35 +0000 Subject: [PATCH 085/262] Version Packages --- .changeset/chatty-parents-search.md | 5 --- .changeset/dry-carrots-impress.md | 6 --- .changeset/dry-elephants-doubt.md | 5 --- .changeset/eight-plums-hide.md | 5 --- .changeset/eighty-crews-rhyme.md | 5 --- .changeset/fair-carrots-tell.md | 5 --- .changeset/flat-paws-rule.md | 6 --- .changeset/fluffy-suns-repair.md | 5 --- .changeset/fresh-cheetahs-rush.md | 5 --- .changeset/giant-onions-obey.md | 5 --- .changeset/good-glasses-build.md | 6 --- .changeset/gorgeous-pumas-cover.md | 5 --- .changeset/great-years-battle.md | 14 ------ .changeset/grumpy-games-shop.md | 5 --- .changeset/healthy-stingrays-shout.md | 5 --- .changeset/light-fireants-flow.md | 5 --- .changeset/light-horses-hammer.md | 5 --- .changeset/moody-pigs-repeat.md | 5 --- .changeset/new-shirts-move.md | 5 --- .changeset/quiet-badgers-cheer.md | 11 ----- .changeset/real-apples-visit.md | 5 --- .changeset/rotten-cups-bow.md | 6 --- .changeset/rude-items-bow.md | 5 --- .changeset/six-turtles-sip.md | 6 --- .changeset/sour-plums-enjoy.md | 7 --- .changeset/stale-carpets-poke.md | 30 ------------- .changeset/stale-chefs-retire.md | 5 --- .changeset/strong-houses-lick.md | 6 --- .changeset/techdocs-eight-camels-hear.md | 7 --- .changeset/techdocs-swift-mugs-invent.md | 5 --- .changeset/tiny-ears-love.md | 5 --- .changeset/unlucky-starfishes-vanish.md | 6 --- packages/app/CHANGELOG.md | 31 +++++++++++++ packages/app/package.json | 18 ++++---- packages/backend-common/CHANGELOG.md | 8 ++++ packages/backend-common/package.json | 4 +- packages/backend/CHANGELOG.md | 24 ++++++++++ packages/backend/package.json | 22 ++++----- packages/cli/CHANGELOG.md | 8 ++++ packages/cli/package.json | 8 ++-- packages/core-api/CHANGELOG.md | 9 ++++ packages/core-api/package.json | 6 +-- packages/core/CHANGELOG.md | 17 +++++++ packages/core/package.json | 8 ++-- packages/create-app/CHANGELOG.md | 52 ++++++++++++++++++++++ packages/create-app/package.json | 2 +- packages/theme/CHANGELOG.md | 6 +++ packages/theme/package.json | 4 +- plugins/api-docs/package.json | 6 +-- plugins/badges/package.json | 6 +-- plugins/bitrise/package.json | 6 +-- plugins/catalog-backend/CHANGELOG.md | 50 +++++++++++++++++++++ plugins/catalog-backend/package.json | 10 ++--- plugins/catalog-import/CHANGELOG.md | 16 +++++++ plugins/catalog-import/package.json | 8 ++-- plugins/catalog/CHANGELOG.md | 17 +++++++ plugins/catalog/package.json | 8 ++-- plugins/circleci/package.json | 6 +-- plugins/cloudbuild/package.json | 6 +-- plugins/code-coverage-backend/CHANGELOG.md | 10 +++++ plugins/code-coverage-backend/package.json | 6 +-- plugins/code-coverage/CHANGELOG.md | 17 +++++++ plugins/code-coverage/package.json | 8 ++-- plugins/config-schema/package.json | 6 +-- plugins/cost-insights/package.json | 6 +-- plugins/explore/package.json | 6 +-- plugins/fossa/CHANGELOG.md | 17 +++++++ plugins/fossa/package.json | 8 ++-- plugins/gcp-projects/package.json | 6 +-- plugins/github-actions/package.json | 6 +-- plugins/github-deployments/CHANGELOG.md | 16 +++++++ plugins/github-deployments/package.json | 8 ++-- plugins/gitops-profiles/package.json | 6 +-- plugins/graphiql/package.json | 6 +-- plugins/jenkins/package.json | 6 +-- plugins/kafka/package.json | 6 +-- plugins/kubernetes-backend/CHANGELOG.md | 9 ++++ plugins/kubernetes-backend/package.json | 6 +-- plugins/kubernetes/package.json | 6 +-- plugins/lighthouse/package.json | 6 +-- plugins/newrelic/package.json | 6 +-- plugins/org/package.json | 6 +-- plugins/pagerduty/package.json | 6 +-- plugins/register-component/package.json | 6 +-- plugins/rollbar-backend/CHANGELOG.md | 18 ++++++++ plugins/rollbar-backend/package.json | 6 +-- plugins/rollbar/package.json | 6 +-- plugins/scaffolder-backend/CHANGELOG.md | 21 +++++++++ plugins/scaffolder-backend/package.json | 6 +-- plugins/scaffolder/CHANGELOG.md | 17 +++++++ plugins/scaffolder/package.json | 8 ++-- plugins/search-backend-node/CHANGELOG.md | 6 +++ plugins/search-backend-node/package.json | 6 +-- plugins/search-backend/CHANGELOG.md | 11 +++++ plugins/search-backend/package.json | 8 ++-- plugins/search/package.json | 6 +-- plugins/sentry/package.json | 6 +-- plugins/sonarqube/package.json | 6 +-- plugins/splunk-on-call/package.json | 6 +-- plugins/tech-radar/package.json | 6 +-- plugins/techdocs/CHANGELOG.md | 22 +++++++++ plugins/techdocs/package.json | 8 ++-- plugins/todo/package.json | 6 +-- plugins/user-settings/package.json | 6 +-- plugins/welcome/CHANGELOG.md | 16 +++++++ plugins/welcome/package.json | 8 ++-- 106 files changed, 594 insertions(+), 387 deletions(-) delete mode 100644 .changeset/chatty-parents-search.md delete mode 100644 .changeset/dry-carrots-impress.md delete mode 100644 .changeset/dry-elephants-doubt.md delete mode 100644 .changeset/eight-plums-hide.md delete mode 100644 .changeset/eighty-crews-rhyme.md delete mode 100644 .changeset/fair-carrots-tell.md delete mode 100644 .changeset/flat-paws-rule.md delete mode 100644 .changeset/fluffy-suns-repair.md delete mode 100644 .changeset/fresh-cheetahs-rush.md delete mode 100644 .changeset/giant-onions-obey.md delete mode 100644 .changeset/good-glasses-build.md delete mode 100644 .changeset/gorgeous-pumas-cover.md delete mode 100644 .changeset/great-years-battle.md delete mode 100644 .changeset/grumpy-games-shop.md delete mode 100644 .changeset/healthy-stingrays-shout.md delete mode 100644 .changeset/light-fireants-flow.md delete mode 100644 .changeset/light-horses-hammer.md delete mode 100644 .changeset/moody-pigs-repeat.md delete mode 100644 .changeset/new-shirts-move.md delete mode 100644 .changeset/quiet-badgers-cheer.md delete mode 100644 .changeset/real-apples-visit.md delete mode 100644 .changeset/rotten-cups-bow.md delete mode 100644 .changeset/rude-items-bow.md delete mode 100644 .changeset/six-turtles-sip.md delete mode 100644 .changeset/sour-plums-enjoy.md delete mode 100644 .changeset/stale-carpets-poke.md delete mode 100644 .changeset/stale-chefs-retire.md delete mode 100644 .changeset/strong-houses-lick.md delete mode 100644 .changeset/techdocs-eight-camels-hear.md delete mode 100644 .changeset/techdocs-swift-mugs-invent.md delete mode 100644 .changeset/tiny-ears-love.md delete mode 100644 .changeset/unlucky-starfishes-vanish.md create mode 100644 plugins/code-coverage-backend/CHANGELOG.md create mode 100644 plugins/code-coverage/CHANGELOG.md diff --git a/.changeset/chatty-parents-search.md b/.changeset/chatty-parents-search.md deleted file mode 100644 index d9b1222d8f..0000000000 --- a/.changeset/chatty-parents-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Sort the table filter options by name. diff --git a/.changeset/dry-carrots-impress.md b/.changeset/dry-carrots-impress.md deleted file mode 100644 index aa057beb58..0000000000 --- a/.changeset/dry-carrots-impress.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-search-backend': patch -'@backstage/plugin-search-backend-node': patch ---- - -Lunr Search Engine support diff --git a/.changeset/dry-elephants-doubt.md b/.changeset/dry-elephants-doubt.md deleted file mode 100644 index 7a9ccc9892..0000000000 --- a/.changeset/dry-elephants-doubt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-deployments': patch ---- - -Adds extraColumns field to GitHub Deployments card diff --git a/.changeset/eight-plums-hide.md b/.changeset/eight-plums-hide.md deleted file mode 100644 index d1f8bcecfe..0000000000 --- a/.changeset/eight-plums-hide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Forward user token to scaffolder task for subsequent api requests diff --git a/.changeset/eighty-crews-rhyme.md b/.changeset/eighty-crews-rhyme.md deleted file mode 100644 index 5a8379acb6..0000000000 --- a/.changeset/eighty-crews-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Exposing Material UI extension point for tabs to be able to add additional information to them diff --git a/.changeset/fair-carrots-tell.md b/.changeset/fair-carrots-tell.md deleted file mode 100644 index 62dce5c3ce..0000000000 --- a/.changeset/fair-carrots-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Add `config:docs` command that opens up reference documentation for the local configuration schema in a browser. diff --git a/.changeset/flat-paws-rule.md b/.changeset/flat-paws-rule.md deleted file mode 100644 index af7725793e..0000000000 --- a/.changeset/flat-paws-rule.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core': patch -'@backstage/plugin-scaffolder': patch ---- - -Adding Headings for Accessibility on the Scaffolder Plugin diff --git a/.changeset/fluffy-suns-repair.md b/.changeset/fluffy-suns-repair.md deleted file mode 100644 index 6f45905219..0000000000 --- a/.changeset/fluffy-suns-repair.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Respect top-level UI schema keys in scaffolder forms. Allows more advanced RJSF features such as explicit field ordering. diff --git a/.changeset/fresh-cheetahs-rush.md b/.changeset/fresh-cheetahs-rush.md deleted file mode 100644 index fe8a9caafb..0000000000 --- a/.changeset/fresh-cheetahs-rush.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -No longer add newly created plugins to `plugins.ts` in the app, as it is no longer needed. diff --git a/.changeset/giant-onions-obey.md b/.changeset/giant-onions-obey.md deleted file mode 100644 index fbf9faa0a3..0000000000 --- a/.changeset/giant-onions-obey.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-import': patch ---- - -allow import from HTTP repositories diff --git a/.changeset/good-glasses-build.md b/.changeset/good-glasses-build.md deleted file mode 100644 index 3d506d3e43..0000000000 --- a/.changeset/good-glasses-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-api': patch -'@backstage/core': patch ---- - -Add support for discovering plugins through the app element tree, removing the need to register them explicitly. diff --git a/.changeset/gorgeous-pumas-cover.md b/.changeset/gorgeous-pumas-cover.md deleted file mode 100644 index c4c9facac4..0000000000 --- a/.changeset/gorgeous-pumas-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-welcome': patch ---- - -Australian Greeting diff --git a/.changeset/great-years-battle.md b/.changeset/great-years-battle.md deleted file mode 100644 index a2d61be11a..0000000000 --- a/.changeset/great-years-battle.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@backstage/plugin-rollbar-backend': patch -'@backstage/plugin-scaffolder-backend': minor ---- - -Fix some `spleling`. - -The `scaffolder-backend` has a configuration schema change that may be breaking -in rare circumstances. Due to a typo in the schema, the -`scaffolder.github.visibility`, `scaffolder.gitlab.visibility`, and -`scaffolder.bitbucket.visibility` did not get proper validation that the value -is one of the supported strings (`public`, `internal` (not available for -Bitbucket), and `private`). If you had a value that was not one of these three, -you may have to adjust your config. diff --git a/.changeset/grumpy-games-shop.md b/.changeset/grumpy-games-shop.md deleted file mode 100644 index 7426786f89..0000000000 --- a/.changeset/grumpy-games-shop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -remove use of deprecated type HelmetOptions diff --git a/.changeset/healthy-stingrays-shout.md b/.changeset/healthy-stingrays-shout.md deleted file mode 100644 index c3ce59ce1f..0000000000 --- a/.changeset/healthy-stingrays-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -SystemDiagramCard UI improvements diff --git a/.changeset/light-fireants-flow.md b/.changeset/light-fireants-flow.md deleted file mode 100644 index a8f7b09278..0000000000 --- a/.changeset/light-fireants-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Fix the schema / code mismatch in LDAP `set` config diff --git a/.changeset/light-horses-hammer.md b/.changeset/light-horses-hammer.md deleted file mode 100644 index 0d421c7056..0000000000 --- a/.changeset/light-horses-hammer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/theme': patch ---- - -Replace the link color in dark theme diff --git a/.changeset/moody-pigs-repeat.md b/.changeset/moody-pigs-repeat.md deleted file mode 100644 index 396fa80281..0000000000 --- a/.changeset/moody-pigs-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Exported SignInProviderConfig to strongly type SignInPage providers diff --git a/.changeset/new-shirts-move.md b/.changeset/new-shirts-move.md deleted file mode 100644 index 3896c85bbb..0000000000 --- a/.changeset/new-shirts-move.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Add low german greeting diff --git a/.changeset/quiet-badgers-cheer.md b/.changeset/quiet-badgers-cheer.md deleted file mode 100644 index e22bf9492c..0000000000 --- a/.changeset/quiet-badgers-cheer.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Removed `plugins.ts` from the app, as plugins are now discovered through the react tree. - -To apply this change to an existing app, simply delete `packages/app/src/plugins.ts` along with the import and usage in `packages/app/src/App.tsx`. - -Note that there are a few plugins that require explicit registration, in which case you would need to keep them in `plugins.ts`. The set of plugins that need explicit registration is any plugin that doesn't have a component extension that gets rendered as part of the app element tree. An example of such a plugin in the main Backstage repo is `@backstage/plugin-badges`. In the case of the badges plugin this is because there is not yet a component-based API for adding context menu items to the entity layout. - -If you have plugins that still rely on route registration through the `register` method of `createPlugin`, these need to be kept in `plugins.ts` as well. However, it is recommended to migrate these to export an extensions component instead. diff --git a/.changeset/real-apples-visit.md b/.changeset/real-apples-visit.md deleted file mode 100644 index b5165f633b..0000000000 --- a/.changeset/real-apples-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -GithubDiscoveryProcessor now excludes archived repositories so they won't be added to Backstage. diff --git a/.changeset/rotten-cups-bow.md b/.changeset/rotten-cups-bow.md deleted file mode 100644 index 967681171d..0000000000 --- a/.changeset/rotten-cups-bow.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-code-coverage': patch -'@backstage/plugin-code-coverage-backend': patch ---- - -Update tests to function in windows diff --git a/.changeset/rude-items-bow.md b/.changeset/rude-items-bow.md deleted file mode 100644 index 69b76d821e..0000000000 --- a/.changeset/rude-items-bow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch ---- - -Kubernetes client TLS verification is now configurable and defaults to true diff --git a/.changeset/six-turtles-sip.md b/.changeset/six-turtles-sip.md deleted file mode 100644 index e71b04e64d..0000000000 --- a/.changeset/six-turtles-sip.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Support configuration of file storage for SQLite databases. Every plugin has its -own database file at the specified path. diff --git a/.changeset/sour-plums-enjoy.md b/.changeset/sour-plums-enjoy.md deleted file mode 100644 index ef68166255..0000000000 --- a/.changeset/sour-plums-enjoy.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Fix system diagram card to be on the system page - -To apply the same fix to an existing application, in `EntityPage.tsx` simply move the `<EntityLayout.route>` for the `/diagram` path from the `groupPage` down into the `systemPage` element. diff --git a/.changeset/stale-carpets-poke.md b/.changeset/stale-carpets-poke.md deleted file mode 100644 index 4f39e57b71..0000000000 --- a/.changeset/stale-carpets-poke.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Externalize repository processing for BitbucketDiscoveryProcessor. - -Add an extension point where you can customize how a matched Bitbucket repository should -be processed. This can for example be used if you want to generate the catalog-info.yaml -automatically based on other files in a repository, while taking advantage of the -build-in repository crawling functionality. - -`BitbucketDiscoveryProcessor.fromConfig` now takes an optional parameter `options.parser` where -you can customize the logic for each repository found. The default parser has the same -behaviour as before, where it emits an optional location for the matched repository -and lets the other processors take care of further processing. - -```typescript -const customRepositoryParser: BitbucketRepositoryParser = async function* customRepositoryParser({ - client, - repository, -}) { - // Custom logic for interpret the matching repository. - // See defaultRepositoryParser for an example -}; - -const processor = BitbucketDiscoveryProcessor.fromConfig(env.config, { - parser: customRepositoryParser, - logger: env.logger, -}); -``` diff --git a/.changeset/stale-chefs-retire.md b/.changeset/stale-chefs-retire.md deleted file mode 100644 index e43c20062a..0000000000 --- a/.changeset/stale-chefs-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Adding close button on support menu diff --git a/.changeset/strong-houses-lick.md b/.changeset/strong-houses-lick.md deleted file mode 100644 index 9739bdfda1..0000000000 --- a/.changeset/strong-houses-lick.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-api': patch -'@backstage/core': patch ---- - -Fixed a potentially confusing error being thrown about misuse of routable extensions where the error was actually something different. diff --git a/.changeset/techdocs-eight-camels-hear.md b/.changeset/techdocs-eight-camels-hear.md deleted file mode 100644 index 8f2479f6bd..0000000000 --- a/.changeset/techdocs-eight-camels-hear.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-techdocs': minor ---- - -Add feedback link icon in Techdocs Reader that directs to GitLab or GitHub repo issue page with pre-filled title and source link. -For link to appear, requires `repo_url` and `edit_uri` to be filled in mkdocs.yml, as per https://www.mkdocs.org/user-guide/configuration. An `edit_uri` will need to be specified for self-hosted GitLab/GitHub instances with a different host name. -To identify issue URL format as GitHub or GitLab, the host name of source in `repo_url` is checked if it contains `gitlab` or `github`. Alternately this is determined by matching to `host` values from `integrations` in app-config.yaml. diff --git a/.changeset/techdocs-swift-mugs-invent.md b/.changeset/techdocs-swift-mugs-invent.md deleted file mode 100644 index 912089fb3c..0000000000 --- a/.changeset/techdocs-swift-mugs-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Add a test id to the shadow root element of the Reader to access it easily in e2e tests diff --git a/.changeset/tiny-ears-love.md b/.changeset/tiny-ears-love.md deleted file mode 100644 index 9c3d1613a5..0000000000 --- a/.changeset/tiny-ears-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Added support for Datadog rum events diff --git a/.changeset/unlucky-starfishes-vanish.md b/.changeset/unlucky-starfishes-vanish.md deleted file mode 100644 index 3bb341bee9..0000000000 --- a/.changeset/unlucky-starfishes-vanish.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-fossa': patch ---- - -Add a `FossaPage` that shows the license compliance status of all components in the catalog. -See the projects `Readme` on how to use it. diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 81a7f66f4c..7262b2ae29 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,36 @@ # example-app +## 0.2.25 + +### Patch Changes + +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [4e5c94249] +- Updated dependencies [99fbef232] +- Updated dependencies [cb0206b2b] +- Updated dependencies [1373f4f12] +- Updated dependencies [29a7e4be8] +- Updated dependencies [ab07d77f6] +- Updated dependencies [96728a2af] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [87c4f59de] +- Updated dependencies [55b2fc0c0] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] +- Updated dependencies [ac6025f63] +- Updated dependencies [e292e393f] +- Updated dependencies [479b29124] + - @backstage/core@0.7.6 + - @backstage/cli@0.6.9 + - @backstage/plugin-scaffolder@0.9.1 + - @backstage/plugin-catalog-import@0.5.3 + - @backstage/plugin-catalog@0.5.5 + - @backstage/theme@0.2.6 + - @backstage/plugin-code-coverage@0.1.2 + - @backstage/plugin-techdocs@0.8.0 + ## 0.2.24 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 95e14766c3..ba9af03310 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,21 +1,21 @@ { "name": "example-app", - "version": "0.2.24", + "version": "0.2.25", "private": true, "bundled": true, "dependencies": { "@backstage/catalog-model": "^0.7.7", - "@backstage/cli": "^0.6.8", - "@backstage/core": "^0.7.5", + "@backstage/cli": "^0.6.9", + "@backstage/core": "^0.7.6", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-api-docs": "^0.4.11", "@backstage/plugin-badges": "^0.2.0", - "@backstage/plugin-catalog": "^0.5.4", - "@backstage/plugin-catalog-import": "^0.5.2", + "@backstage/plugin-catalog": "^0.5.5", + "@backstage/plugin-catalog-import": "^0.5.3", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/plugin-circleci": "^0.2.12", "@backstage/plugin-cloudbuild": "^0.2.13", - "@backstage/plugin-code-coverage": "^0.1.0", + "@backstage/plugin-code-coverage": "^0.1.2", "@backstage/plugin-cost-insights": "^0.8.4", "@backstage/plugin-explore": "^0.3.2", "@backstage/plugin-gcp-projects": "^0.2.5", @@ -29,14 +29,14 @@ "@backstage/plugin-org": "^0.3.12", "@backstage/plugin-pagerduty": "0.3.2", "@backstage/plugin-rollbar": "^0.3.3", - "@backstage/plugin-scaffolder": "^0.9.0", + "@backstage/plugin-scaffolder": "^0.9.1", "@backstage/plugin-search": "^0.3.4", "@backstage/plugin-sentry": "^0.3.8", "@backstage/plugin-tech-radar": "^0.3.9", - "@backstage/plugin-techdocs": "^0.7.2", + "@backstage/plugin-techdocs": "^0.8.0", "@backstage/plugin-todo": "^0.1.0", "@backstage/plugin-user-settings": "^0.2.8", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@octokit/rest": "^18.0.12", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index c194f7e666..68fab7d861 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/backend-common +## 0.6.3 + +### Patch Changes + +- d367f63b5: remove use of deprecated type HelmetOptions +- b42531cfe: Support configuration of file storage for SQLite databases. Every plugin has its + own database file at the specified path. + ## 0.6.2 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 41fa657818..998ac475d9 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.6.2", + "version": "0.6.3", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -73,7 +73,7 @@ } }, "devDependencies": { - "@backstage/cli": "^0.6.7", + "@backstage/cli": "^0.6.9", "@backstage/test-utils": "^0.1.10", "@types/archiver": "^5.1.0", "@types/compression": "^1.7.0", diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 6585ea2723..ee04e2bb6b 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,29 @@ # example-backend +## 0.2.25 + +### Patch Changes + +- Updated dependencies [b9b2b4b76] +- Updated dependencies [84c54474d] +- Updated dependencies [49574a8a3] +- Updated dependencies [d367f63b5] +- Updated dependencies [5fe62f124] +- Updated dependencies [09b5fcf2e] +- Updated dependencies [55b2fc0c0] +- Updated dependencies [c42cd1daa] +- Updated dependencies [b42531cfe] +- Updated dependencies [c2306f898] + - @backstage/plugin-search-backend@0.1.3 + - @backstage/plugin-search-backend-node@0.1.3 + - @backstage/plugin-scaffolder-backend@0.10.0 + - @backstage/plugin-rollbar-backend@0.1.9 + - @backstage/backend-common@0.6.3 + - @backstage/plugin-catalog-backend@0.8.0 + - @backstage/plugin-code-coverage-backend@0.1.2 + - @backstage/plugin-kubernetes-backend@0.3.5 + - example-app@0.2.25 + ## 0.2.22 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 984b8b60a5..440ceca8e5 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.22", + "version": "0.2.25", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,30 +27,30 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.6.1", + "@backstage/backend-common": "^0.6.3", "@backstage/catalog-client": "^0.3.9", "@backstage/catalog-model": "^0.7.5", "@backstage/config": "^0.1.4", "@backstage/plugin-app-backend": "^0.3.10", "@backstage/plugin-auth-backend": "^0.3.7", "@backstage/plugin-badges-backend": "^0.1.1", - "@backstage/plugin-catalog-backend": "^0.7.0", - "@backstage/plugin-code-coverage-backend": "^0.1.0", + "@backstage/plugin-catalog-backend": "^0.8.0", + "@backstage/plugin-code-coverage-backend": "^0.1.2", "@backstage/plugin-graphql-backend": "^0.1.6", - "@backstage/plugin-kubernetes-backend": "^0.3.3", + "@backstage/plugin-kubernetes-backend": "^0.3.5", "@backstage/plugin-kafka-backend": "^0.2.3", "@backstage/plugin-proxy-backend": "^0.2.6", - "@backstage/plugin-rollbar-backend": "^0.1.8", - "@backstage/plugin-scaffolder-backend": "^0.9.4", - "@backstage/plugin-search-backend": "^0.1.2", - "@backstage/plugin-search-backend-node": "^0.1.2", + "@backstage/plugin-rollbar-backend": "^0.1.9", + "@backstage/plugin-scaffolder-backend": "^0.10.0", + "@backstage/plugin-search-backend": "^0.1.3", + "@backstage/plugin-search-backend-node": "^0.1.3", "@backstage/plugin-techdocs-backend": "^0.7.0", "@backstage/plugin-todo-backend": "^0.1.3", "@gitbeaker/node": "^28.0.2", "@octokit/rest": "^18.0.12", "azure-devops-node-api": "^10.1.1", "dockerode": "^3.2.1", - "example-app": "^0.2.21", + "example-app": "^0.2.25", "express": "^4.17.1", "express-promise-router": "^4.1.0", "knex": "^0.95.1", @@ -60,7 +60,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.9", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index a1381495ff..af452b3c9d 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/cli +## 0.6.9 + +### Patch Changes + +- 4e5c94249: Add `config:docs` command that opens up reference documentation for the local configuration schema in a browser. +- 1373f4f12: No longer add newly created plugins to `plugins.ts` in the app, as it is no longer needed. +- 479b29124: Added support for Datadog rum events + ## 0.6.8 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 251b2ab076..cd61193efe 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.6.8", + "version": "0.6.9", "private": false, "publishConfig": { "access": "public" @@ -116,12 +116,12 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.6.2", + "@backstage/backend-common": "^0.6.3", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", diff --git a/packages/core-api/CHANGELOG.md b/packages/core-api/CHANGELOG.md index 609940b8db..fab82a77e5 100644 --- a/packages/core-api/CHANGELOG.md +++ b/packages/core-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/core-api +## 0.2.17 + +### Patch Changes + +- ab07d77f6: Add support for discovering plugins through the app element tree, removing the need to register them explicitly. +- 50ce875a0: Fixed a potentially confusing error being thrown about misuse of routable extensions where the error was actually something different. +- Updated dependencies [931b21a12] + - @backstage/theme@0.2.6 + ## 0.2.16 ### Patch Changes diff --git a/packages/core-api/package.json b/packages/core-api/package.json index 33e5ac146d..a55df67343 100644 --- a/packages/core-api/package.json +++ b/packages/core-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-api", "description": "Internal Core API used by Backstage plugins and apps", - "version": "0.2.16", + "version": "0.2.17", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@types/react": "^16.9", @@ -42,7 +42,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.7", + "@backstage/cli": "^0.6.9", "@backstage/test-utils": "^0.1.10", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 7f691a2787..1b556ac1c3 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/core +## 0.7.6 + +### Patch Changes + +- 94da20976: Sort the table filter options by name. +- d8cc7e67a: Exposing Material UI extension point for tabs to be able to add additional information to them +- 99fbef232: Adding Headings for Accessibility on the Scaffolder Plugin +- ab07d77f6: Add support for discovering plugins through the app element tree, removing the need to register them explicitly. +- 937ed39ce: Exported SignInProviderConfig to strongly type SignInPage providers +- 9a9e7a42f: Adding close button on support menu +- 50ce875a0: Fixed a potentially confusing error being thrown about misuse of routable extensions where the error was actually something different. +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [50ce875a0] + - @backstage/core-api@0.2.17 + - @backstage/theme@0.2.6 + ## 0.7.5 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 7b1898a19d..344ea10398 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core", "description": "Core API used by Backstage plugins and apps", - "version": "0.7.5", + "version": "0.7.6", "private": false, "publishConfig": { "access": "public", @@ -30,9 +30,9 @@ }, "dependencies": { "@backstage/config": "^0.1.4", - "@backstage/core-api": "^0.2.16", + "@backstage/core-api": "^0.2.17", "@backstage/errors": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -69,7 +69,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 5975b78e06..bd35768e68 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,57 @@ # @backstage/create-app +## 1.0.0 + +### Patch Changes + +- ee22773e9: Removed `plugins.ts` from the app, as plugins are now discovered through the react tree. + + To apply this change to an existing app, simply delete `packages/app/src/plugins.ts` along with the import and usage in `packages/app/src/App.tsx`. + + Note that there are a few plugins that require explicit registration, in which case you would need to keep them in `plugins.ts`. The set of plugins that need explicit registration is any plugin that doesn't have a component extension that gets rendered as part of the app element tree. An example of such a plugin in the main Backstage repo is `@backstage/plugin-badges`. In the case of the badges plugin this is because there is not yet a component-based API for adding context menu items to the entity layout. + + If you have plugins that still rely on route registration through the `register` method of `createPlugin`, these need to be kept in `plugins.ts` as well. However, it is recommended to migrate these to export an extensions component instead. + +- 670acd88e: Fix system diagram card to be on the system page + + To apply the same fix to an existing application, in `EntityPage.tsx` simply move the `<EntityLayout.route>` for the `/diagram` path from the `groupPage` down into the `systemPage` element. + +- Updated dependencies [94da20976] +- Updated dependencies [84c54474d] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [4e5c94249] +- Updated dependencies [99fbef232] +- Updated dependencies [cb0206b2b] +- Updated dependencies [1373f4f12] +- Updated dependencies [29a7e4be8] +- Updated dependencies [ab07d77f6] +- Updated dependencies [49574a8a3] +- Updated dependencies [d367f63b5] +- Updated dependencies [96728a2af] +- Updated dependencies [5fe62f124] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [87c4f59de] +- Updated dependencies [09b5fcf2e] +- Updated dependencies [b42531cfe] +- Updated dependencies [c2306f898] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] +- Updated dependencies [ac6025f63] +- Updated dependencies [e292e393f] +- Updated dependencies [479b29124] + - @backstage/core@0.7.6 + - @backstage/plugin-scaffolder-backend@0.10.0 + - @backstage/cli@0.6.9 + - @backstage/plugin-scaffolder@0.9.1 + - @backstage/plugin-catalog-import@0.5.3 + - @backstage/plugin-rollbar-backend@0.1.9 + - @backstage/backend-common@0.6.3 + - @backstage/plugin-catalog@0.5.5 + - @backstage/plugin-catalog-backend@0.8.0 + - @backstage/theme@0.2.6 + - @backstage/plugin-techdocs@0.8.0 + ## 0.3.18 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index ea3d3548b8..2b30eafa2b 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "Create app package for Backstage", - "version": "0.3.18", + "version": "1.0.0", "private": false, "publishConfig": { "access": "public" diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index 9ce3c75802..22964d6b25 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/theme +## 0.2.6 + +### Patch Changes + +- 931b21a12: Replace the link color in dark theme + ## 0.2.5 ### Patch Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index b10e01ca1b..87821b6751 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.2.5", + "version": "0.2.6", "private": false, "publishConfig": { "access": "public", @@ -31,7 +31,7 @@ "@material-ui/core": "^4.11.0" }, "devDependencies": { - "@backstage/cli": "^0.6.6" + "@backstage/cli": "^0.6.9" }, "files": [ "dist" diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 13f27c321b..51df09ba80 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -31,9 +31,9 @@ "dependencies": { "@asyncapi/react-component": "^0.22.3", "@backstage/catalog-model": "^0.7.7", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-icons/font": "^1.0.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -49,7 +49,7 @@ "swagger-ui-react": "^3.37.2" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 0d59e271b0..9f0c49af7e 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -21,10 +21,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.6", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.3", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -34,7 +34,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 16a02ae42a..83911cdfc4 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -21,9 +21,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.2", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.2", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -37,7 +37,7 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 94e9960e35..28efc1c5d3 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,55 @@ # @backstage/plugin-catalog-backend +## 0.8.0 + +### Minor Changes + +- 5fe62f124: Fix the schema / code mismatch in LDAP `set` config + +### Patch Changes + +- 09b5fcf2e: GithubDiscoveryProcessor now excludes archived repositories so they won't be added to Backstage. +- c2306f898: Externalize repository processing for BitbucketDiscoveryProcessor. + + Add an extension point where you can customize how a matched Bitbucket repository should + be processed. This can for example be used if you want to generate the catalog-info.yaml + automatically based on other files in a repository, while taking advantage of the + build-in repository crawling functionality. + + `BitbucketDiscoveryProcessor.fromConfig` now takes an optional parameter `options.parser` where + you can customize the logic for each repository found. The default parser has the same + behaviour as before, where it emits an optional location for the matched repository + and lets the other processors take care of further processing. + + ```typescript + const customRepositoryParser: BitbucketRepositoryParser = async function* customRepositoryParser({ + client, + repository, + }) { + // Custom logic for interpret the matching repository. + // See defaultRepositoryParser for an example + }; + + const processor = BitbucketDiscoveryProcessor.fromConfig(env.config, { + parser: customRepositoryParser, + logger: env.logger, + }); + ``` + +- Updated dependencies [94da20976] +- Updated dependencies [b9b2b4b76] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [d367f63b5] +- Updated dependencies [937ed39ce] +- Updated dependencies [b42531cfe] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/plugin-search-backend-node@0.1.3 + - @backstage/backend-common@0.6.3 + ## 0.7.1 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 5125e9703e..9afb537637 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.7.1", + "version": "0.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,13 +30,13 @@ }, "dependencies": { "@azure/msal-node": "^1.0.0-beta.3", - "@backstage/backend-common": "^0.6.1", + "@backstage/backend-common": "^0.6.3", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", - "@backstage/plugin-search-backend-node": "^0.1.2", + "@backstage/plugin-search-backend-node": "^0.1.3", "@backstage/search-common": "^0.1.1", "@octokit/graphql": "^4.5.8", "@types/express": "^4.17.6", @@ -65,7 +65,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/test-utils": "^0.1.9", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 5fd93562d6..8c189a5f9b 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-import +## 0.5.3 + +### Patch Changes + +- 29a7e4be8: allow import from HTTP repositories +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 + ## 0.5.2 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 6af4b02bd0..9ba32d830c 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.5.2", + "version": "0.5.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "dependencies": { "@backstage/catalog-model": "^0.7.6", "@backstage/catalog-client": "^0.3.9", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/integration": "^0.5.0", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -53,7 +53,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index eccfa953a4..35e000f130 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog +## 0.5.5 + +### Patch Changes + +- 96728a2af: SystemDiagramCard UI improvements +- 87c4f59de: Add low german greeting +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 + ## 0.5.4 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 8561ae3188..b6b306c260 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.5.4", + "version": "0.5.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ "dependencies": { "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -53,7 +53,7 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@microsoft/microsoft-graph-types": "^1.25.0", diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 5eb91d08bb..5c05c0ee6f 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.2", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -50,7 +50,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 75e877ccb6..6ad0b8bfa9 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -32,8 +32,8 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/plugin-catalog-react": "^0.1.2", - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md new file mode 100644 index 0000000000..cfc08db5c4 --- /dev/null +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -0,0 +1,10 @@ +# @backstage/plugin-code-coverage-backend + +## 0.1.2 + +### Patch Changes + +- 55b2fc0c0: Update tests to function in windows +- Updated dependencies [d367f63b5] +- Updated dependencies [b42531cfe] + - @backstage/backend-common@0.6.3 diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 1e7903b016..3fc238ce61 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-coverage-backend", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,7 +19,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.6.2", + "@backstage/backend-common": "^0.6.3", "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", @@ -36,7 +36,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.21.2", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md new file mode 100644 index 0000000000..4a55b7f0f5 --- /dev/null +++ b/plugins/code-coverage/CHANGELOG.md @@ -0,0 +1,17 @@ +# @backstage/plugin-code-coverage + +## 0.1.2 + +### Patch Changes + +- 55b2fc0c0: Update tests to function in windows +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 1d02da3dea..1adc94fff7 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-coverage", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "dependencies": { "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/styles": "^4.11.0", @@ -39,7 +39,7 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 2db05d549a..55f785a7a4 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -21,9 +21,9 @@ }, "dependencies": { "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -34,7 +34,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index bec5db9fe0..c68fdde509 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -31,8 +31,8 @@ }, "dependencies": { "@backstage/config": "^0.1.3", - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -55,7 +55,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 7765760906..7c2eb5c90d 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -31,10 +31,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/plugin-explore-react": "^0.0.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -45,7 +45,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 001b926c6d..fe916804d2 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-fossa +## 0.2.5 + +### Patch Changes + +- 40d1e11cf: Add a `FossaPage` that shows the license compliance status of all components in the catalog. + See the projects `Readme` on how to use it. +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 + ## 0.2.4 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 2f656c476a..23f9cfde74 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-fossa", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index fecf9bdf22..509576cf2b 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 3dba840b8b..6a95803d6f 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -34,9 +34,9 @@ "dependencies": { "@backstage/catalog-model": "^0.7.5", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/integration": "^0.5.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -50,7 +50,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 9369ef87f9..e7f849ef2e 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-github-deployments +## 0.1.3 + +### Patch Changes + +- 60d0a1a2e: Adds extraColumns field to GitHub Deployments card +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 + ## 0.1.2 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index c5571b6e1f..12a36c160e 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-deployments", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.6", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.3", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -34,7 +34,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index d3a0d0df66..ae614fe504 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -42,7 +42,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 4ebedffd74..4aa26587ad 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -43,7 +43,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index c736eb0b5b..edee4bc2ee 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.3", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 644c074b81..a7295469d6 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -21,9 +21,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -33,7 +33,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 379f0dd872..8bcac8a60b 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-kubernetes-backend +## 0.3.5 + +### Patch Changes + +- c42cd1daa: Kubernetes client TLS verification is now configurable and defaults to true +- Updated dependencies [d367f63b5] +- Updated dependencies [b42531cfe] + - @backstage/backend-common@0.6.3 + ## 0.3.4 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 79864b7b48..7a8b16bc8a 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.3.4", + "version": "0.3.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.6.1", + "@backstage/backend-common": "^0.6.3", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", "@google-cloud/container": "^2.2.0", @@ -52,7 +52,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@types/aws4": "^1.5.1", "supertest": "^6.1.3" }, diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index df00c0801f..03013e1480 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -33,10 +33,10 @@ "dependencies": { "@backstage/catalog-model": "^0.7.4", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/plugin-kubernetes-backend": "^0.3.2", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@kubernetes/client-node": "^0.14.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index eb7d69d77d..45980df00c 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -33,9 +33,9 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.2", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 82952c7452..0951d972c2 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/org/package.json b/plugins/org/package.json index 0a9917cb7d..5bed02e9c8 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -21,10 +21,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.6", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/core-api": "^0.2.16", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -35,7 +35,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 44e8cb5b7f..c0e3afec34 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -31,9 +31,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index a8cfcc894a..2870ef79f1 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -31,9 +31,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -45,7 +45,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index a64fa25a81..8e20e93555 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-rollbar-backend +## 0.1.9 + +### Patch Changes + +- 49574a8a3: Fix some `spleling`. + + The `scaffolder-backend` has a configuration schema change that may be breaking + in rare circumstances. Due to a typo in the schema, the + `scaffolder.github.visibility`, `scaffolder.gitlab.visibility`, and + `scaffolder.bitbucket.visibility` did not get proper validation that the value + is one of the supported strings (`public`, `internal` (not available for + Bitbucket), and `private`). If you had a value that was not one of these three, + you may have to adjust your config. + +- Updated dependencies [d367f63b5] +- Updated dependencies [b42531cfe] + - @backstage/backend-common@0.6.3 + ## 0.1.8 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 489c12139d..05b02b2c39 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar-backend", - "version": "0.1.8", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.6.0", + "@backstage/backend-common": "^0.6.3", "@backstage/config": "^0.1.4", "@types/express": "^4.17.6", "axios": "^0.21.1", @@ -47,7 +47,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.5", + "@backstage/cli": "^0.6.9", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 6d0e49b1ae..6d654866af 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 2c45bdc611..cb1855e041 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-scaffolder-backend +## 0.10.0 + +### Minor Changes + +- 49574a8a3: Fix some `spleling`. + + The `scaffolder-backend` has a configuration schema change that may be breaking + in rare circumstances. Due to a typo in the schema, the + `scaffolder.github.visibility`, `scaffolder.gitlab.visibility`, and + `scaffolder.bitbucket.visibility` did not get proper validation that the value + is one of the supported strings (`public`, `internal` (not available for + Bitbucket), and `private`). If you had a value that was not one of these three, + you may have to adjust your config. + +### Patch Changes + +- 84c54474d: Forward user token to scaffolder task for subsequent api requests +- Updated dependencies [d367f63b5] +- Updated dependencies [b42531cfe] + - @backstage/backend-common@0.6.3 + ## 0.9.6 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 2c65d91604..729ef58d99 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.9.6", + "version": "0.10.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.6.2", + "@backstage/backend-common": "^0.6.3", "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", @@ -67,7 +67,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/test-utils": "^0.1.10", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index b7a8cbb89c..fee76f8775 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-scaffolder +## 0.9.1 + +### Patch Changes + +- 99fbef232: Adding Headings for Accessibility on the Scaffolder Plugin +- cb0206b2b: Respect top-level UI schema keys in scaffolder forms. Allows more advanced RJSF features such as explicit field ordering. +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 + ## 0.9.0 ### Minor Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 10785a4db7..4d4563df2f 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.9.0", + "version": "0.9.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -60,7 +60,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 8718488b21..e7a9d9aa0a 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-search-backend-node +## 0.1.3 + +### Patch Changes + +- b9b2b4b76: Lunr Search Engine support + ## 0.1.2 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 2d1803f4c4..b5d13af01c 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-node", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,8 +25,8 @@ "@types/lunr": "^2.3.3" }, "devDependencies": { - "@backstage/backend-common": "^0.6.0", - "@backstage/cli": "^0.6.6" + "@backstage/backend-common": "^0.6.3", + "@backstage/cli": "^0.6.9" }, "files": [ "dist" diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index b6a8d9fd18..9313e2e83a 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-search-backend +## 0.1.3 + +### Patch Changes + +- b9b2b4b76: Lunr Search Engine support +- Updated dependencies [b9b2b4b76] +- Updated dependencies [d367f63b5] +- Updated dependencies [b42531cfe] + - @backstage/plugin-search-backend-node@0.1.3 + - @backstage/backend-common@0.6.3 + ## 0.1.2 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 82b72e9506..a94fed35b9 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,9 +19,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.6.0", + "@backstage/backend-common": "^0.6.3", "@backstage/search-common": "^0.1.1", - "@backstage/plugin-search-backend-node": "^0.1.2", + "@backstage/plugin-search-backend-node": "^0.1.3", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -29,7 +29,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.9", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search/package.json b/plugins/search/package.json index 13019c7f32..c7ab201efe 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -29,11 +29,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/catalog-model": "^0.7.3", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/search-common": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -44,7 +44,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index dee05a8c2d..9908af2e24 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -46,7 +46,7 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index d48f59febe..97243bb930 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -34,8 +34,8 @@ "dependencies": { "@backstage/catalog-model": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.3", - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 990d0acb27..ecaf21f8eb 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -31,9 +31,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.4", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -45,7 +45,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index e927ed938a..5a1c2e2095 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -30,8 +30,8 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -43,7 +43,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 3924a56df3..4f89cd9844 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-techdocs +## 0.8.0 + +### Minor Changes + +- ac6025f63: Add feedback link icon in Techdocs Reader that directs to GitLab or GitHub repo issue page with pre-filled title and source link. + For link to appear, requires `repo_url` and `edit_uri` to be filled in mkdocs.yml, as per https://www.mkdocs.org/user-guide/configuration. An `edit_uri` will need to be specified for self-hosted GitLab/GitHub instances with a different host name. + To identify issue URL format as GitHub or GitLab, the host name of source in `repo_url` is checked if it contains `gitlab` or `github`. Alternately this is determined by matching to `host` values from `integrations` in app-config.yaml. + +### Patch Changes + +- e292e393f: Add a test id to the shadow root element of the Reader to access it easily in e2e tests +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 + ## 0.7.2 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 88b3b6a1df..025a419f59 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "0.7.2", + "version": "0.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ "dependencies": { "@backstage/config": "^0.1.4", "@backstage/catalog-model": "^0.7.7", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/test-utils": "^0.1.9", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@backstage/errors": "^0.1.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -49,7 +49,7 @@ "sanitize-html": "^2.3.2" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 5a80f068cc..7339e568c3 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -27,10 +27,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.5", + "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.1", - "@backstage/theme": "^0.2.5", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -39,7 +39,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 6055f31b8a..d410dc103e 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/welcome/CHANGELOG.md b/plugins/welcome/CHANGELOG.md index 68b8c358c2..cf907b5b4f 100644 --- a/plugins/welcome/CHANGELOG.md +++ b/plugins/welcome/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-welcome +## 0.2.7 + +### Patch Changes + +- f85851837: Australian Greeting +- Updated dependencies [94da20976] +- Updated dependencies [d8cc7e67a] +- Updated dependencies [99fbef232] +- Updated dependencies [ab07d77f6] +- Updated dependencies [931b21a12] +- Updated dependencies [937ed39ce] +- Updated dependencies [9a9e7a42f] +- Updated dependencies [50ce875a0] + - @backstage/core@0.7.6 + - @backstage/theme@0.2.6 + ## 0.2.6 ### Patch Changes diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json index aa7a746016..b276b86835 100644 --- a/plugins/welcome/package.json +++ b/plugins/welcome/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-welcome", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -30,8 +30,8 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.7.5", - "@backstage/theme": "^0.2.5", + "@backstage/core": "^0.7.6", + "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.8", + "@backstage/cli": "^0.6.9", "@backstage/dev-utils": "^0.1.13", "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", From f218637d0859edd6d1bbce4f8050b5c73c430723 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Thu, 22 Apr 2021 13:43:17 +0200 Subject: [PATCH 086/262] create-app: release version 0.3.19 Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- packages/create-app/CHANGELOG.md | 2 +- packages/create-app/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index bd35768e68..c821a3ab81 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,6 +1,6 @@ # @backstage/create-app -## 1.0.0 +## 0.3.19 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 2b30eafa2b..5cf6cdd78e 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "Create app package for Backstage", - "version": "1.0.0", + "version": "0.3.19", "private": false, "publishConfig": { "access": "public" From 6fbd7beca5bd67cc7721c942e7180aecb60ba273 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 15:50:24 +0200 Subject: [PATCH 087/262] Rename changeset Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- ...lovely-wombats-relate.md => techdocs-lovely-wombats-relate.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{lovely-wombats-relate.md => techdocs-lovely-wombats-relate.md} (100%) diff --git a/.changeset/lovely-wombats-relate.md b/.changeset/techdocs-lovely-wombats-relate.md similarity index 100% rename from .changeset/lovely-wombats-relate.md rename to .changeset/techdocs-lovely-wombats-relate.md From dcd54c7cd12ec1c48ce44e8a2f7c9e4c0d300d07 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 16:07:13 +0200 Subject: [PATCH 088/262] Use `RouteRef` to generate path to search page Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/sixty-dragons-retire.md | 5 +++++ .../src/components/SidebarSearch/SidebarSearch.tsx | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .changeset/sixty-dragons-retire.md diff --git a/.changeset/sixty-dragons-retire.md b/.changeset/sixty-dragons-retire.md new file mode 100644 index 0000000000..62965c6e88 --- /dev/null +++ b/.changeset/sixty-dragons-retire.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Use `RouteRef` to generate path to search page. diff --git a/plugins/search/src/components/SidebarSearch/SidebarSearch.tsx b/plugins/search/src/components/SidebarSearch/SidebarSearch.tsx index 7e72e83b02..b422c33e02 100644 --- a/plugins/search/src/components/SidebarSearch/SidebarSearch.tsx +++ b/plugins/search/src/components/SidebarSearch/SidebarSearch.tsx @@ -13,22 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useCallback } from 'react'; +import { SidebarSearchField, useRouteRef } from '@backstage/core'; import qs from 'qs'; +import React, { useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; -import { SidebarSearchField } from '@backstage/core'; +import { rootRouteRef } from '../../plugin'; export const SidebarSearch = () => { + const searchRoute = useRouteRef(rootRouteRef); const navigate = useNavigate(); const handleSearch = useCallback( (query: string): void => { const queryString = qs.stringify({ query }, { addQueryPrefix: true }); - // TODO: Here the url to the search plugin is hardcoded. We need a way to query the route in the future. - // Maybe an API that I can just call from other places? - navigate(`/search${queryString}`); + navigate(`${searchRoute()}${queryString}`); }, - [navigate], + [navigate, searchRoute], ); return <SidebarSearchField onSearch={handleSearch} to="/search" />; From 546172674279917bfa49ce621207925e760a6da5 Mon Sep 17 00:00:00 2001 From: jrusso1020 <jrusso@brex.com> Date: Thu, 22 Apr 2021 09:08:46 -0600 Subject: [PATCH 089/262] [Fixes 5420] Update component example in documentation Currently the entity component example towards the top of the page has metadata.labels.system set https://github.com/backstage/backstage/blame/master/docs/features/software-catalog/descriptor-format.md#L47 but further down on the page it's spec.system https://github.com/backstage/backstage/blame/master/docs/features/software-catalog/descriptor-format.md#L423. This updates them to both use the correct spec.system key/value, as well as add an example label to get a sense for what labels look like as well Signed-off-by: jrusso1020 <jrusso@brex.com> --- docs/features/software-catalog/descriptor-format.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index d3b14dd888..2506e2e9c1 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -44,7 +44,7 @@ metadata: name: artist-web description: The place to be, for great artists labels: - system: public-websites + backstage.io/custom: ValueStuff annotations: example.com/service-discovery: artistweb circleci.com/project-slug: github/example-org/artist-website @@ -58,6 +58,7 @@ spec: type: website lifecycle: production owner: artist-relations-team + system: public-websites ``` This is the same entity as returned in JSON from the software catalog API: @@ -76,7 +77,7 @@ This is the same entity as returned in JSON from the software catalog API: "etag": "ZjU2MWRkZWUtMmMxZS00YTZiLWFmMWMtOTE1NGNiZDdlYzNk", "generation": 1, "labels": { - "system": "public-websites" + "backstage.io/custom": "ValueStuff" }, "links": [{ "url": "https://admin.example-org.com", @@ -90,7 +91,8 @@ This is the same entity as returned in JSON from the software catalog API: "spec": { "lifecycle": "production", "owner": "artist-relations-team", - "type": "website" + "type": "website", + "system": "public-websites" } } ``` From 8bd92cff3f0c9c5d794252bb51dda4859829d8bf Mon Sep 17 00:00:00 2001 From: Brian Fox <brianhfox@gmail.com> Date: Thu, 22 Apr 2021 17:30:08 +0200 Subject: [PATCH 090/262] Update nginx deployment to use 1.19 features - There is no need to override the `CMD` on the base image to get the custom scripts to run. This can be done simply by adding the custom configuration script to the `/docker-entrypoint.d` folder. See https://github.com/nginxinc/docker-nginx/blob/master/mainline/debian/docker-entrypoint.sh. - With the above change made, we can now also reap the benefit of support for `envsubst` having been added in 1.19 - as long as the config is placed in the folder `/etc/nginx/templates/`. See https://github.com/docker-library/docs/tree/master/nginx#using-environment-variables-in-nginx-configuration-new-in-119 and https://github.com/nginxinc/docker-nginx/blob/master/mainline/debian/20-envsubst-on-templates.sh for more info. Signed-off-by: Brian Fox <brianhfox@gmail.com> --- contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild | 5 ++--- contrib/docker/frontend-with-nginx/Dockerfile.hostbuild | 6 +++--- .../docker/{run.sh => inject-config.sh} | 8 -------- 3 files changed, 5 insertions(+), 14 deletions(-) rename contrib/docker/frontend-with-nginx/docker/{run.sh => inject-config.sh} (80%) diff --git a/contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild b/contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild index dda9779eb0..41f931544f 100644 --- a/contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild +++ b/contrib/docker/frontend-with-nginx/Dockerfile.dockerbuild @@ -51,9 +51,8 @@ FROM nginx:mainline RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/* COPY --from=build /app/packages/app/dist /usr/share/nginx/html -COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template -COPY docker/run.sh /usr/local/bin/run.sh +COPY docker/default.conf.template /etc/nginx/templates/default.conf.template -CMD run.sh +COPY docker/inject-config.sh /docker-entrypoint.d/40-inject-config.sh ENV PORT 80 diff --git a/contrib/docker/frontend-with-nginx/Dockerfile.hostbuild b/contrib/docker/frontend-with-nginx/Dockerfile.hostbuild index 6e5912dd67..1e0134017f 100644 --- a/contrib/docker/frontend-with-nginx/Dockerfile.hostbuild +++ b/contrib/docker/frontend-with-nginx/Dockerfile.hostbuild @@ -33,9 +33,9 @@ FROM nginx:mainline RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/* COPY packages/app/dist /usr/share/nginx/html -COPY docker/default.conf.template /etc/nginx/conf.d/default.conf.template -COPY docker/run.sh /usr/local/bin/run.sh +COPY docker/default.conf.template /etc/nginx/templates/default.conf.template -CMD run.sh +COPY docker/inject-config.sh /docker-entrypoint.d/40-inject-config.sh ENV PORT 80 + diff --git a/contrib/docker/frontend-with-nginx/docker/run.sh b/contrib/docker/frontend-with-nginx/docker/inject-config.sh similarity index 80% rename from contrib/docker/frontend-with-nginx/docker/run.sh rename to contrib/docker/frontend-with-nginx/docker/inject-config.sh index fdb1742a07..a0cea96ff3 100755 --- a/contrib/docker/frontend-with-nginx/docker/run.sh +++ b/contrib/docker/frontend-with-nginx/docker/inject-config.sh @@ -2,13 +2,6 @@ set -Eeuo pipefail -# Run nginx as root -sed -i 's/user nginx.*$//' /etc/nginx/nginx.conf - -# Write selected env vars to nginx config -envsubst '$PORT' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf - -# Inject runtime config into the client function inject_config() { # Read runtime config from env in the same way as the @backstage/config-loader package local config @@ -41,4 +34,3 @@ function inject_config() { inject_config -exec nginx -g 'daemon off;' From c6a5acfc2a84ed0ef3269cc4958276604286caf7 Mon Sep 17 00:00:00 2001 From: Brian Fox <brianhfox@gmail.com> Date: Thu, 22 Apr 2021 17:46:21 +0200 Subject: [PATCH 091/262] Fix typo - Service should be only be enabled when backend is enabled Signed-off-by: Brian Fox <brianhfox@gmail.com> --- .../backstage/templates/service.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/templates/service.yaml b/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/templates/service.yaml index 77a113ae5c..e74bfe0b8d 100644 --- a/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/templates/service.yaml +++ b/contrib/kubernetes/basic_kubernetes_example_with_helm/backstage/templates/service.yaml @@ -16,7 +16,7 @@ spec: app.kubernetes.io/name: {{ include "backstage.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} -{{- if .Values.app.enabled }} +{{- if .Values.backend.enabled }} --- apiVersion: v1 kind: Service From 610619dba09e0c82be7abde8c16ae54456cc77d2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Thu, 15 Apr 2021 19:45:40 +0200 Subject: [PATCH 092/262] docs: update install step in plugin architecture docs Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- docs/overview/architecture-overview.md | 48 +++++++++++++++----------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index f2f2bc72c8..fab5698014 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -67,33 +67,41 @@ is available at ### Installing plugins -Plugins are typically loaded by the UI in your Backstage applications -`plugins.ts` file. For example, -[here](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts) -is that file in the Backstage sample app. +Plugins are typically installed as React components in your Backstage +application. For example, +[here](https://github.com/backstage/backstage/blob/master/packages/app/src/App.tsx) +is a file that imports many full-page plugins in the Backstage sample app. -Plugins can be enabled, and passed configuration in `apis.ts`. For example, -[here](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts) -is that file in the Backstage sample app. - -This is how the Lighthouse plugin would be enabled in a typical Backstage -application: +An example of one of these plugin components is the `CatalogIndexPage`, which is +a full-page view that allows you to browse entities in the Backstage catalog. It +is installed in the app by importing it and adding it as an element like this: ```tsx -import { ApiHolder, ApiRegistry } from '@backstage/core'; -import { - lighthouseApiRef, - LighthouseRestApi, -} from '@backstage/plugin-lighthouse'; +import { CatalogIndexPage } from '@backstage/plugin-catalog'; -const builder = ApiRegistry.builder(); +... -export const lighthouseApi = new LighthouseRestApi(/* URL of the lighthouse microservice! */); -builder.add(lighthouseApiRef, lighthouseApi); - -export default builder.build() as ApiHolder; +const routes = ( + <FlatRoutes> + ... + <Route path="/catalog" element={<CatalogIndexPage />} /> + ... + </FlatRoutes> +); ``` +Note that we use `"/catalog"` as our path to this plugin page, but we can choose +any route we want for the page, as long as it doesn't collide with the routes +that we choose for the other plugins in the app. + +These components that are exported from plugins are referred to as "Plugin +Extension Components", or "Extensions Components". They are regular React +components, but in addition to being able to be rendered by React, they also +contain various pieces of metadata that is used to write together the entire +app. Extensions components are created using `create*Extension` methods, which +you can read more about in the +[composability documentation](../plugins/composability.md). + As of this moment, there is no config based install procedure for plugins. Some code changes are required. From c614ede9a5b56232d2b8cb655bcc9a903d4ac9a7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Thu, 15 Apr 2021 20:12:33 +0200 Subject: [PATCH 093/262] docs: update plugin installation docs Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/gentle-days-return.md | 21 ++++++ docs/features/kubernetes/installation.md | 12 +--- .../features/software-catalog/installation.md | 10 +-- .../software-templates/installation.md | 10 +-- docs/features/techdocs/getting-started.md | 10 +-- .../configure-app-with-plugins.md | 9 +-- docs/plugins/structure-of-a-plugin.md | 3 +- plugins/api-docs/README.md | 14 +--- plugins/bitrise/README.md | 6 -- plugins/catalog-import/README.md | 10 +-- plugins/circleci/README.md | 30 ++++----- plugins/cost-insights/README.md | 14 ++-- plugins/explore/README.md | 10 +-- plugins/fossa/README.md | 16 ++--- plugins/github-actions/README.md | 24 +++++-- plugins/github-deployments/README.md | 12 +--- plugins/graphiql/README.md | 13 ++-- plugins/jenkins/README.md | 19 ++++-- plugins/lighthouse/README.md | 19 ++---- .../lighthouse/src/components/Intro/index.tsx | 11 +-- plugins/pagerduty/README.md | 6 -- plugins/register-component/README.md | 67 +++---------------- plugins/rollbar/README.md | 32 ++++----- plugins/sentry/README.md | 40 +++++------ plugins/sonarqube/README.md | 17 ++--- 25 files changed, 152 insertions(+), 283 deletions(-) create mode 100644 .changeset/gentle-days-return.md diff --git a/.changeset/gentle-days-return.md b/.changeset/gentle-days-return.md new file mode 100644 index 0000000000..96552173bd --- /dev/null +++ b/.changeset/gentle-days-return.md @@ -0,0 +1,21 @@ +--- +'@backstage/plugin-api-docs': patch +'@backstage/plugin-bitrise': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-circleci': patch +'@backstage/plugin-cost-insights': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-fossa': patch +'@backstage/plugin-github-actions': patch +'@backstage/plugin-github-deployments': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-jenkins': patch +'@backstage/plugin-lighthouse': patch +'@backstage/plugin-pagerduty': patch +'@backstage/plugin-register-component': patch +'@backstage/plugin-rollbar': patch +'@backstage/plugin-sentry': patch +'@backstage/plugin-sonarqube': patch +--- + +Updated README to have up-to-date install instructions. diff --git a/docs/features/kubernetes/installation.md b/docs/features/kubernetes/installation.md index fed24c58d6..10968b427c 100644 --- a/docs/features/kubernetes/installation.md +++ b/docs/features/kubernetes/installation.md @@ -23,16 +23,8 @@ cd packages/app yarn add @backstage/plugin-kubernetes ``` -Once the package has been installed, you need to import the plugin in your app. -Add the following to `packages/app/src/plugins.ts`: - -`plugins.ts`: - -```typescript -export { plugin as Kubernetes } from '@backstage/plugin-kubernetes'; -``` - -Now, add the "Kubernetes" tab to the catalog entity page. In +Once the package has been installed, you need to import the plugin in your app +by adding the "Kubernetes" tab to the catalog entity page. In `packages/app/src/components/catalog/EntityPage.tsx`, you'll add a router to get to the tab, and add the tab itself. diff --git a/docs/features/software-catalog/installation.md b/docs/features/software-catalog/installation.md index ff8dfbda68..df473f886f 100644 --- a/docs/features/software-catalog/installation.md +++ b/docs/features/software-catalog/installation.md @@ -24,14 +24,8 @@ yarn add @backstage/plugin-catalog ### Adding the Plugin to your `packages/app` -Add the following entry to the head of your `packages/app/src/plugins.ts`: - -```ts -export { catalogPlugin } from '@backstage/plugin-catalog'; -``` - -Next we need to install the two pages that the catalog plugin provides. You can -choose any name for these routes, but we recommend the following: +Add the two pages that the catalog plugin provides to your app. You can choose +any name for these routes, but we recommend the following: ```tsx // packages/app/src/App.tsx diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index 105b7e5f96..0abaab0aed 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -26,14 +26,8 @@ yarn add @backstage/plugin-scaffolder ### Adding the Plugin to your `packages/app` -Add the following entry to the head of your `packages/app/src/plugins.ts`: - -```ts -export { scaffolderPlugin } from '@backstage/plugin-scaffolder'; -``` - -Next we need to install the root page that the Scaffolder plugin provides. You -can choose any path for the route, but we recommend the following: +Add the root page that the Scaffolder plugin provides to your app. You can +choose any path for the route, but we recommend the following: ```tsx import { ScaffolderPage } from '@backstage/plugin-scaffolder'; diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index a96e881849..934e91bd26 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -29,14 +29,8 @@ yarn add @backstage/plugin-techdocs Once the package has been installed, you need to import the plugin in your app. -Add the following to `packages/app/src/plugins.ts`: - -```typescript -export { plugin as TechDocs } from '@backstage/plugin-techdocs'; -``` - -Now we can add a route for the TechDocs page. In `packages/app/src/App.tsx`, -import TechDocsPage and add the following to `FlatRoutes`: +In `packages/app/src/App.tsx`, import TechDocsPage and add the following to +`FlatRoutes`: ```tsx import { TechDocsPage } from '@backstage/plugin-techdocs'; diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index b2f3a37d90..746b4bd940 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -27,14 +27,7 @@ package.json. Backstage Apps are set up as monorepos with [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/). Since CircleCI is a frontend UI plugin, it goes in `app` rather than `backend`. -2. Add the plugin itself to the App: - -```js -// packages/app/src/plugins.ts -export { plugin as CircleCi } from '@backstage/plugin-circleci'; -``` - -3. Register the plugin in the entity pages: +2. Add the `EntityCircleCIContent` extension to the entity pages in the app: ```diff // packages/app/src/components/catalog/EntityPage.tsx diff --git a/docs/plugins/structure-of-a-plugin.md b/docs/plugins/structure-of-a-plugin.md index 2aacd02cf2..f81e3794e5 100644 --- a/docs/plugins/structure-of-a-plugin.md +++ b/docs/plugins/structure-of-a-plugin.md @@ -100,8 +100,7 @@ There are three things needed for a Backstage app to start making use of a plugin. 1. Add plugin as dependency in `app/package.json` -2. `import` plugin in `app/src/plugins.ts` -3. Import and use one or more plugin extensions, for example in +2. Import and use one or more plugin extensions, for example in `app/src/App.tsx`. Luckily these three steps happen automatically when you create a plugin with the diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index 4e71e87275..3d44eaaa29 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -33,17 +33,7 @@ To link that a component provides or consumes an API, see the [`providesApis`](h yarn add @backstage/plugin-api-docs ``` -2. Add the plugin to the app: - -```ts -// packages/app/src/plugins.ts - -export { apiDocsPlugin } from '@backstage/plugin-api-docs'; -``` - -<Route path="/api-docs" element={<ApiExplorerPage />} /> - -3. Register the `ApiExplorerPage` at the `/api-docs` path: +2. Add the `ApiExplorerPage` extensions to the app: ```tsx // packages/app/src/App.tsx @@ -53,7 +43,7 @@ import { ApiExplorerPage } from '@backstage/plugin-api-docs'; <Route path="/api-docs" element={<ApiExplorerPage />} />; ``` -4. Add one of the provided widgets to the EntityPage: +3. Add one of the provided widgets to the EntityPage: ```tsx // packages/app/src/components/catalog/EntityPage.tsx diff --git a/plugins/bitrise/README.md b/plugins/bitrise/README.md index 59d85b0a98..ae3917d78a 100644 --- a/plugins/bitrise/README.md +++ b/plugins/bitrise/README.md @@ -11,12 +11,6 @@ Welcome to the Bitrise plugin! $ yarn add @backstage/plugin-bitrise ``` -Then make sure to export the plugin in your app's [`plugins.ts`](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts) to enable the plugin: - -```js -export { bitrisePlugin } from '@backstage/plugin-bitrise'; -``` - Bitrise Plugin exposes an "Entity Tab Content" component `EntityBitriseContent`. You can include it in the [`EntityPage.tsx`](https://github.com/backstage/backstage/blob/master/packages/app/src/components/catalog/EntityPage.tsx)`: ```tsx diff --git a/plugins/catalog-import/README.md b/plugins/catalog-import/README.md index 97371ce0e7..90190e4356 100644 --- a/plugins/catalog-import/README.md +++ b/plugins/catalog-import/README.md @@ -23,15 +23,7 @@ Some features are not yet available for all supported Git providers. yarn add @backstage/plugin-catalog-import ``` -2. Add the plugin to the app: - -```ts -// packages/app/src/plugins.ts - -export { catalogImportPlugin } from '@backstage/plugin-catalog-import'; -``` - -3. Register the `CatalogImportPage` at the `/catalog-import` path: +2. Add the `CatalogImportPage` extensions to the app: ```tsx // packages/app/src/App.tsx diff --git a/plugins/circleci/README.md b/plugins/circleci/README.md index d30e950aa9..868ae6e26a 100644 --- a/plugins/circleci/README.md +++ b/plugins/circleci/README.md @@ -13,26 +13,22 @@ Website: [https://circleci.com/](https://circleci.com/) yarn add @backstage/plugin-circleci ``` -2. Add plugin itself: +2. Add the `EntityCircleCIContent` extension to the entity page in the app: -```js -// packages/app/src/plugins.ts -export { plugin as Circleci } from '@backstage/plugin-circleci'; -``` - -3. Register the plugin router: - -```jsx +```tsx // packages/app/src/components/catalog/EntityPage.tsx +import { EntityCircleCIContent } from '@backstage/plugin-circleci'; -import { Router as CircleCIRouter } from '@backstage/plugin-circleci'; - -// Then somewhere inside <EntityPageLayout> -<EntityPageLayout.Content - path="/ci-cd/*" - title="CI/CD" - element={<CircleCIRouter />} -/>; +// ... +const serviceEntityPage = ( + <EntityPageLayout> + ... + <EntityLayout.Route path="/circle-ci" title="Circle CI"> + <EntityCircleCIContent /> + </EntityLayout.Route> + ... + </EntityPageLayout> +); ``` 4. Add proxy config: diff --git a/plugins/cost-insights/README.md b/plugins/cost-insights/README.md index bbd047be14..f737c022f3 100644 --- a/plugins/cost-insights/README.md +++ b/plugins/cost-insights/README.md @@ -51,11 +51,17 @@ export const apis = [ ]; ``` -4. Add cost-insights to your Backstage plugins. +4. Add the `CostInsightsPage` extension to your `App.tsx`: -```ts -// packages/app/src/plugins.ts -export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; +```tsx +// packages/app/src/App.tsx +import { CostInsightsPage } from '@backstage/plugin-cost-insights'; + +<FlatRoutes> + ... + <Route path="/cost-insights" element={<CostInsightsPage />} /> + ... +</FlatRoutes>; ``` 5. Add Cost Insights to your app Sidebar. diff --git a/plugins/explore/README.md b/plugins/explore/README.md index b236af14dc..fea1333e34 100644 --- a/plugins/explore/README.md +++ b/plugins/explore/README.md @@ -5,13 +5,7 @@ This plugin helps to visualize the domains and tools in your ecosystem. ## Getting started -To install the plugin, include the following import your `plugins.ts`: - -```typescript -export { explorePlugin } from '@backstage/plugin-explore'; -``` - -Register and bind the route in `App.tsx`: +To install the plugin, add and bind the route in `App.tsx`: ```typescript import { ExplorePage, explorePlugin } from '@backstage/plugin-explore'; @@ -30,7 +24,7 @@ bindRoutes({ bind }) { <Route path="/explore" element={<ExplorePage />} /> ``` -Add a link to the sidebar in `Root.tsx`: +And add a link to the sidebar in `Root.tsx`: ```typescript import LayersIcon from '@material-ui/icons/Layers'; diff --git a/plugins/fossa/README.md b/plugins/fossa/README.md index 049a1c25cb..11f3e90e1c 100644 --- a/plugins/fossa/README.md +++ b/plugins/fossa/README.md @@ -14,15 +14,7 @@ The FOSSA Plugin displays code statistics from [FOSSA](https://fossa.com/). yarn add @backstage/plugin-fossa ``` -2. Add plugin to the app: - -```js -// packages/app/src/plugins.ts - -export { fossaPlugin } from '@backstage/plugin-fossa'; -``` - -3. Add the `EntityFossaCard` to the EntityPage: +2. Add the `EntityFossaCard` to the EntityPage: ```jsx // packages/app/src/components/catalog/EntityPage.tsx @@ -40,7 +32,7 @@ const OverviewContent = ({ entity }: { entity: Entity }) => ( ); ``` -4. Add the proxy config: +3. Add the proxy config: ```yaml # app-config.yaml @@ -57,9 +49,9 @@ fossa: organizationId: <your-fossa-organization-id> ``` -5. Get an api-token and provide `FOSSA_AUTH_HEADER` as env variable (https://app.fossa.com/account/settings/integrations/api_tokens) +4. Get an api-token and provide `FOSSA_AUTH_HEADER` as env variable (https://app.fossa.com/account/settings/integrations/api_tokens) -6. Add the `fossa.io/project-name` annotation to your catalog-info.yaml file: +5. Add the `fossa.io/project-name` annotation to your catalog-info.yaml file: ```yaml apiVersion: backstage.io/v1alpha1 diff --git a/plugins/github-actions/README.md b/plugins/github-actions/README.md index d47144351e..328ef6054d 100644 --- a/plugins/github-actions/README.md +++ b/plugins/github-actions/README.md @@ -35,17 +35,29 @@ TBD ### Standalone app requirements -If you didn't clone this repo you have to do some extra work. - -1. Add plugin API to your Backstage instance: +1. Install the plugin dependency in your Backstage app package: ```bash +cd packages/app yarn add @backstage/plugin-github-actions ``` -```js -// packages/app/src/plugins.ts -export { plugin as GithubActions } from '@backstage/plugin-github-actions'; +2. Add to the app `EntityPage` component: + +```tsx +// packages/app/src/components/catalog/EntityPage.tsx +import { EntityGithubActionsContent } from '@backstage/plugin-github-actions'; + +// ... +const serviceEntityPage = ( + <EntityPageLayout> + ... + <EntityLayout.Route path="/github-actions" title="GitHub Actions"> + <EntityGithubActionsContent /> + </EntityLayout.Route> + ... + </EntityPageLayout> +); ``` 2. Run the app with `yarn start` and the backend with `yarn --cwd packages/backend start`, navigate to `/github-actions/`. diff --git a/plugins/github-deployments/README.md b/plugins/github-deployments/README.md index 174d1bc8c7..1bb8846105 100644 --- a/plugins/github-deployments/README.md +++ b/plugins/github-deployments/README.md @@ -18,15 +18,7 @@ The GitHub Deployments Plugin displays recent deployments from GitHub. yarn add @backstage/plugin-github-deployments ``` -2. Add the plugin to the app - -```typescript -// packages/app/src/plugins.ts - -export { githubDeploymentsPlugin as GithubDeploymentsPlugin } from '@backstage/plugin-github-deployments'; -``` - -3. Add the `EntityGithubDeploymentsCard` to the EntityPage: +2. Add the `EntityGithubDeploymentsCard` to the EntityPage: ```typescript // packages/app/src/components/catalog/EntityPage.tsx @@ -44,7 +36,7 @@ const OverviewContent = () => ( ); ``` -4. Add the `github.com/project-slug` annotation to your `catalog-info.yaml` file: +3. Add the `github.com/project-slug` annotation to your `catalog-info.yaml` file: ```yaml apiVersion: backstage.io/v1alpha1 diff --git a/plugins/graphiql/README.md b/plugins/graphiql/README.md index c75d8b71e3..39372890d1 100644 --- a/plugins/graphiql/README.md +++ b/plugins/graphiql/README.md @@ -16,18 +16,13 @@ cd packages/app yarn add @backstage/plugin-graphiql ``` -```diff -# in packages/app/src/plugins.ts -+export { plugin as GraphiQL } from '@backstage/plugin-graphiql'; -``` - ```diff # in packages/app/src/App.tsx -+import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql'; ++import { GraphiQLPage } from '@backstage/plugin-graphiql'; - const AppRoutes = () => ( - <Routes> -+ <Route path="/graphiql" element={<GraphiQLRouter />} /> + const routes = ( + <FlatRoutes> ++ <Route path="/graphiql" element={<GraphiQLPage />} /> ``` ### Adding GraphQL endpoints diff --git a/plugins/jenkins/README.md b/plugins/jenkins/README.md index b3bc21b7d5..f406393190 100644 --- a/plugins/jenkins/README.md +++ b/plugins/jenkins/README.md @@ -14,11 +14,22 @@ Website: [https://jenkins.io/](https://jenkins.io/) yarn add @backstage/plugin-jenkins ``` -2. Add plugin: +2. Add the `EntityJenkinsContent` extension to the entity page in the app: -```js -// packages/app/src/plugins.ts -export { plugin as Jenkins } from '@backstage/plugin-jenkins'; +```tsx +// packages/app/src/components/catalog/EntityPage.tsx +import { EntityJenkinsContent } from '@backstage/plugin-circleci'; + +// ... +const serviceEntityPage = ( + <EntityPageLayout> + ... + <EntityLayout.Route path="/jenkins" title="Jenkins"> + <EntityJenkinsContent /> + </EntityLayout.Route> + ... + </EntityPageLayout> +); ``` 3. Add proxy configuration to `app-config.yaml` diff --git a/plugins/lighthouse/README.md b/plugins/lighthouse/README.md index 149172b7e8..028547ea3e 100644 --- a/plugins/lighthouse/README.md +++ b/plugins/lighthouse/README.md @@ -31,26 +31,17 @@ When you have an instance running that Backstage can hook into, first install th $ yarn add @backstage/plugin-lighthouse ``` -Then make sure to export the plugin in -your app's [`plugins.ts`](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts) -to enable the plugin: - -```js -export { plugin as LighthousePlugin } from '@backstage/plugin-lighthouse'; -``` - -Modify your app routes in `App.tsx` to include the Router component exported from the plugin, for example: +Modify your app routes in `App.tsx` to include the `LighthousePage` component exported from the plugin, for example: ```tsx // At the top imports -import { Router as LighthouseRouter } from '@backstage/plugin-lighthouse'; +import { LighthousePage } from '@backstage/plugin-lighthouse'; -// Inside App component -<Routes> +<FlatRoutes> // ... - <Route path="/lighthouse/*" element={<LighthouseRouter />} /> + <Route path="/lighthouse" element={<LighthousePage />} /> // ... -</Routes>; +</FlatRoutes>; ``` Then configure the `lighthouse-audit-service` URL in your [`app-config.yaml`](https://github.com/backstage/backstage/blob/master/app-config.yaml). diff --git a/plugins/lighthouse/src/components/Intro/index.tsx b/plugins/lighthouse/src/components/Intro/index.tsx index 25ffccabbd..a89518a5ed 100644 --- a/plugins/lighthouse/src/components/Intro/index.tsx +++ b/plugins/lighthouse/src/components/Intro/index.tsx @@ -49,19 +49,12 @@ When you have an instance running that Backstage can hook into, first install th $ yarn add @backstage/plugin-lighthouse \`\`\` -Then make sure to export the plugin in your app's [\`plugins.ts\`](https://github.com/backstage/backstage/blob/master/packages/app/src/plugins.ts) to enable the plugin: +Modify your app routes in \`App.tsx\` to include the \`LighthousePage\` component exported from the plugin, for example: -\`\`\`js -export { plugin as LighthousePlugin } from '@backstage/plugin-lighthouse'; -\`\`\` - -Modify your app routes in \`App.tsx\` or \`App.jsx\` to include the Router component exported from the plugin, for example: - -\`\`\`js +\`\`\`tsx // At the top imports import { LighthousePage } from '@backstage/plugin-lighthouse'; -// Inside App component <FlatRoutes> // ... <Route path="/lighthouse" element={<LighthousePage />} /> diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index 9d8023b9fe..36f380fdd5 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -22,12 +22,6 @@ Install the plugin: yarn add @backstage/plugin-pagerduty ``` -Add it to the app in `plugins.ts`: - -```ts -export { plugin as Pagerduty } from '@backstage/plugin-pagerduty'; -``` - Add it to the `EntityPage.tsx`: ```ts diff --git a/plugins/register-component/README.md b/plugins/register-component/README.md index 0abf27590f..9c5304385e 100644 --- a/plugins/register-component/README.md +++ b/plugins/register-component/README.md @@ -16,69 +16,24 @@ When installed it is accessible on [localhost:3000/register-component](localhost ## Standalone setup -0. Install plugin and its dependency `plugin-catalog` +1. Install plugin and its dependency `plugin-catalog` ```bash -yarn add @backstage/plugin-register-component -W -yarn add @backstage/plugin-catalog -W +cd packages/app +yarn add @backstage/plugin-register-component ``` -1. Add dependencies to the active plugins list +2. Add the `RegisterComponentPage` extension to your `App.tsx`: -```typescript -// packages/app/src/plugins.ts -export { plugin as RegisterComponent } from '@backstage/plugin-register-component'; -export { plugin as CatalogPlugin } from '@backstage/plugin-catalog'; -``` - -2. Create `packages/app/src/apis.ts` and register all the needed plugins - -```typescript -import { - alertApiRef, - AlertApiForwarder, - ApiRegistry, - ConfigApi, - errorApiRef, - ErrorApiForwarder, - ErrorAlerter, -} from '@backstage/core'; - -import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog'; - -export const apis = (config: ConfigApi) => { - const backendUrl = config.getString('backend.baseUrl'); - - const builder = ApiRegistry.builder(); - - const alertApi = builder.add(alertApiRef, new AlertApiForwarder()); - const errorApi = builder.add( - errorApiRef, - new ErrorAlerter(alertApi, new ErrorApiForwarder()), - ); - - builder.add( - catalogApiRef, - new CatalogClient({ - apiOrigin: backendUrl, - basePath: '/catalog', - }), - ); - - return builder.build(); -}; -``` - -3. Pass `apis` to createApp - -```typescript +```tsx // packages/app/src/App.tsx -import { apis } from './apis'; +import { RegisterComponentPage } from '@backstage/plugin-cost-insights'; -const app = createApp({ - apis, - plugins: Object.values(plugins), -}); +<FlatRoutes> + ... + <Route path="/register-component" element={<RegisterComponentPage />} /> + ... +</FlatRoutes>; ``` ## Running diff --git a/plugins/rollbar/README.md b/plugins/rollbar/README.md index 993b93d3a0..584bd7d6bc 100644 --- a/plugins/rollbar/README.md +++ b/plugins/rollbar/README.md @@ -12,33 +12,25 @@ Website: [https://rollbar.com/](https://rollbar.com/) yarn add @backstage/plugin-rollbar ``` -3. Add plugin to the list of plugins: +3. Add to the app `EntityPage` component: -```ts -// packages/app/src/plugins.ts -export { plugin as Rollbar } from '@backstage/plugin-rollbar'; -``` - -4. Add to the app `EntityPage` component: - -```ts +```tsx // packages/app/src/components/catalog/EntityPage.tsx -import { Router as RollbarRouter } from '@backstage/plugin-rollbar'; +import { EntityRollbarContent } from '@backstage/plugin-rollbar'; // ... -const ServiceEntityPage = ({ entity }: { entity: Entity }) => ( +const serviceEntityPage = ( <EntityPageLayout> - // ... - <EntityPageLayout.Content - path="/rollbar" - title="Errors" - element={<RollbarRouter entity={entity} />} - /> + ... + <EntityLayout.Route path="/rollbar" title="Rollbar"> + <EntityRollbarContent /> + </EntityLayout.Route> + ... </EntityPageLayout> ); ``` -5. Setup the `app.config.yaml` and account token environment variable +4. Setup the `app.config.yaml` and account token environment variable ```yaml # app.config.yaml @@ -48,7 +40,7 @@ rollbar: accountToken: ${ROLLBAR_ACCOUNT_TOKEN} ``` -6. Annotate entities with the rollbar project slug +5. Annotate entities with the rollbar project slug ```yaml # pump-station-catalog-component.yaml @@ -60,7 +52,7 @@ metadata: rollbar.com/project-slug: project-name ``` -7. Run app with `yarn start` and navigate to `/rollbar` or a catalog entity +6. Run app with `yarn start` and navigate to `/rollbar` or a catalog entity ## Features diff --git a/plugins/sentry/README.md b/plugins/sentry/README.md index 52cef9cbe6..9bdb2dc16d 100644 --- a/plugins/sentry/README.md +++ b/plugins/sentry/README.md @@ -14,53 +14,43 @@ The Sentry Plugin displays issues from [Sentry](https://sentry.io). yarn add @backstage/plugin-sentry ``` -2. Add plugin to the app: - -```js -// packages/app/src/plugins.ts - -export { plugin as Sentry } from '@backstage/plugin-sentry'; -``` - -3. Add the `SentryIssuesWidget` to the EntityPage: +2. Add the `EntitySentryCard` to the EntityPage: ```jsx // packages/app/src/components/catalog/EntityPage.tsx -import { SentryIssuesWidget } from '@backstage/plugin-sentry'; +import { EntitySentryCard } from '@backstage/plugin-sentry'; -const OverviewContent = ({ entity }: { entity: Entity }) => ( +const overviewContent = ( <Grid container spacing={3} alignItems="stretch"> // ... <Grid item xs={12} sm={6} md={4}> - <SentryIssuesWidget entity={entity} /> + <EntitySentryCard /> </Grid> // ... </Grid> ); ``` -> You can also import a `Router` if you want to have a dedicated sentry page: +> You can also import the full-page `EntitySentryContent` extension if you want to have a dedicated sentry page: > > ```tsx > // packages/app/src/components/catalog/EntityPage.tsx > -> import { Router as SentryRouter } from '@backstage/plugin-sentry'; +> import { EntitySentryContent } from '@backstage/plugin-sentry'; > -> const ServiceEntityPage = ({ entity }: { entity: Entity }) => ( -> <EntityPageLayout> +> const serviceEntityPage = ( +> <EntityLayout> > // ... -> <EntityPageLayout.Content -> path="/sentry" -> title="Sentry" -> element={<SentryRouter entity={entity} />} -> /> +> <EntityLayout.Route path="/sentry" title="Sentry"> +> <EntitySentryContent /> +> </EntityLayout.Route> > // ... -> </EntityPageLayout> +> </EntityLayout> > ); > ``` -4. Add the proxy config: +3. Add the proxy config: ```yaml # app-config.yaml @@ -76,9 +66,9 @@ sentry: organization: <your-organization> ``` -5. Create a new internal integration with the permissions `Issues & Events: Read` (https://docs.sentry.io/product/integrations/integration-platform/) and provide it as `SENTRY_TOKEN` as env variable. +4. Create a new internal integration with the permissions `Issues & Events: Read` (https://docs.sentry.io/product/integrations/integration-platform/) and provide it as `SENTRY_TOKEN` as env variable. -6. Add the `sentry.io/project-slug` annotation to your catalog-info.yaml file: +5. Add the `sentry.io/project-slug` annotation to your catalog-info.yaml file: ```yaml apiVersion: backstage.io/v1alpha1 diff --git a/plugins/sonarqube/README.md b/plugins/sonarqube/README.md index 7c745edf90..5c12832e57 100644 --- a/plugins/sonarqube/README.md +++ b/plugins/sonarqube/README.md @@ -13,14 +13,7 @@ The SonarQube Plugin displays code statistics from [SonarCloud](https://sonarclo yarn add @backstage/plugin-sonarqube ``` -2. Add plugin to the app: - -```js -// packages/app/src/plugins.ts -export { plugin as SonarQube } from '@backstage/plugin-sonarqube'; -``` - -3. Add the `EntitySonarQubeCard` to the EntityPage: +2. Add the `EntitySonarQubeCard` to the EntityPage: ```diff // packages/app/src/components/catalog/EntityPage.tsx @@ -40,7 +33,7 @@ export { plugin as SonarQube } from '@backstage/plugin-sonarqube'; ); ``` -4. Add the proxy config: +3. Add the proxy config: Provide a method for your Backstage backend to get to your SonarQube API end point. Add configuration to your `app-config.yaml` file depending on the product you use. @@ -77,16 +70,16 @@ sonarQube: baseUrl: https://your.sonarqube.instance.com ``` -5. Get and provide `SONARQUBE_AUTH` as an env variable (https://sonarcloud.io/account/security or https://docs.sonarqube.org/latest/user-guide/user-token/) +4. Get and provide `SONARQUBE_AUTH` as an env variable (https://sonarcloud.io/account/security or https://docs.sonarqube.org/latest/user-guide/user-token/) -6. Run the following commands in the root folder of the project to install and compile the changes. +5. Run the following commands in the root folder of the project to install and compile the changes. ```yaml yarn install yarn tsc ``` -7. Add the `sonarqube.org/project-key` annotation to the `catalog-info.yaml` file of the target repo for which code quality analysis is needed. +6. Add the `sonarqube.org/project-key` annotation to the `catalog-info.yaml` file of the target repo for which code quality analysis is needed. ```yaml apiVersion: backstage.io/v1alpha1 From 8e067f00bec02b3666b063cf2f0b8a96ce08f9f6 Mon Sep 17 00:00:00 2001 From: azhurbilo <artemzhurbilo@gmail.com> Date: Thu, 22 Apr 2021 20:22:45 +0300 Subject: [PATCH 094/262] add ability to disable some helm lighthouse resources Signed-off-by: azhurbilo <artemzhurbilo@gmail.com> --- .../backstage/templates/lighthouse-config.yaml | 4 +++- ... => postgresql-password-backend-secret.yaml} | 0 .../postgresql-password-lighthouse-secret.yaml | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) rename contrib/chart/backstage/templates/{postgresql-password-secret.yaml => postgresql-password-backend-secret.yaml} (100%) create mode 100644 contrib/chart/backstage/templates/postgresql-password-lighthouse-secret.yaml diff --git a/contrib/chart/backstage/templates/lighthouse-config.yaml b/contrib/chart/backstage/templates/lighthouse-config.yaml index fdf4bd8b06..7b8cad42dc 100644 --- a/contrib/chart/backstage/templates/lighthouse-config.yaml +++ b/contrib/chart/backstage/templates/lighthouse-config.yaml @@ -1,3 +1,4 @@ +{{- if .Values.lighthouse.enabled }} apiVersion: v1 kind: ConfigMap metadata: @@ -7,4 +8,5 @@ data: PGUSER: {{ include "lighthouse.postgresql.user" . | quote }} PGPORT: {{ include "lighthouse.postgresql.port" . | quote }} PGHOST: {{ include "lighthouse.postgresql.host" . | quote }} - PGPATH_TO_CA: {{ include "backstage.lighthouse.postgresCaFilename" . | quote }} \ No newline at end of file + PGPATH_TO_CA: {{ include "backstage.lighthouse.postgresCaFilename" . | quote }} +{{- end }} \ No newline at end of file diff --git a/contrib/chart/backstage/templates/postgresql-password-secret.yaml b/contrib/chart/backstage/templates/postgresql-password-backend-secret.yaml similarity index 100% rename from contrib/chart/backstage/templates/postgresql-password-secret.yaml rename to contrib/chart/backstage/templates/postgresql-password-backend-secret.yaml diff --git a/contrib/chart/backstage/templates/postgresql-password-lighthouse-secret.yaml b/contrib/chart/backstage/templates/postgresql-password-lighthouse-secret.yaml new file mode 100644 index 0000000000..e7374e70db --- /dev/null +++ b/contrib/chart/backstage/templates/postgresql-password-lighthouse-secret.yaml @@ -0,0 +1,17 @@ +{{- if .Values.lighthouse.enabled }} +{{- if not .Values.postgresql.enabled }} +--- +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ include "lighthouse.postgresql.passwordSecret" . }} + labels: + release: {{ .Release.Name }} + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/hook-delete-policy": "before-hook-creation" +data: + postgresql-password: {{ .Values.lighthouse.database.connection.password | b64enc }} +{{- end }} +{{- end }} From 041575f25741c5924ec83e3cc9a967a93ab11122 Mon Sep 17 00:00:00 2001 From: azhurbilo <artemzhurbilo@gmail.com> Date: Thu, 22 Apr 2021 20:51:37 +0300 Subject: [PATCH 095/262] ability to change components service type Signed-off-by: azhurbilo <artemzhurbilo@gmail.com> --- contrib/chart/backstage/templates/backend-deployment.yaml | 6 +++++- contrib/chart/backstage/templates/frontend-deployment.yaml | 2 +- .../chart/backstage/templates/lighthouse-deployment.yaml | 2 +- contrib/chart/backstage/values.yaml | 3 +++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/contrib/chart/backstage/templates/backend-deployment.yaml b/contrib/chart/backstage/templates/backend-deployment.yaml index 144fc93e62..7009a22de0 100644 --- a/contrib/chart/backstage/templates/backend-deployment.yaml +++ b/contrib/chart/backstage/templates/backend-deployment.yaml @@ -49,16 +49,20 @@ spec: name: {{ include "backend.postgresql.passwordSecret" .}} key: postgresql-password volumeMounts: + {{- if .Values.postgresql.enabled }} - name: postgres-ca mountPath: {{ include "backstage.backend.postgresCaDir" . }} + {{- end }} - name: app-config mountPath: {{ printf "/usr/src/app/%s" (include "backstage.appConfigFilename" .) }} subPath: {{ include "backstage.appConfigFilename" . }} volumes: + {{- if .Values.postgresql.enabled }} - name: postgres-ca configMap: name: {{ include "backstage.fullname" . }}-postgres-ca + {{- end }} - name: app-config configMap: name: {{ include "backstage.fullname" . }}-app-config @@ -83,5 +87,5 @@ spec: app: backstage component: backend - type: ClusterIP + type: {{ .Values.backend.serviceType }} {{- end }} diff --git a/contrib/chart/backstage/templates/frontend-deployment.yaml b/contrib/chart/backstage/templates/frontend-deployment.yaml index 9c674cc160..f74cf0a1e9 100644 --- a/contrib/chart/backstage/templates/frontend-deployment.yaml +++ b/contrib/chart/backstage/templates/frontend-deployment.yaml @@ -62,5 +62,5 @@ spec: app: backstage component: frontend - type: ClusterIP + type: {{ .Values.frontend.serviceType }} {{- end }} diff --git a/contrib/chart/backstage/templates/lighthouse-deployment.yaml b/contrib/chart/backstage/templates/lighthouse-deployment.yaml index d6e1ce19dd..6104d4e73c 100644 --- a/contrib/chart/backstage/templates/lighthouse-deployment.yaml +++ b/contrib/chart/backstage/templates/lighthouse-deployment.yaml @@ -78,5 +78,5 @@ spec: app: backstage component: lighthouse-audit-service - type: ClusterIP + type: {{ .Values.lighthouse.serviceType }} {{- end }} diff --git a/contrib/chart/backstage/values.yaml b/contrib/chart/backstage/values.yaml index bd80bc22b6..e21148b04b 100644 --- a/contrib/chart/backstage/values.yaml +++ b/contrib/chart/backstage/values.yaml @@ -10,6 +10,7 @@ frontend: tag: test1 pullPolicy: IfNotPresent containerPort: 80 + serviceType: ClusterIP resources: requests: memory: 128Mi @@ -26,6 +27,7 @@ backend: tag: test1 pullPolicy: IfNotPresent containerPort: 7000 + serviceType: ClusterIP resources: requests: memory: 512Mi @@ -40,6 +42,7 @@ lighthouse: tag: latest pullPolicy: IfNotPresent containerPort: 3003 + serviceType: ClusterIP resources: requests: memory: 128Mi From 349c15d9f713c2a3c34bd8a9df7343b94ce3bb87 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez <ryanv@spotify.com> Date: Thu, 22 Apr 2021 15:01:40 -0400 Subject: [PATCH 096/262] make ratio optional Signed-off-by: Ryan Vazquez <ryanv@spotify.com> --- .../components/CostGrowth/CostGrowth.test.tsx | 6 + .../src/components/CostGrowth/CostGrowth.tsx | 61 +++++-- .../CostGrowth/CostGrowthIndicator.test.tsx | 9 +- .../CostGrowth/CostGrowthIndicator.tsx | 34 ++-- .../CostOverviewLegend.test.tsx | 153 ++++++++++++++++++ .../CostOverviewCard/CostOverviewLegend.tsx | 27 ++-- .../ProductEntityTable.tsx | 36 +++-- .../ProductInsightsChart.tsx | 33 ++-- .../cost-insights/src/testUtils/mockData.ts | 5 - .../cost-insights/src/testUtils/testUtils.ts | 12 +- .../src/types/ChangeStatistic.ts | 4 +- plugins/cost-insights/src/utils/assert.ts | 2 +- .../cost-insights/src/utils/change.test.ts | 16 +- plugins/cost-insights/src/utils/change.ts | 41 +++-- plugins/cost-insights/src/utils/formatters.ts | 10 +- 15 files changed, 336 insertions(+), 113 deletions(-) create mode 100644 plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.test.tsx diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index f8c06845c9..7133ae81e3 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -46,6 +46,7 @@ describe.each` engineerCost | ratio | amount | expected ${200_000} | ${0} | ${0} | ${'Negligible'} ${200_000} | ${0} | ${8_333} | ${'Negligible'} + ${200_000} | ${undefined} | ${10_000} | ${`~1 ${engineers.unit}`} ${200_000} | ${0.000000001} | ${8_334} | ${`0% or ~1 ${engineers.unit}`} ${200_000} | ${-0.000000001} | ${10_000} | ${`0% or ~1 ${engineers.unit}`} ${200_000} | ${-0.8} | ${10_000} | ${`80% or ~1 ${engineers.unit}`} @@ -65,6 +66,9 @@ describe.each` engineerCost | ratio | amount | expected ${200_000} | ${0} | ${0} | ${'Negligible'} ${200_000} | ${0} | ${8_333} | ${'Negligible'} + ${200_000} | ${undefined} | ${-1_000} | ${'Negligible'} + ${200_000} | ${undefined} | ${1_000} | ${'Negligible'} + ${200_000} | ${undefined} | ${10_000} | ${'~$10,000'} ${200_000} | ${0.000000001} | ${8_334} | ${'0% or ~$8,334'} ${200_000} | ${-0.000000001} | ${10_000} | ${'0% or ~$10,000'} ${200_000} | ${-0.8} | ${10_000} | ${'80% or ~$10,000'} @@ -84,6 +88,8 @@ describe.each` engineerCost | ratio | amount | expected ${200_000} | ${0} | ${0} | ${'Negligible'} ${200_000} | ${0} | ${8_333} | ${'Negligible'} + ${200_000} | ${undefined} | ${1_000} | ${'Negligible'} + ${200_000} | ${undefined} | ${10_000} | ${`~2,857 ${carbon.unit}s`} ${200_000} | ${0.000000001} | ${8_334} | ${`0% or ~2,381 ${carbon.unit}s`} ${200_000} | ${-0.000000001} | ${10_000} | ${`0% or ~2,857 ${carbon.unit}s`} ${200_000} | ${-0.8} | ${10_000} | ${`80% or ~2,857 ${carbon.unit}s`} diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx index 01a0874636..196f8bec44 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx @@ -29,6 +29,7 @@ import { useCostGrowthStyles as useStyles } from '../../utils/styles'; import { formatPercent, formatCurrency } from '../../utils/formatters'; import { indefiniteArticleOf } from '../../utils/grammar'; import { useConfig, useCurrency } from '../../hooks'; +import { notEmpty } from '../../utils/assert'; export type CostGrowthProps = { change: ChangeStatistic; @@ -42,31 +43,65 @@ export const CostGrowth = ({ change, duration }: CostGrowthProps) => { // Only display costs in absolute values const amount = Math.abs(change.amount); - const ratio = Math.abs(change.ratio); + const ratio = Math.abs(change.ratio ?? NaN); const rate = rateOf(engineerCost, duration); const engineers = amount / rate; const converted = amount / (currency.rate ?? rate); + // If a ratio cannot be calculated, don't format. + const growth = notEmpty(change.ratio) + ? growthOf({ ratio: change.ratio, amount: engineers }) + : null; // Determine if growth is significant enough to highlight - const growth = growthOf(change.ratio, engineers); const classes = classnames({ [styles.excess]: growth === GrowthType.Excess, [styles.savings]: growth === GrowthType.Savings, }); - const percent = formatPercent(ratio); - - let cost = `${percent} or ~${formatCurrency(converted, currency.unit)}`; - // Always display the converted value but use the cost in engineers - // to determine negligibility, as costs should be time-period aware if (engineers < EngineerThreshold) { - cost = 'Negligible'; - } else if (currency.kind === CurrencyType.USD) { - cost = `${percent} or ~${currency.prefix}${formatCurrency(converted)}`; - } else if (amount < 1) { - cost = `less than ${indefiniteArticleOf(['a', 'an'], currency.unit)}`; + return <span className={classes}>Negligible</span>; } - return <span className={classes}>{cost}</span>; + if (currency.kind === CurrencyType.USD) { + // Do not display percentage if ratio cannot be calculated + if (isNaN(ratio)) { + return ( + <span className={classes}> + ~{currency.prefix} + {formatCurrency(converted)} + </span> + ); + } + + return ( + <span className={classes}> + {formatPercent(ratio)} or ~{currency.prefix} + {formatCurrency(converted)} + </span> + ); + } + + if (amount < 1) { + return ( + <span className={classes}> + less than {indefiniteArticleOf(['a', 'an'], currency.unit)} + </span> + ); + } + + // Do not display percentage if ratio cannot be calculated + if (isNaN(ratio)) { + return ( + <span className={classes}> + ~{formatCurrency(converted, currency.unit)} + </span> + ); + } + + return ( + <span className={classes}> + {formatPercent(ratio)} or ~{formatCurrency(converted, currency.unit)} + </span> + ); }; diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.test.tsx index 8be5e238cc..6dc6f2cc93 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.test.tsx @@ -21,8 +21,6 @@ import { ChangeThreshold, EngineerThreshold } from '../../types'; describe.each` ratio | amount | ariaLabel - ${-0.1} | ${undefined} | ${'savings'} - ${0.01} | ${undefined} | ${'excess'} ${ChangeThreshold.lower} | ${EngineerThreshold} | ${'savings'} ${ChangeThreshold.lower - 0.01} | ${EngineerThreshold} | ${'savings'} ${ChangeThreshold.lower - 0.01} | ${EngineerThreshold + 0.1} | ${'savings'} @@ -32,7 +30,7 @@ describe.each` `('growthOf', ({ ratio, amount, ariaLabel }) => { it(`should display the correct indicator for ${ariaLabel}`, async () => { const { getByLabelText } = await renderInTestApp( - <CostGrowthIndicator ratio={ratio} amount={amount} />, + <CostGrowthIndicator change={{ ratio, amount }} />, ); expect(getByLabelText(ariaLabel)).toBeInTheDocument(); }); @@ -40,7 +38,8 @@ describe.each` describe.each` ratio | amount - ${0} | ${undefined} + ${undefined} | ${0} + ${0} | ${0} ${ChangeThreshold.lower} | ${0} ${ChangeThreshold.lower + 0.01} | ${EngineerThreshold} ${ChangeThreshold.lower + 0.01} | ${EngineerThreshold + 0.1} @@ -49,7 +48,7 @@ describe.each` `('growthOf', ({ ratio, amount }) => { it('should display the correct indicator for negligible growth', async () => { const { queryByLabelText } = await renderInTestApp( - <CostGrowthIndicator ratio={ratio} amount={amount} />, + <CostGrowthIndicator change={{ ratio, amount }} />, ); expect(queryByLabelText('savings')).not.toBeInTheDocument(); expect(queryByLabelText('excess')).not.toBeInTheDocument(); diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.tsx index e220fdb8e7..a1c200c6b3 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowthIndicator.tsx @@ -20,49 +20,33 @@ import { Typography, TypographyProps } from '@material-ui/core'; import { default as ArrowDropUp } from '@material-ui/icons/ArrowDropUp'; import { default as ArrowDropDown } from '@material-ui/icons/ArrowDropDown'; import { growthOf } from '../../utils/change'; -import { GrowthType } from '../../types'; +import { ChangeStatistic, GrowthType, Maybe } from '../../types'; import { useCostGrowthStyles as useStyles } from '../../utils/styles'; export type CostGrowthIndicatorProps = TypographyProps & { - ratio: number; - amount?: number; - formatter?: (amount: number) => string; + change: ChangeStatistic; + formatter?: (change: ChangeStatistic) => Maybe<string>; }; export const CostGrowthIndicator = ({ - ratio, - amount, + change, formatter, className, ...props }: CostGrowthIndicatorProps) => { const classes = useStyles(); - const growth = growthOf(ratio, amount); + const growth = growthOf(change); const classNames = classnames(classes.indicator, className, { - [classes.savings]: growth === GrowthType.Savings, [classes.excess]: growth === GrowthType.Excess, + [classes.savings]: growth === GrowthType.Savings, }); - // Display cost as a factor of engineer cost growth and percentage growth - if (typeof amount === 'number') { - return ( - <Typography className={classNames} component="span" {...props}> - {formatter ? formatter(amount) : amount} - {growth === GrowthType.Savings && ( - <ArrowDropDown aria-label="savings" /> - )} - {growth === GrowthType.Excess && <ArrowDropUp aria-label="excess" />} - </Typography> - ); - } - - // Display cost as a factor of percent change return ( <Typography className={classNames} component="span" {...props}> - {formatter ? formatter(ratio) : ratio} - {ratio < 0 && <ArrowDropDown aria-label="savings" />} - {ratio > 0 && <ArrowDropUp aria-label="excess" />} + {formatter ? formatter(change) : change.ratio} + {growth === GrowthType.Excess && <ArrowDropUp aria-label="excess" />} + {growth === GrowthType.Savings && <ArrowDropDown aria-label="savings" />} </Typography> ); }; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.test.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.test.tsx new file mode 100644 index 0000000000..112081fed4 --- /dev/null +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.test.tsx @@ -0,0 +1,153 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 React from 'react'; +import { render } from '@testing-library/react'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { CostOverviewLegend } from './CostOverviewLegend'; +import { + MockBillingDateProvider, + MockConfigProvider, + MockFilterProvider, + MockCurrencyProvider, +} from '../../testUtils'; + +function renderInTestApp(children: JSX.Element) { + return render( + wrapInTestApp( + <MockConfigProvider> + <MockCurrencyProvider> + <MockBillingDateProvider> + <MockFilterProvider>{children}</MockFilterProvider> + </MockBillingDateProvider> + </MockCurrencyProvider> + </MockConfigProvider>, + ), + ); +} + +describe('<CostOverviewLegend />', () => { + it('displays the legend without exploding', async () => { + const { findByText } = renderInTestApp( + <CostOverviewLegend + metric={{ + kind: 'msc', + name: 'MSC', + default: false, + }} + metricData={{ + id: 'msc', + format: 'number', + aggregation: [], + change: { + ratio: 0, + amount: 0, + }, + }} + dailyCostData={{ + id: 'mock-id', + aggregation: [], + change: { + amount: 0, + }, + }} + />, + ); + + expect(await findByText('Cost Trend')).toBeInTheDocument(); + expect(await findByText('MSC Trend')).toBeInTheDocument(); + }); + + it('does not display metric legend if metric data is not provided', async () => { + const { findByText, queryByText } = renderInTestApp( + <CostOverviewLegend + metric={{ + kind: 'msc', + name: 'MSC', + default: false, + }} + metricData={null} + dailyCostData={{ + id: 'mock-id', + aggregation: [], + change: { + amount: 0, + }, + }} + />, + ); + + expect(await findByText('Cost Trend')).toBeInTheDocument(); + expect(queryByText('MSC Trend')).not.toBeInTheDocument(); + }); +}); + +describe.each` + ratio | amount | title | expected + ${undefined} | ${1_000} | ${'∞'} | ${'Your Excess'} + ${undefined} | ${-1_000} | ${'-∞'} | ${'Your Savings'} +`('<CostOverviewLegend />', ({ ratio, amount, title, expected }) => { + it('displays the correct legend if ratio cannot be calculated and costs are within time period', async () => { + const { findByText, findAllByText } = renderInTestApp( + <CostOverviewLegend + metric={{ + kind: 'msc', + name: 'MSC', + default: false, + }} + metricData={{ + id: 'msc', + format: 'number', + change: { + ratio: ratio, + amount: amount, + }, + aggregation: [ + { + date: '2020-01-01', + amount: 0, + }, + { + date: '2020-07-01', // within default P90D period + amount: amount, + }, + ], + }} + dailyCostData={{ + id: 'mock-id', + change: { + ratio, + amount, + }, + aggregation: [ + { + date: '2020-01-01', + amount: 0, + }, + { + date: '2020-07-01', // within default P90D period + amount: amount, + }, + ], + }} + />, + ); + + expect(await findByText('Cost Trend')).toBeInTheDocument(); + expect(await findByText('MSC Trend')).toBeInTheDocument(); + expect(await findAllByText(title).then(res => res.length)).toBe(2); + expect(await findByText(expected)).toBeInTheDocument(); + }); +}); diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx index ebba5173a9..0033ba4f14 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx @@ -25,11 +25,13 @@ import { Metric, } from '../../types'; import { useLastCompleteBillingDate, useFilters } from '../../hooks'; -import { getComparedChange } from '../../utils/change'; +import { getComparedChange, choose } from '../../utils/change'; import { mapFiltersToProps } from './selector'; -import { formatPercent } from '../../utils/formatters'; +import { formatChange } from '../../utils/formatters'; import { CostGrowth } from '../CostGrowth'; +import { notEmpty } from '../../utils/assert'; + type CostOverviewLegendProps = { metric: Maybe<Metric>; metricData: Maybe<MetricData>; @@ -42,9 +44,8 @@ export const CostOverviewLegend = ({ metricData, }: PropsWithChildren<CostOverviewLegendProps>) => { const theme = useTheme<CostInsightsTheme>(); - - const lastCompleteBillingDate = useLastCompleteBillingDate(); const { duration } = useFilters(mapFiltersToProps); + const lastCompleteBillingDate = useLastCompleteBillingDate(); const comparedChange = metricData ? getComparedChange( @@ -57,23 +58,25 @@ export const CostOverviewLegend = ({ return ( <Box display="flex" flexDirection="row"> - <Box mr={2}> - <LegendItem title="Cost Trend" markerColor={theme.palette.blue}> - {formatPercent(dailyCostData.change!.ratio)} - </LegendItem> - </Box> - {metric && metricData && comparedChange && ( + {dailyCostData.change && ( + <Box mr={2}> + <LegendItem title="Cost Trend" markerColor={theme.palette.blue}> + {formatChange(dailyCostData.change)} + </LegendItem> + </Box> + )} + {metricData && metric && comparedChange && ( <> <Box mr={2}> <LegendItem title={`${metric.name} Trend`} markerColor={theme.palette.magenta} > - {formatPercent(metricData.change.ratio)} + {formatChange(metricData.change)} </LegendItem> </Box> <LegendItem - title={comparedChange.ratio <= 0 ? 'Your Savings' : 'Your Excess'} + title={choose(['Your Savings', 'Your Excess'], comparedChange)} > <CostGrowth change={comparedChange} duration={duration} /> </LegendItem> diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx index 45576bda65..a8211fbbed 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx @@ -18,10 +18,11 @@ import React from 'react'; import classnames from 'classnames'; import { Table, TableColumn } from '@backstage/core'; import { Typography } from '@material-ui/core'; -import { costFormatter, formatPercent } from '../../utils/formatters'; +import { costFormatter, formatChange } from '../../utils/formatters'; import { useEntityDialogStyles as useStyles } from '../../utils/styles'; import { CostGrowthIndicator } from '../CostGrowth'; -import { BarChartOptions, Entity } from '../../types'; +import { BarChartOptions, ChangeStatistic, Entity } from '../../types'; +import { isUndefined } from '../../utils/assert'; export type ProductEntityTableOptions = Partial< Pick<BarChartOptions, 'previousName' | 'currentName'> @@ -32,7 +33,7 @@ type RowData = { label: string; previous: number; current: number; - ratio: number; + change: ChangeStatistic; }; function createRenderer(col: keyof RowData, classes: Record<string, string>) { @@ -41,7 +42,7 @@ function createRenderer(col: keyof RowData, classes: Record<string, string>) { const rowStyles = classnames(classes.row, { [classes.rowTotal]: row.id === 'total', [classes.colFirst]: col === 'label', - [classes.colLast]: col === 'ratio', + [classes.colLast]: col === 'change', }); switch (col) { @@ -52,12 +53,12 @@ function createRenderer(col: keyof RowData, classes: Record<string, string>) { {costFormatter.format(row[col])} </Typography> ); - case 'ratio': + case 'change': return ( <CostGrowthIndicator className={rowStyles} - ratio={row.ratio} - formatter={amount => formatPercent(Math.abs(amount))} + change={row.change} + formatter={formatChange} /> ); default: @@ -75,10 +76,15 @@ function createSorter(field?: keyof Omit<RowData, 'id'>) { if (a.id === 'total') return 1; if (b.id === 'total') return 1; if (field === 'label') return a.label.localeCompare(b.label); + if (field === 'change') { + if (formatChange(a[field]) === '∞' || formatChange(b[field]) === '-∞') + return 1; + if (formatChange(a[field]) === '-∞' || formatChange(b[field]) === '∞') + return -1; + return a[field].ratio! - b[field].ratio!; + } - return field - ? a[field] - b[field] - : b.previous + b.current - (a.previous + a.current); + return b.previous + b.current - (a.previous + a.current); }; } @@ -134,11 +140,11 @@ export const ProductEntityTable = ({ customSort: createSorter('current'), }, { - field: 'ratio', + field: 'change', title: <Typography className={lastColClasses}>Change</Typography>, align: 'right', - render: createRenderer('ratio', classes), - customSort: createSorter('ratio'), + render: createRenderer('change', classes), + customSort: createSorter('change'), }, ]; @@ -148,14 +154,14 @@ export const ProductEntityTable = ({ label: e.id || 'Unknown', previous: e.aggregation[0], current: e.aggregation[1], - ratio: e.change.ratio, + change: e.change, })) .concat({ id: 'total', label: 'Total', previous: entity.aggregation[0], current: entity.aggregation[1], - ratio: entity.change.ratio, + change: entity.change, }) .sort(createSorter()); diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx index ace2766277..07fea77d9d 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsChart.tsx @@ -40,7 +40,7 @@ import { findAnyKey, assertAlways, } from '../../utils/assert'; -import { formatPeriod, formatPercent } from '../../utils/formatters'; +import { formatPeriod, formatChange } from '../../utils/formatters'; import { titleOf, tooltipItemOf, @@ -54,6 +54,7 @@ import { useBarChartLayoutStyles as useLayoutStyles, } from '../../utils/styles'; import { Duration, Entity, Maybe } from '../../types'; +import { choose } from '../../utils/change'; export type ProductInsightsChartProps = { billingDate: string; @@ -86,7 +87,6 @@ export const ProductInsightsChart = ({ return breakdowns.length > 0; }, [entities, activeLabel]); - const legendTitle = `Cost ${entity.change.ratio <= 0 ? 'Savings' : 'Growth'}`; const costStart = entity.aggregation[0]; const costEnd = entity.aggregation[1]; const resources = entities.map(resourceOf); @@ -136,7 +136,6 @@ export const ProductInsightsChart = ({ const items = payload.map(tooltipItemOf).filter(notEmpty); const activeEntity = findAlways(entities, e => e.id === id); - const ratio = activeEntity.change.ratio; const breakdowns = Object.keys(activeEntity.entities); if (breakdowns.length) { @@ -148,11 +147,13 @@ export const ProductInsightsChart = ({ title={title} subtitle={subtitle} topRight={ - <CostGrowthIndicator - className={classes.indicator} - ratio={ratio} - formatter={formatPercent} - /> + !!activeEntity.change.ratio && ( + <CostGrowthIndicator + formatter={formatChange} + change={activeEntity.change} + className={classes.indicator} + /> + ) } actions={ <Box className={classes.actions}> @@ -173,11 +174,13 @@ export const ProductInsightsChart = ({ <BarChartTooltip title={title} topRight={ - <CostGrowthIndicator - className={classes.indicator} - ratio={ratio} - formatter={formatPercent} - /> + !!activeEntity.change.ratio && ( + <CostGrowthIndicator + formatter={formatChange} + change={activeEntity.change} + className={classes.indicator} + /> + ) } content={ id @@ -197,7 +200,9 @@ export const ProductInsightsChart = ({ return ( <Box className={layoutClasses.wrapper}> <BarChartLegend costStart={costStart} costEnd={costEnd} options={options}> - <LegendItem title={legendTitle}> + <LegendItem + title={choose(['Cost Savings', 'Cost Excess'], entity.change)} + > <CostGrowth change={entity.change} duration={duration} /> </LegendItem> </BarChartLegend> diff --git a/plugins/cost-insights/src/testUtils/mockData.ts b/plugins/cost-insights/src/testUtils/mockData.ts index 5149da278d..27bb07d0e1 100644 --- a/plugins/cost-insights/src/testUtils/mockData.ts +++ b/plugins/cost-insights/src/testUtils/mockData.ts @@ -294,7 +294,6 @@ export const MockBigQueryInsights: Entity = { id: 'dataset-c', aggregation: [0, 10_000], change: { - ratio: 10_000, amount: 10_000, }, entities: {}, @@ -415,7 +414,6 @@ export const MockCloudDataflowInsights: Entity = { id: 'pipeline-c', aggregation: [0, 10_000], change: { - ratio: 10_000, amount: 10_000, }, entities: {}, @@ -503,7 +501,6 @@ export const MockCloudStorageInsights: Entity = { id: 'Mock SKU C', aggregation: [2_000, 0], change: { - ratio: -1, amount: -2000, }, entities: {}, @@ -515,7 +512,6 @@ export const MockCloudStorageInsights: Entity = { id: 'bucket-c', aggregation: [0, 0], change: { - ratio: 0, amount: 0, }, entities: {}, @@ -655,7 +651,6 @@ export const MockComputeEngineInsights: Entity = { id: 'service-c', aggregation: [0, 10_000], change: { - ratio: 10_000, amount: 10_000, }, entities: {}, diff --git a/plugins/cost-insights/src/testUtils/testUtils.ts b/plugins/cost-insights/src/testUtils/testUtils.ts index 37913f635e..5077e05b75 100644 --- a/plugins/cost-insights/src/testUtils/testUtils.ts +++ b/plugins/cost-insights/src/testUtils/testUtils.ts @@ -93,10 +93,16 @@ export function changeOf(aggregation: DateAggregation[]): ChangeStatistic { const lastAmount = aggregation.length ? aggregation[aggregation.length - 1].amount : 0; - const ratio = - firstAmount !== 0 ? (lastAmount - firstAmount) / firstAmount : 0; + + // if either the first or last amounts are zero, the rate of increase/decrease is infinite + if (!firstAmount || !lastAmount) { + return { + amount: lastAmount - firstAmount, + }; + } + return { - ratio: ratio, + ratio: (lastAmount - firstAmount) / firstAmount, amount: lastAmount - firstAmount, }; } diff --git a/plugins/cost-insights/src/types/ChangeStatistic.ts b/plugins/cost-insights/src/types/ChangeStatistic.ts index a47640411a..70cd9fb9a2 100644 --- a/plugins/cost-insights/src/types/ChangeStatistic.ts +++ b/plugins/cost-insights/src/types/ChangeStatistic.ts @@ -16,7 +16,9 @@ export interface ChangeStatistic { // The ratio of change from one duration to another, expressed as: (newSum - oldSum) / oldSum - ratio: number; + // If a ratio cannot be calculated - such as when a new or old sum is zero, + // the ratio can be omitted and where applicable, ∞ or -∞ will display based on amount. + ratio?: number; // The actual USD change between time periods (can be negative if costs decreased) amount: number; } diff --git a/plugins/cost-insights/src/utils/assert.ts b/plugins/cost-insights/src/utils/assert.ts index 05ce65197b..5f9f0d01e1 100644 --- a/plugins/cost-insights/src/utils/assert.ts +++ b/plugins/cost-insights/src/utils/assert.ts @@ -20,7 +20,7 @@ export function notEmpty<TValue>( return !isNull(value) && !isUndefined(value); } -export function isUndefined(value: any): boolean { +export function isUndefined(value: any): value is undefined { return value === undefined; } diff --git a/plugins/cost-insights/src/utils/change.test.ts b/plugins/cost-insights/src/utils/change.test.ts index 7208e9bc4f..191ae589d6 100644 --- a/plugins/cost-insights/src/utils/change.test.ts +++ b/plugins/cost-insights/src/utils/change.test.ts @@ -32,23 +32,23 @@ const GrowthMap = { describe.each` ratio | amount | expected - ${0.0} | ${undefined} | ${GrowthType.Negligible} + ${undefined} | ${0} | ${GrowthType.Negligible} + ${0.0} | ${0} | ${GrowthType.Negligible} ${0.0} | ${EngineerThreshold} | ${GrowthType.Negligible} ${ChangeThreshold.lower} | ${0} | ${GrowthType.Negligible} - ${ChangeThreshold.lower + 0.01} | ${undefined} | ${GrowthType.Negligible} + ${ChangeThreshold.lower + 0.01} | ${0} | ${GrowthType.Negligible} ${ChangeThreshold.lower + 0.01} | ${EngineerThreshold} | ${GrowthType.Negligible} ${ChangeThreshold.lower + 0.01} | ${EngineerThreshold + 0.1} | ${GrowthType.Negligible} ${ChangeThreshold.lower - 0.01} | ${EngineerThreshold - 0.1} | ${GrowthType.Negligible} - ${ChangeThreshold.upper - 0.01} | ${undefined} | ${GrowthType.Negligible} + ${ChangeThreshold.lower - 0.01} | ${0} | ${GrowthType.Negligible} + ${ChangeThreshold.upper} | ${0} | ${GrowthType.Negligible} + ${ChangeThreshold.upper - 0.01} | ${0} | ${GrowthType.Negligible} ${ChangeThreshold.upper + 0.01} | ${EngineerThreshold - 0.1} | ${GrowthType.Negligible} - ${ChangeThreshold.lower} | ${undefined} | ${GrowthType.Savings} + ${ChangeThreshold.upper + 0.01} | ${0} | ${GrowthType.Negligible} ${ChangeThreshold.lower} | ${EngineerThreshold} | ${GrowthType.Savings} - ${ChangeThreshold.lower - 0.01} | ${undefined} | ${GrowthType.Savings} ${ChangeThreshold.lower - 0.01} | ${EngineerThreshold} | ${GrowthType.Savings} ${ChangeThreshold.lower - 0.01} | ${EngineerThreshold + 0.1} | ${GrowthType.Savings} - ${ChangeThreshold.upper} | ${undefined} | ${GrowthType.Excess} ${ChangeThreshold.upper} | ${EngineerThreshold} | ${GrowthType.Excess} - ${ChangeThreshold.upper + 0.01} | ${undefined} | ${GrowthType.Excess} ${ChangeThreshold.upper + 0.01} | ${EngineerThreshold} | ${GrowthType.Excess} ${ChangeThreshold.upper + 0.01} | ${EngineerThreshold + 0.1} | ${GrowthType.Excess} `( @@ -63,7 +63,7 @@ describe.each` expected: GrowthType; }) => { it(`should display ${GrowthMap[expected]}`, () => { - expect(growthOf(ratio, amount)).toBe(expected); + expect(growthOf({ ratio, amount })).toBe(expected); }); }, ); diff --git a/plugins/cost-insights/src/utils/change.ts b/plugins/cost-insights/src/utils/change.ts index 950fbfeb82..479818bdae 100644 --- a/plugins/cost-insights/src/utils/change.ts +++ b/plugins/cost-insights/src/utils/change.ts @@ -27,21 +27,26 @@ import { import dayjs, { OpUnitType } from 'dayjs'; import durationPlugin from 'dayjs/plugin/duration'; import { inclusiveStartDateOf } from './duration'; +import { notEmpty } from './assert'; dayjs.extend(durationPlugin); // Used for displaying status colors -export function growthOf(ratio: number, amount?: number) { - if (typeof amount === 'number') { - if (amount >= EngineerThreshold && ratio >= ChangeThreshold.upper) { +export function growthOf(change: ChangeStatistic): GrowthType { + const exceedsEngineerThreshold = Math.abs(change.amount) >= EngineerThreshold; + + if (notEmpty(change.ratio)) { + if (exceedsEngineerThreshold && change.ratio >= ChangeThreshold.upper) { return GrowthType.Excess; } - if (amount >= EngineerThreshold && ratio <= ChangeThreshold.lower) { + + if (exceedsEngineerThreshold && change.ratio <= ChangeThreshold.lower) { return GrowthType.Savings; } } else { - if (ratio >= ChangeThreshold.upper) return GrowthType.Excess; - if (ratio <= ChangeThreshold.lower) return GrowthType.Savings; + if (exceedsEngineerThreshold && change.amount > 0) return GrowthType.Excess; + if (exceedsEngineerThreshold && change.amount < 0) + return GrowthType.Savings; } return GrowthType.Negligible; @@ -54,15 +59,24 @@ export function getComparedChange( duration: Duration, lastCompleteBillingDate: string, // YYYY-MM-DD, ): ChangeStatistic { - const ratio = dailyCost.change!.ratio - metricData.change.ratio; + const dailyCostRatio = dailyCost.change?.ratio; + const metricDataRatio = metricData.change?.ratio; const previousPeriodTotal = getPreviousPeriodTotalCost( dailyCost.aggregation, duration, lastCompleteBillingDate, ); + + // if either ratio cannot be calculated, no compared ratio can be calculated + if (!notEmpty(dailyCostRatio) || !notEmpty(metricDataRatio)) { + return { + amount: previousPeriodTotal, + }; + } + return { - ratio: ratio, - amount: previousPeriodTotal * ratio, + ratio: dailyCostRatio - metricDataRatio, + amount: previousPeriodTotal * (dailyCostRatio - metricDataRatio), }; } @@ -78,7 +92,6 @@ export function getPreviousPeriodTotalCost( ? [dayjsDuration.days(), 'day'] : [dayjsDuration.months(), 'month']; const nextPeriodStart = dayjs(startDate).add(amount, type); - // Add up costs that incurred before the start of the next period. return aggregation.reduce((acc, costByDate) => { return dayjs(costByDate.date).isBefore(nextPeriodStart) @@ -86,3 +99,11 @@ export function getPreviousPeriodTotalCost( : acc; }, 0); } + +export function choose<T>( + [savings, excess]: [T, T], + change: ChangeStatistic, +): T { + const isSavings = (change.ratio ?? change.amount) <= 0; + return isSavings ? savings : excess; +} diff --git a/plugins/cost-insights/src/utils/formatters.ts b/plugins/cost-insights/src/utils/formatters.ts index 8f2b94f997..75306d7392 100644 --- a/plugins/cost-insights/src/utils/formatters.ts +++ b/plugins/cost-insights/src/utils/formatters.ts @@ -16,8 +16,9 @@ import moment from 'moment'; import pluralize from 'pluralize'; -import { Duration } from '../types'; +import { ChangeStatistic, Duration } from '../types'; import { inclusiveEndDateOf, inclusiveStartDateOf } from '../utils/duration'; +import { notEmpty } from './assert'; export type Period = { periodStart: string; @@ -78,6 +79,13 @@ export function formatCurrency(amount: number, currency?: string): string { return currency ? `${numString} ${pluralize(currency, n)}` : numString; } +export function formatChange(change: ChangeStatistic): string { + if (notEmpty(change.ratio)) { + return formatPercent(Math.abs(change.ratio)); + } + return change.amount >= 0 ? '∞' : '-∞'; +} + export function formatPercent(n: number): string { // Number.toFixed shows scientific notation for extreme numbers if (isNaN(n) || Math.abs(n) < 0.01) { From 6f1b82b14175f85a76a7b91db9800ec8f6425d81 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez <ryanv@spotify.com> Date: Thu, 22 Apr 2021 15:03:17 -0400 Subject: [PATCH 097/262] changeset Signed-off-by: Ryan Vazquez <ryanv@spotify.com> --- .changeset/cost-insights-five-baboons-attack.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/cost-insights-five-baboons-attack.md diff --git a/.changeset/cost-insights-five-baboons-attack.md b/.changeset/cost-insights-five-baboons-attack.md new file mode 100644 index 0000000000..f2c070acb4 --- /dev/null +++ b/.changeset/cost-insights-five-baboons-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': minor +--- + +make change ratio optional From c2abcf91acc397b9837eff29f0dffbcbdfb110da Mon Sep 17 00:00:00 2001 From: Ryan Vazquez <ryanv@spotify.com> Date: Thu, 22 Apr 2021 15:41:58 -0400 Subject: [PATCH 098/262] lint Signed-off-by: Ryan Vazquez <ryanv@spotify.com> --- .../src/components/CostOverviewCard/CostOverviewLegend.tsx | 2 -- .../src/components/ProductInsightsCard/ProductEntityTable.tsx | 1 - 2 files changed, 3 deletions(-) diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx index 0033ba4f14..ad8a065a6e 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewLegend.tsx @@ -30,8 +30,6 @@ import { mapFiltersToProps } from './selector'; import { formatChange } from '../../utils/formatters'; import { CostGrowth } from '../CostGrowth'; -import { notEmpty } from '../../utils/assert'; - type CostOverviewLegendProps = { metric: Maybe<Metric>; metricData: Maybe<MetricData>; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx index a8211fbbed..f9bb44058b 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductEntityTable.tsx @@ -22,7 +22,6 @@ import { costFormatter, formatChange } from '../../utils/formatters'; import { useEntityDialogStyles as useStyles } from '../../utils/styles'; import { CostGrowthIndicator } from '../CostGrowth'; import { BarChartOptions, ChangeStatistic, Entity } from '../../types'; -import { isUndefined } from '../../utils/assert'; export type ProductEntityTableOptions = Partial< Pick<BarChartOptions, 'previousName' | 'currentName'> From 39bdaa0046f41c395d0e43f7b00d6d4239471b30 Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" <ftt.adrian.ke@grabtaxi.com> Date: Tue, 6 Apr 2021 17:18:38 +0800 Subject: [PATCH 099/262] Add TechDocs landing page customization and exported components Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- .changeset/techdocs-quiet-pens-prove.md | 5 + docs/features/techdocs/how-to-guides.md | 77 ++++++++ ...Content.test.tsx => DocsCardGrid.test.tsx} | 17 +- .../src/home/components/DocsCardGrid.tsx | 58 ++++++ ...nedContent.test.tsx => DocsTable.test.tsx} | 44 +---- .../{OwnedContent.tsx => DocsTable.tsx} | 68 +++---- .../src/home/components/OverviewContent.tsx | 73 -------- .../components/TechDocsCustomHome.test.tsx | 83 +++++++++ .../home/components/TechDocsCustomHome.tsx | 169 ++++++++++++++++++ .../src/home/components/TechDocsHome.test.tsx | 26 ++- .../src/home/components/TechDocsHome.tsx | 118 ++++-------- plugins/techdocs/src/index.ts | 5 + plugins/techdocs/src/plugin.ts | 39 ++++ 13 files changed, 538 insertions(+), 244 deletions(-) create mode 100644 .changeset/techdocs-quiet-pens-prove.md rename plugins/techdocs/src/home/components/{OverviewContent.test.tsx => DocsCardGrid.test.tsx} (77%) create mode 100644 plugins/techdocs/src/home/components/DocsCardGrid.tsx rename plugins/techdocs/src/home/components/{OwnedContent.test.tsx => DocsTable.test.tsx} (68%) rename plugins/techdocs/src/home/components/{OwnedContent.tsx => DocsTable.tsx} (67%) delete mode 100644 plugins/techdocs/src/home/components/OverviewContent.tsx create mode 100644 plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx create mode 100644 plugins/techdocs/src/home/components/TechDocsCustomHome.tsx diff --git a/.changeset/techdocs-quiet-pens-prove.md b/.changeset/techdocs-quiet-pens-prove.md new file mode 100644 index 0000000000..379c20e72a --- /dev/null +++ b/.changeset/techdocs-quiet-pens-prove.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Add customization and exportable components for TechDocs landing page diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 2cb769b0e3..a76905d6c5 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -82,3 +82,80 @@ Caveat: Currently TechDocs sites built using URL Reader will be cached for 30 minutes which means they will not be re-built if new changes are made within 30 minutes. This cache invalidation will be replaced by commit timestamp based implementation very soon. + +## How to use a custom TechDocs home page? + +### 1st way: TechDocsCustomHome with a custom configuration + +In your main App.tsx: + +``` +import { + TechDocsCustomHome, + WidgetType, + TechDocsReaderPage, +} from '@backstage/plugin-techdocs'; +import { Entity } from '@backstage/catalog-model'; + +const tabsConfig = [ + { + label: 'Custom Tab', + widgets: [ + { + title: 'Custom Documents Cards 1', + description: + 'Explore your internal technical ecosystem through documentation.', + // sets maximum height of widget, as CSS maxHeight attribute + widgetMaxHeight: '400px' + widgetType: 'DocsCardGrid' as WidgetType, + filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationOne']; + }, + { + title: 'Custom Documents Cards 2', + description: + 'Explore your internal technical ecosystem through documentation.', + widgetMaxHeight: '400px' + widgetType: 'DocsCardGrid' as WidgetType, + filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationTwo']; + }, + ], + }, + { + label: 'Overview', + widgets: [ + { + title: 'Overview', + description: + 'Explore your internal technical ecosystem through documentation.', + widgetType: 'DocsTable' as WidgetType, + filterPredicate: () => true, + }, + ], + }, +]; + +const routes = ( + <FlatRoutes> + <Route + path="/docs" + element={<TechDocsCustomHome tabsConfig={tabsConfig} />} + /> + <Route + path="/docs/:namespace/:kind/:name/*" + element={<TechDocsReaderPage />} + /> + </FlatRoutes> +``` + +An example of tabsConfig that corresponds to the default documentation home page +can be found at `plugins/techdocs/src/home/components/TechDocsHome.tsx`. + +### 2nd way: custom home page plugin + +A custom home page plugin can be built that uses the components extensions +DocsCardGrid and DocsTable, exported from @backstage/techdocs. They both take a +array of documentation entities ( have 'backstage.io/techdocs-ref' annotation ) +as an 'entities' attribute. + +For an reference to the React structure of the default home page, please refer +to `plugins/techdocs/src/home/components/TechDocsCustomHome.tsx`. diff --git a/plugins/techdocs/src/home/components/OverviewContent.test.tsx b/plugins/techdocs/src/home/components/DocsCardGrid.test.tsx similarity index 77% rename from plugins/techdocs/src/home/components/OverviewContent.test.tsx rename to plugins/techdocs/src/home/components/DocsCardGrid.test.tsx index ec67c346d7..1ddaa4c373 100644 --- a/plugins/techdocs/src/home/components/OverviewContent.test.tsx +++ b/plugins/techdocs/src/home/components/DocsCardGrid.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,13 +17,13 @@ import { wrapInTestApp } from '@backstage/test-utils'; import { render } from '@testing-library/react'; import React from 'react'; -import { OverviewContent } from './OverviewContent'; +import { DocsCardGrid } from './DocsCardGrid'; -describe('TechDocs Overview Content', () => { - it('should render all TechDocs Documents', async () => { +describe('Entity Docs Card Grid', () => { + it('should render all entities passed ot it', async () => { const { findByText } = render( wrapInTestApp( - <OverviewContent + <DocsCardGrid entities={[ { apiVersion: 'version', @@ -49,13 +49,6 @@ describe('TechDocs Overview Content', () => { />, ), ); - - expect(await findByText('Overview')).toBeInTheDocument(); - expect( - await findByText( - /Explore your internal technical ecosystem through documentation./i, - ), - ).toBeInTheDocument(); expect(await findByText('testName')).toBeInTheDocument(); expect(await findByText('testName2')).toBeInTheDocument(); }); diff --git a/plugins/techdocs/src/home/components/DocsCardGrid.tsx b/plugins/techdocs/src/home/components/DocsCardGrid.tsx new file mode 100644 index 0000000000..47f747442c --- /dev/null +++ b/plugins/techdocs/src/home/components/DocsCardGrid.tsx @@ -0,0 +1,58 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 React from 'react'; +import { generatePath } from 'react-router-dom'; + +import { Entity } from '@backstage/catalog-model'; +import { Button, ItemCardGrid, ItemCardHeader } from '@backstage/core'; +import { Card, CardActions, CardContent, CardMedia } from '@material-ui/core'; + +import { rootDocsRouteRef } from '../../plugin'; + +export const DocsCardGrid = ({ + entities, +}: { + entities: Entity[] | undefined; +}) => { + if (!entities) return null; + return ( + <ItemCardGrid data-testid="docs-explore"> + {!entities?.length + ? null + : entities.map((entity, index: number) => ( + <Card key={index}> + <CardMedia> + <ItemCardHeader title={entity.metadata.name} /> + </CardMedia> + <CardContent>{entity.metadata.description}</CardContent> + <CardActions> + <Button + to={generatePath(rootDocsRouteRef.path, { + namespace: entity.metadata.namespace ?? 'default', + kind: entity.kind, + name: entity.metadata.name, + })} + color="primary" + > + Read Docs + </Button> + </CardActions> + </Card> + ))} + </ItemCardGrid> + ); +}; diff --git a/plugins/techdocs/src/home/components/OwnedContent.test.tsx b/plugins/techdocs/src/home/components/DocsTable.test.tsx similarity index 68% rename from plugins/techdocs/src/home/components/OwnedContent.test.tsx rename to plugins/techdocs/src/home/components/DocsTable.test.tsx index edccb0d3c6..8a7d8d9af1 100644 --- a/plugins/techdocs/src/home/components/OwnedContent.test.tsx +++ b/plugins/techdocs/src/home/components/DocsTable.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,37 +16,13 @@ import React from 'react'; import { render } from '@testing-library/react'; import { wrapInTestApp } from '@backstage/test-utils'; -import { OwnedContent } from './OwnedContent'; +import { DocsTable } from './DocsTable'; -jest.mock('../hooks', () => ({ - useOwnUser: () => { - return { - value: { - apiVersion: 'version', - kind: 'User', - metadata: { - name: 'owned', - namespace: 'default', - }, - relations: [ - { - target: { - kind: 'TestKind', - name: 'testName', - }, - type: 'ownerOf', - }, - ], - }, - }; - }, -})); - -describe('TechDocs Owned Content', () => { - it('should render TechDocs Owned Documents', async () => { - const { findByText, queryByText } = render( +describe('DocsTable test', () => { + it('should render documents passed', async () => { + const { findByText } = render( wrapInTestApp( - <OwnedContent + <DocsTable entities={[ { apiVersion: 'version', @@ -93,16 +69,12 @@ describe('TechDocs Owned Content', () => { ), ); - expect(await findByText('Owned documents')).toBeInTheDocument(); - expect(await findByText(/Access your documentation./i)).toBeInTheDocument(); expect(await findByText('testName')).toBeInTheDocument(); - expect(await queryByText('testName2')).not.toBeInTheDocument(); + expect(await findByText('testName2')).toBeInTheDocument(); }); it('should render empty state if no owned documents exist', async () => { - const { findByText } = render( - wrapInTestApp(<OwnedContent entities={[]} />), - ); + const { findByText } = render(wrapInTestApp(<DocsTable entities={[]} />)); expect(await findByText('No documents to show')).toBeInTheDocument(); }); diff --git a/plugins/techdocs/src/home/components/OwnedContent.tsx b/plugins/techdocs/src/home/components/DocsTable.tsx similarity index 67% rename from plugins/techdocs/src/home/components/OwnedContent.tsx rename to plugins/techdocs/src/home/components/DocsTable.tsx index f962147345..341ff852be 100644 --- a/plugins/techdocs/src/home/components/OwnedContent.tsx +++ b/plugins/techdocs/src/home/components/DocsTable.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,46 +20,34 @@ import { generatePath } from 'react-router-dom'; import { IconButton, Tooltip } from '@material-ui/core'; import ShareIcon from '@material-ui/icons/Share'; -import { - Content, - ContentHeader, - SupportButton, - Table, - EmptyState, - Button, - SubvalueCell, - Link, -} from '@backstage/core'; +import { Table, EmptyState, Button, SubvalueCell, Link } from '@backstage/core'; import { Entity } from '@backstage/catalog-model'; -import { isOwnerOf } from '@backstage/plugin-catalog-react'; import { rootDocsRouteRef } from '../../plugin'; -import { useOwnUser } from '../hooks'; -export const OwnedContent = ({ +export const DocsTable = ({ entities, + title, }: { entities: Entity[] | undefined; + title?: string | undefined; }) => { const [, copyToClipboard] = useCopyToClipboard(); - const { value: user } = useOwnUser(); - if (!entities || !user) return null; + if (!entities) return null; - const ownedDocuments = entities - .filter((entity: Entity) => isOwnerOf(user, entity)) - .map(entity => { - return { + const documents = entities.map(entity => { + return { + name: entity.metadata.name, + description: entity.metadata.description, + owner: entity?.spec?.owner, + type: entity?.spec?.type, + docsUrl: generatePath(rootDocsRouteRef.path, { + namespace: entity.metadata.namespace ?? 'default', + kind: entity.kind, name: entity.metadata.name, - description: entity.metadata.description, - owner: entity?.spec?.owner, - type: entity?.spec?.type, - docsUrl: generatePath(rootDocsRouteRef.path, { - namespace: entity.metadata.namespace ?? 'default', - kind: entity.kind, - name: entity.metadata.name, - }), - }; - }); + }), + }; + }); const columns = [ { @@ -99,19 +87,17 @@ export const OwnedContent = ({ ]; return ( - <Content> - <ContentHeader - title="Owned documents" - description="Access your documentation." - > - <SupportButton>Discover documentation you own.</SupportButton> - </ContentHeader> - {ownedDocuments && ownedDocuments.length > 0 ? ( + <> + {documents && documents.length > 0 ? ( <Table options={{ paging: true, pageSize: 20, search: true }} - data={ownedDocuments} + data={documents} columns={columns} - title={`Owned (${ownedDocuments.length})`} + title={ + title + ? `${title} (${documents.length})` + : `All (${documents.length})` + } /> ) : ( <EmptyState @@ -130,6 +116,6 @@ export const OwnedContent = ({ } /> )} - </Content> + </> ); }; diff --git a/plugins/techdocs/src/home/components/OverviewContent.tsx b/plugins/techdocs/src/home/components/OverviewContent.tsx deleted file mode 100644 index e0030691f5..0000000000 --- a/plugins/techdocs/src/home/components/OverviewContent.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 React from 'react'; -import { generatePath } from 'react-router-dom'; - -import { Entity } from '@backstage/catalog-model'; -import { - Button, - Content, - ContentHeader, - SupportButton, - ItemCardGrid, - ItemCardHeader, -} from '@backstage/core'; -import { Card, CardActions, CardContent, CardMedia } from '@material-ui/core'; - -import { rootDocsRouteRef } from '../../plugin'; - -export const OverviewContent = ({ - entities, -}: { - entities: Entity[] | undefined; -}) => { - if (!entities) return null; - return ( - <Content> - <ContentHeader - title="Overview" - description="Explore your internal technical ecosystem through documentation." - > - <SupportButton>Discover documentation in your ecosystem.</SupportButton> - </ContentHeader> - <ItemCardGrid data-testid="docs-explore"> - {!entities?.length - ? null - : entities.map((entity, index: number) => ( - <Card key={index}> - <CardMedia> - <ItemCardHeader title={entity.metadata.name} /> - </CardMedia> - <CardContent>{entity.metadata.description}</CardContent> - <CardActions> - <Button - to={generatePath(rootDocsRouteRef.path, { - namespace: entity.metadata.namespace ?? 'default', - kind: entity.kind, - name: entity.metadata.name, - })} - color="primary" - > - Read Docs - </Button> - </CardActions> - </Card> - ))} - </ItemCardGrid> - </Content> - ); -}; diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx new file mode 100644 index 0000000000..a7f4d90240 --- /dev/null +++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx @@ -0,0 +1,83 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { ApiProvider, ApiRegistry } from '@backstage/core'; +import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; +import React from 'react'; +import { TechDocsCustomHome, WidgetType } from './TechDocsCustomHome'; + +describe('TechDocsCustomHome', () => { + const catalogApi: Partial<CatalogApi> = { + getEntities: async () => ({ items: [] }), + }; + + const apiRegistry = ApiRegistry.with(catalogApiRef, catalogApi); + + it('should render a TechDocs home page', async () => { + const tabsConfig = [ + { + label: 'First Tab', + widgets: [ + { + title: 'First Tab', + description: 'First Tab Description', + widgetType: 'DocsCardGrid' as WidgetType, + filterPredicate: () => true, + }, + ], + }, + { + label: 'Second Tab ', + widgets: [ + { + title: 'Second Tab', + description: 'Second Tab Description', + widgetType: 'DocsTable' as WidgetType, + filterPredicate: () => true, + }, + ], + }, + ]; + + await renderInTestApp( + <ApiProvider apis={apiRegistry}> + <TechDocsCustomHome tabsConfig={tabsConfig} /> + </ApiProvider>, + ); + + // Header + expect(await screen.findByText('Documentation')).toBeInTheDocument(); + expect( + await screen.findByText(/Documentation available in Backstage/i), + ).toBeInTheDocument(); + + // Explore Content + expect(await screen.findByTestId('docs-explore')).toBeDefined(); + + // Tabs + expect(await screen.findAllByText('First Tab')).toHaveLength(2); + expect(await screen.findByText('Second Tab')).toBeInTheDocument(); + expect( + await screen.findByText('First Tab Description'), + ).toBeInTheDocument(); + (await screen.findByText('Second Tab')).click(); + expect( + await screen.findByText('Second Tab Description'), + ).toBeInTheDocument(); + }); +}); diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx new file mode 100644 index 0000000000..37a9dadddb --- /dev/null +++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx @@ -0,0 +1,169 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 React, { useState } from 'react'; +import { useAsync } from 'react-use'; +import { makeStyles } from '@material-ui/core'; + +import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; +import { Entity } from '@backstage/catalog-model'; +import { + CodeSnippet, + Content, + ConfigApi, + configApiRef, + Header, + HeaderTabs, + Page, + Progress, + useApi, + WarningPanel, + SupportButton, + ContentHeader, +} from '@backstage/core'; +import { DocsTable } from './DocsTable'; +import { DocsCardGrid } from './DocsCardGrid'; + +const widgets = { + DocsTable: DocsTable, + DocsCardGrid: DocsCardGrid, +}; + +export type WidgetType = 'DocsCardGrid' | 'DocsTable'; + +export interface WidgetConfig { + title: string; + description: string; + widgetType: WidgetType; + widgetMaxHeight?: string; + filterPredicate: (entity: Entity) => boolean; +} + +export interface TabConfig { + label: string; + widgets: WidgetConfig[]; +} + +export type TabsConfig = TabConfig[]; + +const CustomWidget = ({ + config, + entities, + index, +}: { + config: WidgetConfig; + entities: Entity[]; + index: number; +}) => { + const useStyles = makeStyles({ + widgetContainer: { + maxHeight: config.widgetMaxHeight || 'inherit', + marginBottom: '2rem', + overflow: 'auto', + }, + }); + const classes = useStyles(); + const Widget = widgets[config.widgetType]; + const shownEntities = entities.filter(config.filterPredicate); + return ( + <> + <ContentHeader title={config.title} description={config.description}> + {index === 0 ? ( + <SupportButton> + Discover documentation in your ecosystem. + </SupportButton> + ) : null} + </ContentHeader> + <div className={classes.widgetContainer}> + <Widget entities={shownEntities} /> + </div> + </> + ); +}; + +export const TechDocsCustomHome = ({ + tabsConfig, +}: { + tabsConfig: TabsConfig; +}) => { + const [selectedTab, setSelectedTab] = useState<number>(0); + const catalogApi: CatalogApi = useApi(catalogApiRef); + const configApi: ConfigApi = useApi(configApiRef); + + const { value: entities, loading, error } = useAsync(async () => { + const response = await catalogApi.getEntities(); + return response.items.filter((entity: Entity) => { + return !!entity.metadata.annotations?.['backstage.io/techdocs-ref']; + }); + }); + + const generatedSubtitle = `Documentation available in ${ + configApi.getOptionalString('organization.name') ?? 'Backstage' + }`; + + const currentTabConfig = tabsConfig[selectedTab]; + + if (loading) { + return ( + <Page themeId="documentation"> + <Header title="Documentation" subtitle={generatedSubtitle} /> + <Content> + <Progress /> + </Content> + </Page> + ); + } + + if (error) { + return ( + <Page themeId="documentation"> + <Header title="Documentation" subtitle={generatedSubtitle} /> + <Content> + <WarningPanel + severity="error" + title="Could not load available documentation." + > + <CodeSnippet language="text" text={error.toString()} /> + </WarningPanel> + </Content> + </Page> + ); + } + + return ( + <Page themeId="documentation"> + <Header title="Documentation" subtitle={generatedSubtitle} /> + <HeaderTabs + selectedIndex={selectedTab} + onChange={index => setSelectedTab(index)} + tabs={tabsConfig.map(({ label }, index) => ({ + id: index.toString(), + label, + }))} + /> + <Content> + {currentTabConfig.widgets.map((config, index) => ( + <CustomWidget + key={index} + config={config} + entities={!!entities ? entities : []} + index={index} + /> + ))} + </Content> + </Page> + ); +}; diff --git a/plugins/techdocs/src/home/components/TechDocsHome.test.tsx b/plugins/techdocs/src/home/components/TechDocsHome.test.tsx index 8067767d39..566ed3bd0b 100644 --- a/plugins/techdocs/src/home/components/TechDocsHome.test.tsx +++ b/plugins/techdocs/src/home/components/TechDocsHome.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,30 @@ import { screen } from '@testing-library/react'; import React from 'react'; import { TechDocsHome } from './TechDocsHome'; +jest.mock('../hooks', () => ({ + useOwnUser: () => { + return { + value: { + apiVersion: 'version', + kind: 'User', + metadata: { + name: 'owned', + namespace: 'default', + }, + relations: [ + { + target: { + kind: 'TestKind', + name: 'testName', + }, + type: 'ownerOf', + }, + ], + }, + }; + }, +})); + describe('TechDocs Home', () => { const catalogApi: Partial<CatalogApi> = { getEntities: async () => ({ items: [] }), diff --git a/plugins/techdocs/src/home/components/TechDocsHome.tsx b/plugins/techdocs/src/home/components/TechDocsHome.tsx index 5e9e25e7a0..904c759b11 100644 --- a/plugins/techdocs/src/home/components/TechDocsHome.tsx +++ b/plugins/techdocs/src/home/components/TechDocsHome.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,88 +14,44 @@ * limitations under the License. */ -import React, { useState } from 'react'; -import { useAsync } from 'react-use'; - -import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; +import React from 'react'; import { Entity } from '@backstage/catalog-model'; -import { - CodeSnippet, - ConfigApi, - configApiRef, - Content, - Header, - HeaderTabs, - Page, - Progress, - useApi, - WarningPanel, -} from '@backstage/core'; - -import { OverviewContent } from './OverviewContent'; -import { OwnedContent } from './OwnedContent'; +import { useOwnUser } from '../hooks'; +import { isOwnerOf } from '@backstage/plugin-catalog-react'; +import { WidgetType, TechDocsCustomHome } from './TechDocsCustomHome'; export const TechDocsHome = () => { - const [selectedTab, setSelectedTab] = useState<number>(0); - const catalogApi: CatalogApi = useApi(catalogApiRef); - const configApi: ConfigApi = useApi(configApiRef); + const { value: user } = useOwnUser(); - const tabs = [{ label: 'Overview' }, { label: 'Owned Documents' }]; - - const { value, loading, error } = useAsync(async () => { - const response = await catalogApi.getEntities(); - return response.items.filter((entity: Entity) => { - return !!entity.metadata.annotations?.['backstage.io/techdocs-ref']; - }); - }); - - const generatedSubtitle = `Documentation available in ${ - configApi.getOptionalString('organization.name') ?? 'Backstage' - }`; - - if (loading) { - return ( - <Page themeId="documentation"> - <Header title="Documentation" subtitle={generatedSubtitle} /> - <Content> - <Progress /> - </Content> - </Page> - ); - } - - if (error) { - return ( - <Page themeId="documentation"> - <Header title="Documentation" subtitle={generatedSubtitle} /> - <Content> - <WarningPanel - severity="error" - title="Could not load available documentation." - > - <CodeSnippet language="text" text={error.toString()} /> - </WarningPanel> - </Content> - </Page> - ); - } - - return ( - <Page themeId="documentation"> - <Header title="Documentation" subtitle={generatedSubtitle} /> - <HeaderTabs - selectedIndex={selectedTab} - onChange={index => setSelectedTab(index)} - tabs={tabs.map(({ label }, index) => ({ - id: index.toString(), - label, - }))} - /> - {selectedTab === 0 ? ( - <OverviewContent entities={value} /> - ) : ( - <OwnedContent entities={value} /> - )} - </Page> - ); + const tabsConfig = [ + { + label: 'Overview', + widgets: [ + { + title: 'Overview', + description: + 'Explore your internal technical ecosystem through documentation.', + widgetType: 'DocsCardGrid' as WidgetType, + filterPredicate: () => true, + }, + ], + }, + { + label: 'Owned', + widgets: [ + { + title: 'Owned documents', + description: 'Access your documentation.', + widgetType: 'DocsTable' as WidgetType, + filterPredicate: (entity: Entity) => { + if (!user) { + return false; + } + return isOwnerOf(user, entity); + }, + }, + ], + }, + ]; + return <TechDocsCustomHome tabsConfig={tabsConfig} />; }; diff --git a/plugins/techdocs/src/index.ts b/plugins/techdocs/src/index.ts index 30c143e31f..f72938e385 100644 --- a/plugins/techdocs/src/index.ts +++ b/plugins/techdocs/src/index.ts @@ -19,7 +19,12 @@ export { techdocsPlugin as plugin, TechdocsPage, EntityTechdocsContent, + DocsCardGrid, + DocsTable, + TechDocsCustomHome, + TechDocsReaderPage, } from './plugin'; export { Router, EmbeddedDocsRouter } from './Router'; export * from './reader'; export * from './api'; +export type { WidgetType } from './home/components/TechDocsCustomHome'; diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index a945ca1494..d9b38a2c76 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -37,6 +37,7 @@ import { discoveryApiRef, identityApiRef, createRoutableExtension, + createComponentExtension, } from '@backstage/core'; import { techdocsStorageApiRef, @@ -111,3 +112,41 @@ export const EntityTechdocsContent = techdocsPlugin.provide( mountPoint: rootCatalogDocsRouteRef, }), ); + +// takes a list of entities and renders documentation cards +export const DocsCardGrid = techdocsPlugin.provide( + createComponentExtension({ + component: { + lazy: () => + import('./home/components/DocsCardGrid').then(m => m.DocsCardGrid), + }, + }), +); + +// takes a list of entities and renders table listing documentation +export const DocsTable = techdocsPlugin.provide( + createComponentExtension({ + component: { + lazy: () => import('./home/components/DocsTable').then(m => m.DocsTable), + }, + }), +); + +// takes a custom tabs config object and renders a documentation landing page +export const TechDocsCustomHome = techdocsPlugin.provide( + createRoutableExtension({ + component: () => + import('./home/components/TechDocsCustomHome').then( + m => m.TechDocsCustomHome, + ), + mountPoint: rootRouteRef, + }), +); + +export const TechDocsReaderPage = techdocsPlugin.provide( + createRoutableExtension({ + component: () => + import('./reader/components/TechDocsPage').then(m => m.TechDocsPage), + mountPoint: rootDocsRouteRef, + }), +); From 10579c3d0daf824ae2aa41a63e280039e50e14b4 Mon Sep 17 00:00:00 2001 From: Adrian Ke Chongyang <14866712+adrianke77@users.noreply.github.com> Date: Mon, 19 Apr 2021 15:17:50 +0800 Subject: [PATCH 100/262] Update docs/features/techdocs/how-to-guides.md Co-authored-by: Himanshu Mishra <himanshu@orkohunter.net> Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index a76905d6c5..2b3fd08f76 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -89,7 +89,7 @@ implementation very soon. In your main App.tsx: -``` +```tsx import { TechDocsCustomHome, WidgetType, From 74c91998bfd295d2422a3b63327344bdf739ba8d Mon Sep 17 00:00:00 2001 From: Adrian Ke Chongyang <14866712+adrianke77@users.noreply.github.com> Date: Mon, 19 Apr 2021 15:17:55 +0800 Subject: [PATCH 101/262] Update docs/features/techdocs/how-to-guides.md Co-authored-by: Himanshu Mishra <himanshu@orkohunter.net> Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 2b3fd08f76..f387379e06 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -150,7 +150,7 @@ const routes = ( An example of tabsConfig that corresponds to the default documentation home page can be found at `plugins/techdocs/src/home/components/TechDocsHome.tsx`. -### 2nd way: custom home page plugin +### 2nd way: Custom home page plugin A custom home page plugin can be built that uses the components extensions DocsCardGrid and DocsTable, exported from @backstage/techdocs. They both take a From 6db5564af60c4a704c476daad80e8aa8a13fdf62 Mon Sep 17 00:00:00 2001 From: Adrian Ke Chongyang <14866712+adrianke77@users.noreply.github.com> Date: Mon, 19 Apr 2021 15:18:01 +0800 Subject: [PATCH 102/262] Update docs/features/techdocs/how-to-guides.md Co-authored-by: Himanshu Mishra <himanshu@orkohunter.net> Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index f387379e06..e1dbe8b494 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -157,5 +157,5 @@ DocsCardGrid and DocsTable, exported from @backstage/techdocs. They both take a array of documentation entities ( have 'backstage.io/techdocs-ref' annotation ) as an 'entities' attribute. -For an reference to the React structure of the default home page, please refer +For a reference to the React structure of the default home page, please refer to `plugins/techdocs/src/home/components/TechDocsCustomHome.tsx`. From 9f7d5662e3002356c06abe40dbfade36473a239c Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" <ftt.adrian.ke@grabtaxi.com> Date: Mon, 19 Apr 2021 16:24:59 +0800 Subject: [PATCH 103/262] update how-to-guides.md Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index e1dbe8b494..1da925ae5a 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -154,8 +154,8 @@ can be found at `plugins/techdocs/src/home/components/TechDocsHome.tsx`. A custom home page plugin can be built that uses the components extensions DocsCardGrid and DocsTable, exported from @backstage/techdocs. They both take a -array of documentation entities ( have 'backstage.io/techdocs-ref' annotation ) -as an 'entities' attribute. +array of documentation entities ( i.e.have a 'backstage.io/techdocs-ref' +annotation ) as an 'entities' attribute. -For a reference to the React structure of the default home page, please refer -to `plugins/techdocs/src/home/components/TechDocsCustomHome.tsx`. +For a reference to the React structure of the default home page, please refer to +`plugins/techdocs/src/home/components/TechDocsCustomHome.tsx`. From cb321bae90356b4eaa8609144e99ae082b2d939a Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" <ftt.adrian.ke@grabtaxi.com> Date: Thu, 22 Apr 2021 11:53:30 +0800 Subject: [PATCH 104/262] change naming from widget to panel Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 18 ++++++----- .../src/home/components/DocsTable.tsx | 6 +++- .../components/TechDocsCustomHome.test.tsx | 10 +++---- .../home/components/TechDocsCustomHome.tsx | 30 +++++++++---------- .../src/home/components/TechDocsHome.tsx | 11 +++---- plugins/techdocs/src/index.ts | 2 +- 6 files changed, 43 insertions(+), 34 deletions(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 1da925ae5a..682051dd83 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -92,7 +92,7 @@ In your main App.tsx: ```tsx import { TechDocsCustomHome, - WidgetType, + PanelType, TechDocsReaderPage, } from '@backstage/plugin-techdocs'; import { Entity } from '@backstage/catalog-model'; @@ -105,17 +105,17 @@ const tabsConfig = [ title: 'Custom Documents Cards 1', description: 'Explore your internal technical ecosystem through documentation.', - // sets maximum height of widget, as CSS maxHeight attribute - widgetMaxHeight: '400px' - widgetType: 'DocsCardGrid' as WidgetType, + panelType: 'DocsCardGrid' as PanelType, + // optional, is applied to a container of the panel (excludes header of panel) + panelCSS: { maxHeight: '400px' }, filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationOne']; }, { title: 'Custom Documents Cards 2', description: 'Explore your internal technical ecosystem through documentation.', - widgetMaxHeight: '400px' - widgetType: 'DocsCardGrid' as WidgetType, + panelType: 'DocsCardGrid' as PanelType, + panelCSS: { maxHeight: '400px' }, filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationTwo']; }, ], @@ -127,7 +127,7 @@ const tabsConfig = [ title: 'Overview', description: 'Explore your internal technical ecosystem through documentation.', - widgetType: 'DocsTable' as WidgetType, + panelType: 'DocsTable' as PanelType, filterPredicate: () => true, }, ], @@ -150,6 +150,10 @@ const routes = ( An example of tabsConfig that corresponds to the default documentation home page can be found at `plugins/techdocs/src/home/components/TechDocsHome.tsx`. +Currently `panelType` has DocsCardGrid and DocsTable available. We currently +recommend that DocsCardGrid can be optionally vertically stacked by setting a +maxHeight using `panelCSS`, and DocsTable to be in a tab by itself. + ### 2nd way: Custom home page plugin A custom home page plugin can be built that uses the components extensions diff --git a/plugins/techdocs/src/home/components/DocsTable.tsx b/plugins/techdocs/src/home/components/DocsTable.tsx index 341ff852be..cb0a3b4329 100644 --- a/plugins/techdocs/src/home/components/DocsTable.tsx +++ b/plugins/techdocs/src/home/components/DocsTable.tsx @@ -90,7 +90,11 @@ export const DocsTable = ({ <> {documents && documents.length > 0 ? ( <Table - options={{ paging: true, pageSize: 20, search: true }} + options={{ + paging: true, + pageSize: 20, + search: true, + }} data={documents} columns={columns} title={ diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx index a7f4d90240..9ee32fef13 100644 --- a/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx +++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.test.tsx @@ -19,7 +19,7 @@ import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp } from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; -import { TechDocsCustomHome, WidgetType } from './TechDocsCustomHome'; +import { TechDocsCustomHome, PanelType } from './TechDocsCustomHome'; describe('TechDocsCustomHome', () => { const catalogApi: Partial<CatalogApi> = { @@ -32,22 +32,22 @@ describe('TechDocsCustomHome', () => { const tabsConfig = [ { label: 'First Tab', - widgets: [ + panels: [ { title: 'First Tab', description: 'First Tab Description', - widgetType: 'DocsCardGrid' as WidgetType, + panelType: 'DocsCardGrid' as PanelType, filterPredicate: () => true, }, ], }, { label: 'Second Tab ', - widgets: [ + panels: [ { title: 'Second Tab', description: 'Second Tab Description', - widgetType: 'DocsTable' as WidgetType, + panelType: 'DocsTable' as PanelType, filterPredicate: () => true, }, ], diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx index 37a9dadddb..ffcb02451b 100644 --- a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx +++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx @@ -37,46 +37,46 @@ import { import { DocsTable } from './DocsTable'; import { DocsCardGrid } from './DocsCardGrid'; -const widgets = { +const panels = { DocsTable: DocsTable, DocsCardGrid: DocsCardGrid, }; -export type WidgetType = 'DocsCardGrid' | 'DocsTable'; +export type PanelType = 'DocsCardGrid' | 'DocsTable'; -export interface WidgetConfig { +export interface PanelConfig { title: string; description: string; - widgetType: WidgetType; - widgetMaxHeight?: string; + panelType: PanelType; + panelCSS?: {}; filterPredicate: (entity: Entity) => boolean; } export interface TabConfig { label: string; - widgets: WidgetConfig[]; + panels: PanelConfig[]; } export type TabsConfig = TabConfig[]; -const CustomWidget = ({ +const CustomPanel = ({ config, entities, index, }: { - config: WidgetConfig; + config: PanelConfig; entities: Entity[]; index: number; }) => { const useStyles = makeStyles({ - widgetContainer: { - maxHeight: config.widgetMaxHeight || 'inherit', + panelContainer: { marginBottom: '2rem', overflow: 'auto', + ...(config.panelCSS ? config.panelCSS : {}), }, }); const classes = useStyles(); - const Widget = widgets[config.widgetType]; + const Panel = panels[config.panelType]; const shownEntities = entities.filter(config.filterPredicate); return ( <> @@ -87,8 +87,8 @@ const CustomWidget = ({ </SupportButton> ) : null} </ContentHeader> - <div className={classes.widgetContainer}> - <Widget entities={shownEntities} /> + <div className={classes.panelContainer}> + <Panel entities={shownEntities} /> </div> </> ); @@ -155,8 +155,8 @@ export const TechDocsCustomHome = ({ }))} /> <Content> - {currentTabConfig.widgets.map((config, index) => ( - <CustomWidget + {currentTabConfig.panels.map((config, index) => ( + <CustomPanel key={index} config={config} entities={!!entities ? entities : []} diff --git a/plugins/techdocs/src/home/components/TechDocsHome.tsx b/plugins/techdocs/src/home/components/TechDocsHome.tsx index 904c759b11..a9641391e2 100644 --- a/plugins/techdocs/src/home/components/TechDocsHome.tsx +++ b/plugins/techdocs/src/home/components/TechDocsHome.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { Entity } from '@backstage/catalog-model'; import { useOwnUser } from '../hooks'; import { isOwnerOf } from '@backstage/plugin-catalog-react'; -import { WidgetType, TechDocsCustomHome } from './TechDocsCustomHome'; +import { PanelType, TechDocsCustomHome } from './TechDocsCustomHome'; export const TechDocsHome = () => { const { value: user } = useOwnUser(); @@ -26,23 +26,24 @@ export const TechDocsHome = () => { const tabsConfig = [ { label: 'Overview', - widgets: [ + panels: [ { title: 'Overview', description: 'Explore your internal technical ecosystem through documentation.', - widgetType: 'DocsCardGrid' as WidgetType, + panelType: 'DocsCardGrid' as PanelType, filterPredicate: () => true, }, ], }, { label: 'Owned', - widgets: [ + panels: [ { title: 'Owned documents', description: 'Access your documentation.', - widgetType: 'DocsTable' as WidgetType, + panelType: 'DocsTable' as PanelType, + paneCSS: { maxHeight: '200px' }, filterPredicate: (entity: Entity) => { if (!user) { return false; diff --git a/plugins/techdocs/src/index.ts b/plugins/techdocs/src/index.ts index f72938e385..b33b91e2c5 100644 --- a/plugins/techdocs/src/index.ts +++ b/plugins/techdocs/src/index.ts @@ -27,4 +27,4 @@ export { export { Router, EmbeddedDocsRouter } from './Router'; export * from './reader'; export * from './api'; -export type { WidgetType } from './home/components/TechDocsCustomHome'; +export type { PanelType } from './home/components/TechDocsCustomHome'; From f5dab83b5972ae9c317a51a7b77ccf1c788b788e Mon Sep 17 00:00:00 2001 From: Adrian Ke Chongyang <14866712+adrianke77@users.noreply.github.com> Date: Fri, 23 Apr 2021 11:00:08 +0800 Subject: [PATCH 105/262] Update docs/features/techdocs/how-to-guides.md Signed-off-by: Eric Peterson <ericpeterson@spotify.com> Co-authored-by: Eric Peterson <iamEAP@users.noreply.github.com> Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 682051dd83..1b19f12b8a 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -100,7 +100,7 @@ import { Entity } from '@backstage/catalog-model'; const tabsConfig = [ { label: 'Custom Tab', - widgets: [ + panels: [ { title: 'Custom Documents Cards 1', description: From 7a3b3b2be6bec8bbc733313e56cc0d396be2c16d Mon Sep 17 00:00:00 2001 From: Adrian Ke Chongyang <14866712+adrianke77@users.noreply.github.com> Date: Fri, 23 Apr 2021 11:00:17 +0800 Subject: [PATCH 106/262] Update docs/features/techdocs/how-to-guides.md Signed-off-by: Eric Peterson <ericpeterson@spotify.com> Co-authored-by: Eric Peterson <iamEAP@users.noreply.github.com> Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 1b19f12b8a..384656ea38 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -122,7 +122,7 @@ const tabsConfig = [ }, { label: 'Overview', - widgets: [ + panels: [ { title: 'Overview', description: From 64ade20227f269f26ad3d4ffa1c20fcf6d223c77 Mon Sep 17 00:00:00 2001 From: Adrian Ke Chongyang <14866712+adrianke77@users.noreply.github.com> Date: Fri, 23 Apr 2021 11:00:30 +0800 Subject: [PATCH 107/262] Update plugins/techdocs/src/home/components/TechDocsHome.tsx Signed-off-by: Eric Peterson <ericpeterson@spotify.com> Co-authored-by: Eric Peterson <iamEAP@users.noreply.github.com> Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- plugins/techdocs/src/home/components/TechDocsHome.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/techdocs/src/home/components/TechDocsHome.tsx b/plugins/techdocs/src/home/components/TechDocsHome.tsx index a9641391e2..ef2749015a 100644 --- a/plugins/techdocs/src/home/components/TechDocsHome.tsx +++ b/plugins/techdocs/src/home/components/TechDocsHome.tsx @@ -43,7 +43,6 @@ export const TechDocsHome = () => { title: 'Owned documents', description: 'Access your documentation.', panelType: 'DocsTable' as PanelType, - paneCSS: { maxHeight: '200px' }, filterPredicate: (entity: Entity) => { if (!user) { return false; From 4666ddb275465dc499d9b9c30d2dbb3546233d4b Mon Sep 17 00:00:00 2001 From: Adrian Ke Chongyang <14866712+adrianke77@users.noreply.github.com> Date: Fri, 23 Apr 2021 11:00:37 +0800 Subject: [PATCH 108/262] Update plugins/techdocs/src/home/components/TechDocsHome.tsx Signed-off-by: Eric Peterson <ericpeterson@spotify.com> Co-authored-by: Eric Peterson <iamEAP@users.noreply.github.com> Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- plugins/techdocs/src/home/components/TechDocsHome.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs/src/home/components/TechDocsHome.tsx b/plugins/techdocs/src/home/components/TechDocsHome.tsx index ef2749015a..72f59d5446 100644 --- a/plugins/techdocs/src/home/components/TechDocsHome.tsx +++ b/plugins/techdocs/src/home/components/TechDocsHome.tsx @@ -37,7 +37,7 @@ export const TechDocsHome = () => { ], }, { - label: 'Owned', + label: 'Owned Documents', panels: [ { title: 'Owned documents', From 7dd94b075056ea9118047d4c66e0285f23e9139c Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" <ftt.adrian.ke@grabtaxi.com> Date: Fri, 23 Apr 2021 11:20:46 +0800 Subject: [PATCH 109/262] add CSSProperties type for panelCSS Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- plugins/techdocs/package.json | 1 + plugins/techdocs/src/home/components/TechDocsCustomHome.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 88b3b6a1df..775e57d00f 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -41,6 +41,7 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", + "@material-ui/styles": "^4.10.0", "react": "^16.13.1", "react-dom": "^16.13.1", "react-router": "6.0.0-beta.0", diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx index ffcb02451b..7230adb29b 100644 --- a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx +++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx @@ -17,7 +17,7 @@ import React, { useState } from 'react'; import { useAsync } from 'react-use'; import { makeStyles } from '@material-ui/core'; - +import { CSSProperties } from '@material-ui/styles'; import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; import { Entity } from '@backstage/catalog-model'; import { @@ -48,7 +48,7 @@ export interface PanelConfig { title: string; description: string; panelType: PanelType; - panelCSS?: {}; + panelCSS?: CSSProperties; filterPredicate: (entity: Entity) => boolean; } From 813a4a04f55752bf273c2dac304f1d1dbd2152f8 Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" <ftt.adrian.ke@grabtaxi.com> Date: Fri, 23 Apr 2021 11:38:09 +0800 Subject: [PATCH 110/262] fix DocsTable rendering of EmptyState Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- docs/features/techdocs/how-to-guides.md | 6 +++--- plugins/techdocs/src/home/components/TechDocsCustomHome.tsx | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 384656ea38..6c64e83a76 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -87,7 +87,7 @@ implementation very soon. ### 1st way: TechDocsCustomHome with a custom configuration -In your main App.tsx: +As an example, in your main App.tsx: ```tsx import { @@ -107,7 +107,7 @@ const tabsConfig = [ 'Explore your internal technical ecosystem through documentation.', panelType: 'DocsCardGrid' as PanelType, // optional, is applied to a container of the panel (excludes header of panel) - panelCSS: { maxHeight: '400px' }, + panelCSS: { maxHeight: '400px', overflow:'auto' }, filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationOne']; }, { @@ -115,7 +115,7 @@ const tabsConfig = [ description: 'Explore your internal technical ecosystem through documentation.', panelType: 'DocsCardGrid' as PanelType, - panelCSS: { maxHeight: '400px' }, + panelCSS: { maxHeight: '400px', overflow:'auto' }, filterPredicate: (entity: Entity) => !!entity.metadata.annotations?.['customCardAnnotationTwo']; }, ], diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx index 7230adb29b..ff9f1bf101 100644 --- a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx +++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx @@ -71,7 +71,6 @@ const CustomPanel = ({ const useStyles = makeStyles({ panelContainer: { marginBottom: '2rem', - overflow: 'auto', ...(config.panelCSS ? config.panelCSS : {}), }, }); From e363f6103ef99b73a5945dd95eee9bc9b344f11b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Apr 2021 04:14:11 +0000 Subject: [PATCH 111/262] chore(deps): bump serialize-error from 8.0.1 to 8.1.0 Bumps [serialize-error](https://github.com/sindresorhus/serialize-error) from 8.0.1 to 8.1.0. - [Release notes](https://github.com/sindresorhus/serialize-error/releases) - [Commits](https://github.com/sindresorhus/serialize-error/compare/v8.0.1...v8.1.0) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index df07058f48..ba1b3bfe73 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23454,9 +23454,9 @@ serialize-error@^2.1.0: integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= serialize-error@^8.0.1: - version "8.0.1" - resolved "https://registry.npmjs.org/serialize-error/-/serialize-error-8.0.1.tgz#7a67f8ecbbf28973b5a954a2852ff9f4eef52d99" - integrity sha512-r5o60rWFS+8/b49DNAbB+GXZA0SpDpuWE758JxDKgRTga05r3U5lwyksE91dYKDhXSmnu36RALj615E6Aj5pSg== + version "8.1.0" + resolved "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz#3a069970c712f78634942ddd50fbbc0eaebe2f67" + integrity sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ== dependencies: type-fest "^0.20.2" From 0b95bc1c6bf96530ff716926bb5a1e5141363d32 Mon Sep 17 00:00:00 2001 From: Brian Fox <brianhfox@gmail.com> Date: Fri, 23 Apr 2021 09:57:39 +0200 Subject: [PATCH 112/262] Align techdocs navigation with microsite Signed-off-by: Brian Fox <brianhfox@gmail.com> --- mkdocs.yml | 153 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 57 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 031fb56059..7826b3221d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,114 +7,153 @@ plugins: nav: - Overview: - What is Backstage?: 'overview/what-is-backstage.md' - - Backstage architecture: 'overview/architecture-overview.md' - - Roadmap: 'overview/roadmap.md' + - Architecture overview: 'overview/architecture-overview.md' + - Project Roadmap: 'overview/roadmap.md' - Vision: 'overview/vision.md' - - The Spotify story: 'overview/background.md' + - The Spotify Story: 'overview/background.md' - Strategies for adopting: 'overview/adopting.md' + - Stability Index: 'overview/stability-index.md' - Logo assets: 'overview/logos.md' - - Getting started: + - Getting Started: - Getting Started: 'getting-started/index.md' + - Create an App: 'getting-started/create-an-app.md' - Running Backstage locally: 'getting-started/running-backstage-locally.md' + - App configuration: + - Configuring App with plugins: 'getting-started/configure-app-with-plugins.md' + - Customize the look-and-feel of your App: 'getting-started/app-custom-theme.md' + - Keeping Backstage Updated: 'getting-started/keeping-backstage-updated.md' + - Key Concepts: 'getting-started/concepts.md' - Contributors: 'getting-started/contributors.md' - - Demo deployment: https://backstage-demo.roadie.io - - Production deployments: - - Create an App: 'getting-started/create-an-app.md' - - App configuration: - - Configuring App with plugins: 'getting-started/configure-app-with-plugins.md' - - Customize the look-and-feel of your App: 'getting-started/app-custom-theme.md' - - Deployment scenarios: - - Docker: 'getting-started/deployment-docker.md' - - Kubernetes: 'getting-started/deployment-k8s.md' - - Kubernetes and Helm: 'getting-started/deployment-helm.md' - - Other: 'getting-started/deployment-other.md' - - Features: + - CLI: + - Overview: 'cli/index.md' + - Commands: 'cli/commands.md' + - Core Features: - Software Catalog: - Overview: 'features/software-catalog/index.md' - - Installation: 'features/software-catalog/installation.md' - - Configuration: 'features/software-catalog/configuration.md' - - System model: 'features/software-catalog/system-model.md' + - Installing in your Backstage App: 'features/software-catalog/installation.md' + - Catalog Configuration: 'features/software-catalog/configuration.md' + - System Model: 'features/software-catalog/system-model.md' - YAML File Format: 'features/software-catalog/descriptor-format.md' - Entity References: 'features/software-catalog/references.md' - Well-known Annotations: 'features/software-catalog/well-known-annotations.md' + - Well-known Relations: 'features/software-catalog/well-known-relations.md' - Extending the model: 'features/software-catalog/extending-the-model.md' - External integrations: 'features/software-catalog/external-integrations.md' - API: 'features/software-catalog/api.md' - - Software creation templates: + - Kubernetes: + - Overview: 'features/kubernetes/index.md' + - Installation: 'features/kubernetes/installation.md' + - Configuration: 'features/kubernetes/configuration.md' + - Troubleshooting: 'features/kubernetes/troubleshooting.md' + - Software Templates: - Overview: 'features/software-templates/index.md' - - Installation: 'features/software-templates/installation.md' - - Adding templates: 'features/software-templates/adding-templates.md' - - Extending the Scaffolder: - - Overview: 'features/software-templates/extending/index.md' - - Create your own Templater: 'features/software-templates/extending/create-your-own-templater.md' - - Create your own Publisher: 'features/software-templates/extending/create-your-own-publisher.md' - - Create your own Preparer: 'features/software-templates/extending/create-your-own-preparer.md' + - Installing in your Backstage App: 'features/software-templates/installation.md' + - Adding your own Templates: 'features/software-templates/adding-templates.md' + - Writing Templates: 'features/software-templates/writing-templates.md' + - Builtin Actions: 'features/software-templates/builtin-actions.md' + - Writing Custom Actions: 'features/software-templates/writing-custom-actions.md' + - Writing Templates (Legacy): 'features/software-templates/legacy.md' - Backstage Search: - Overview: 'features/search/README.md' - - Architecture: 'features/search/architecture.md' + - Search Architecture: 'features/search/architecture.md' - TechDocs: - Overview: 'features/techdocs/README.md' - Getting Started: 'features/techdocs/getting-started.md' - Concepts: 'features/techdocs/concepts.md' - TechDocs Architecture: 'features/techdocs/architecture.md' - Creating and Publishing Documentation: 'features/techdocs/creating-and-publishing.md' - - Configuration: 'features/techdocs/configuration.md' + - TechDocs Configuration Options: 'features/techdocs/configuration.md' - Using Cloud Storage: 'features/techdocs/using-cloud-storage.md' + - Configuring CI/CD to generate and publish TechDocs sites: 'features/techdocs/configuring-ci-cd.md' - HOW TO guides: 'features/techdocs/how-to-guides.md' - Troubleshooting: 'features/techdocs/troubleshooting.md' - FAQ: 'features/techdocs/FAQ.md' - - Kubernetes: - - Overview: 'features/kubernetes/index.md' - Integrations: + - Overview: 'integrations/index.md' + - Azure DevOps: + - Locations: 'integrations/azure/locations.md' + - Bitbucket: + - Locations: 'integrations/bitbucket/locations.md' + - Discovery: 'integrations/bitbucket/discovery.md' + - Datadog: + - Installation: 'integrations/datadog-rum/installation.md' - GitHub: + - Locations: 'integrations/github/locations.md' + - Discovery: 'integrations/github/discovery.md' - Org Data: 'integrations/github/org.md' - - LDAP: - - Org Data: 'integrations/ldap/org.md' + - GitLab: + - Locations: 'integrations/gitlab/locations.md' - Google Analytics: - Installation: 'integrations/google-analytics/installation.md' + - Google GCS: + - Locations: 'integrations/google-cloud-storage/locations.md' + - LDAP: + - Org Data: 'integrations/ldap/org.md' - Plugins: - - Overview: 'plugins/index.md' + - Intro to plugins: 'plugins/index.md' - Existing plugins: 'plugins/existing-plugins.md' - - Creating a new plugin: 'plugins/create-a-plugin.md' - - Developing a plugin: 'plugins/plugin-development.md' + - Create a Backstage Plugin: 'plugins/create-a-plugin.md' + - Plugin Development: 'plugins/plugin-development.md' - Structure of a plugin: 'plugins/structure-of-a-plugin.md' + - Plugin Development: 'plugins/plugin-development.md' + - Integrate into the Service Catalog: 'plugins/integrating-plugin-into-service-catalog.md' - Composability System Migration: 'plugins/composability.md' - Backends and APIs: - Proxying: 'plugins/proxying.md' - - Backstage backend plugin: 'plugins/backend-plugin.md' + - Backend plugin: 'plugins/backend-plugin.md' - Call existing API: 'plugins/call-existing-api.md' + - GitHub Apps for Backend Authentication: 'plugins/github-apps.md' - Testing: - - Overview: 'plugins/testing.md' + - Testing with Jest: 'plugins/testing.md' - Publishing: - - Open source and npm: 'plugins/publishing.md' - - Private/internal (non-open source): 'plugins/publish-private.md' + - Publishing: 'plugins/publishing.md' + - Publish private: 'plugins/publish-private.md' + - Add to Marketplace: 'plugins/add-to-marketplace.md' - Observability: 'plugins/observability.md' - Configuration: - - Overview: 'conf/index.md' - - Reading Configuration: 'conf/reading.md' - - Writing Configuration: 'conf/writing.md' - - Defining Configuration: 'conf/defining.md' + - Static Configuration in Backstage: 'conf/index.md' + - Reading Backstage Configuration: 'conf/reading.md' + - Writing Backstage Configuration: 'conf/writing.md' + - Defining Configuration for your Plugin: 'conf/defining.md' - Authentication and identity: - - Overview: 'auth/index.md' - - Add auth provider: 'auth/add-auth-provider.md' + - Adding Authentication: 'auth/index.md' + - Included providers: + - Auth0: 'auth/auth0/provider.md' + - Azure: 'auth/microsoft/provider.md' + - GitHub: 'auth/github/provider.md' + - GitLab: 'auth/gitlab/provider.md' + - Google: 'auth/google/provider.md' + - Okta: 'auth/okta/provider.md' + - OneLogin: 'auth/onelogin/provider.md' + - Adding authentication providers: 'auth/add-auth-provider.md' + - Using authentication and identity: 'auth/using-auth.md' - Auth backend: 'auth/auth-backend.md' - - Auth backend class structure: 'auth/auth-backend-classes.md' - - OAuth: 'auth/oauth.md' + - OAuth and OpenID Connect: 'auth/oauth.md' + - Auth backend classes: 'auth/auth-backend-classes.md' - Glossary: 'auth/glossary.md' + - Deployment: + - Deploying Backstage: 'deployment/index.md' + - Docker: 'deployment/docker.md' + - Kubernetes: 'deployment/k8s.md' + - Helm: 'deployment/helm.md' + - Heroku: 'deployment/heroku.md' - Designing for Backstage: - - Backstage Design Language System (DLS): 'dls/design.md' - - Storybook -- reusable UI components: 'http://backstage.io/storybook' + - Design: 'dls/design.md' - Contributing to Storybook: 'dls/contributing-to-storybook.md' - - Figma resources: 'dls/figma.md' + - Figma: 'dls/figma.md' - API references: - - TypeScript APIs: - - Utilities: 'api/utility-apis.md' + - TypeScript API: + - Utility APIs: 'api/utility-apis.md' + - reference/utility-apis/README: 'reference/utility-apis/README.md' - createPlugin: 'reference/createPlugin.md' - - createPlugin-feature-flags: 'reference/createPlugin-feature-flags.md' + - createPlugin -feature flags: 'reference/createPlugin-feature-flags.md' - Backend APIs: - Backend: 'api/backend.md' - Tutorials: - - Overview: 'tutorials/index.md' + - Future developer journey: 'tutorials/journey.md' + - Monorepo App Setup With Authentication: 'tutorials/quickstart-app-auth.md' + - Adding Custom Plugin to Existing Monorepo App: 'tutorials/quickstart-app-plugin.md' + - Switching Backstage from SQLite to PostgreSQL: 'tutorials/switching-sqlite-postgres.md' - Architecture Decision Records (ADRs): - Overview: 'architecture-decisions/index.md' - ADR001 - Architecture Decision Record (ADR) log: 'architecture-decisions/adr001-add-adr-log.md' @@ -129,7 +168,7 @@ nav: - ADR010 - Luxon Date Library: 'architecture-decisions/adr010-luxon-date-library.md' - ADR011 - Plugin Package Structure: 'architecture-decisions/adr011-plugin-package-structure.md' - Support: - - 'support/support.md' - - 'support/project-structure.md' + - Support and community: 'support/support.md' + - Backstage Project Structure: 'support/project-structure.md' - Glossary: glossary.md - FAQ: FAQ.md From a3a171ccd2a1db14fcd22dae6daeca5de53ea193 Mon Sep 17 00:00:00 2001 From: Brian Fox <brianhfox@gmail.com> Date: Fri, 23 Apr 2021 09:31:00 +0200 Subject: [PATCH 113/262] Microsite nav - Alphabetic order please Signed-off-by: Brian Fox <brianhfox@gmail.com> --- microsite/sidebars.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/microsite/sidebars.json b/microsite/sidebars.json index e2a57bd426..c7b049a53e 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -135,13 +135,13 @@ }, { "type": "subcategory", - "label": "LDAP", - "ids": ["integrations/ldap/org"] + "label": "Google GCS", + "ids": ["integrations/google-cloud-storage/locations"] }, { "type": "subcategory", - "label": "Google GCS", - "ids": ["integrations/google-cloud-storage/locations"] + "label": "LDAP", + "ids": ["integrations/ldap/org"] } ], "Plugins": [ From 5652f4eee5b94c5522cb69cf4d643bfd57ffa441 Mon Sep 17 00:00:00 2001 From: Brian Fox <brianhfox@gmail.com> Date: Fri, 23 Apr 2021 09:31:35 +0200 Subject: [PATCH 114/262] Fix broken link in Software Templates -> Installation Signed-off-by: Brian Fox <brianhfox@gmail.com> --- docs/features/software-templates/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index 105b7e5f96..7d42c71af9 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -265,7 +265,7 @@ the templates at [localhost:3000/create](http://localhost:3000/create) now! Software Templates use [Cookiecutter](https://github.com/cookiecutter/cookiecutter) as templating library. By default it will use the -[spotify/backstage-cookiecutter](<[spotify/backstage-cookiecutter](https://github.com/backstage/backstage/blob/37e35b910afc7d1270855aed0ec4718aba366c91/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile)>) +[spotify/backstage-cookiecutter](https://github.com/backstage/backstage/blob/37e35b910afc7d1270855aed0ec4718aba366c91/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile) docker image. If you are running backstage from a Docker container and you want to avoid From f09f6a166bd1acd9b2026af18ef827d51a3ca893 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 12:41:53 +0200 Subject: [PATCH 115/262] Use interface and not implementation in ApiRef<T> Closes #4404 Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/swift-waves-sleep.md | 12 + plugins/techdocs/dev/api.ts | 8 +- plugins/techdocs/src/api.ts | 236 +---------------- .../src/{api.test.ts => client.test.ts} | 8 +- plugins/techdocs/src/client.ts | 244 ++++++++++++++++++ plugins/techdocs/src/index.ts | 17 +- plugins/techdocs/src/plugin.ts | 22 +- plugins/techdocs/src/types.ts | 4 + 8 files changed, 296 insertions(+), 255 deletions(-) create mode 100644 .changeset/swift-waves-sleep.md rename plugins/techdocs/src/{api.test.ts => client.test.ts} (87%) create mode 100644 plugins/techdocs/src/client.ts diff --git a/.changeset/swift-waves-sleep.md b/.changeset/swift-waves-sleep.md new file mode 100644 index 0000000000..831ecc0001 --- /dev/null +++ b/.changeset/swift-waves-sleep.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Make `techdocsStorageApiRef` and `techdocsApiRef` use interfaces instead of the +actual implementation classes. + +This renames the classes `TechDocsApi` to `TechDocsClient` and `TechDocsStorageApi` +to `TechDocsStorageClient` and renames the interfaces `TechDocs` to `TechDocsApi` +and `TechDocsStorage` to `TechDocsStorageApi` to comply the pattern elsewhere in +the project. This also fixes the types returned by some methods on those +interfaces. diff --git a/plugins/techdocs/dev/api.ts b/plugins/techdocs/dev/api.ts index 7acf3c7032..e764bf82bb 100644 --- a/plugins/techdocs/dev/api.ts +++ b/plugins/techdocs/dev/api.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { DiscoveryApi, IdentityApi } from '@backstage/core'; -import { Config } from '@backstage/config'; import { EntityName } from '@backstage/catalog-model'; -import { TechDocsStorage } from '../src/api'; +import { Config } from '@backstage/config'; +import { DiscoveryApi, IdentityApi } from '@backstage/core'; import { NotFoundError } from '@backstage/errors'; +import { TechDocsStorageApi } from '../src/api'; -export class TechDocsDevStorageApi implements TechDocsStorage { +export class TechDocsDevStorageApi implements TechDocsStorageApi { public configApi: Config; public discoveryApi: DiscoveryApi; public identityApi: IdentityApi; diff --git a/plugins/techdocs/src/api.ts b/plugins/techdocs/src/api.ts index 0be530cc08..204cc1b5a8 100644 --- a/plugins/techdocs/src/api.ts +++ b/plugins/techdocs/src/api.ts @@ -14,11 +14,9 @@ * limitations under the License. */ -import { createApiRef, DiscoveryApi, IdentityApi } from '@backstage/core'; -import { Config } from '@backstage/config'; import { EntityName } from '@backstage/catalog-model'; -import { TechDocsMetadata } from './types'; -import { NotFoundError } from '@backstage/errors'; +import { createApiRef } from '@backstage/core'; +import { TechDocsEntityMetadata, TechDocsMetadata } from './types'; export const techdocsStorageApiRef = createApiRef<TechDocsStorageApi>({ id: 'plugin.techdocs.storageservice', @@ -30,7 +28,10 @@ export const techdocsApiRef = createApiRef<TechDocsApi>({ description: 'Used to make requests towards techdocs API', }); -export interface TechDocsStorage { +export interface TechDocsStorageApi { + getApiOrigin(): Promise<string>; + getStorageUrl(): Promise<string>; + getBuilder(): Promise<string>; getEntityDocs(entityId: EntityName, path: string): Promise<string>; syncEntityDocs(entityId: EntityName): Promise<boolean>; getBaseUrl( @@ -40,227 +41,8 @@ export interface TechDocsStorage { ): Promise<string>; } -export interface TechDocs { +export interface TechDocsApi { + getApiOrigin(): Promise<string>; getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata>; - getEntityMetadata(entityId: EntityName): Promise<string>; -} - -/** - * API to talk to techdocs-backend. - * - * @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API - */ -export class TechDocsApi implements TechDocs { - public configApi: Config; - public discoveryApi: DiscoveryApi; - public identityApi: IdentityApi; - - constructor({ - configApi, - discoveryApi, - identityApi, - }: { - configApi: Config; - discoveryApi: DiscoveryApi; - identityApi: IdentityApi; - }) { - this.configApi = configApi; - this.discoveryApi = discoveryApi; - this.identityApi = identityApi; - } - - async getApiOrigin() { - return ( - this.configApi.getOptionalString('techdocs.requestUrl') ?? - (await this.discoveryApi.getBaseUrl('techdocs')) - ); - } - - /** - * Retrieve TechDocs metadata. - * - * When docs are built, we generate a techdocs_metadata.json and store it along with the generated - * static files. It includes necessary data about the docs site. This method requests techdocs-backend - * which retrieves the TechDocs metadata. - * - * @param {EntityName} entityId Object containing entity data like name, namespace, etc. - */ - async getTechDocsMetadata(entityId: EntityName) { - const { kind, namespace, name } = entityId; - - const apiOrigin = await this.getApiOrigin(); - const requestUrl = `${apiOrigin}/metadata/techdocs/${namespace}/${kind}/${name}`; - const token = await this.identityApi.getIdToken(); - - const request = await fetch(`${requestUrl}`, { - headers: token ? { Authorization: `Bearer ${token}` } : {}, - }); - const res = await request.json(); - - return res; - } - - /** - * Retrieve metadata about an entity. - * - * This method requests techdocs-backend which uses the catalog APIs to respond with filtered - * information required here. - * - * @param {EntityName} entityId Object containing entity data like name, namespace, etc. - */ - async getEntityMetadata(entityId: EntityName) { - const { kind, namespace, name } = entityId; - - const apiOrigin = await this.getApiOrigin(); - const requestUrl = `${apiOrigin}/metadata/entity/${namespace}/${kind}/${name}`; - const token = await this.identityApi.getIdToken(); - - const request = await fetch(`${requestUrl}`, { - headers: token ? { Authorization: `Bearer ${token}` } : {}, - }); - const res = await request.json(); - - return res; - } -} - -/** - * API which talks to TechDocs storage to fetch files to render. - * - * @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API - */ -export class TechDocsStorageApi implements TechDocsStorage { - public configApi: Config; - public discoveryApi: DiscoveryApi; - public identityApi: IdentityApi; - - constructor({ - configApi, - discoveryApi, - identityApi, - }: { - configApi: Config; - discoveryApi: DiscoveryApi; - identityApi: IdentityApi; - }) { - this.configApi = configApi; - this.discoveryApi = discoveryApi; - this.identityApi = identityApi; - } - - async getApiOrigin() { - return ( - this.configApi.getOptionalString('techdocs.requestUrl') ?? - (await this.discoveryApi.getBaseUrl('techdocs')) - ); - } - - async getStorageUrl() { - return ( - this.configApi.getOptionalString('techdocs.storageUrl') ?? - `${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs` - ); - } - - async getBuilder() { - return this.configApi.getString('techdocs.builder'); - } - - /** - * Fetch HTML content as text for an individual docs page in an entity's docs site. - * - * @param {EntityName} entityId Object containing entity data like name, namespace, etc. - * @param {string} path The unique path to an individual docs page e.g. overview/what-is-new - * @returns {string} HTML content of the docs page as string - * @throws {Error} Throws error when the page is not found. - */ - async getEntityDocs(entityId: EntityName, path: string) { - const { kind, namespace, name } = entityId; - - const storageUrl = await this.getStorageUrl(); - const url = `${storageUrl}/${namespace}/${kind}/${name}/${path}`; - const token = await this.identityApi.getIdToken(); - - const request = await fetch( - `${url.endsWith('/') ? url : `${url}/`}index.html`, - { - headers: token ? { Authorization: `Bearer ${token}` } : {}, - }, - ); - - let errorMessage = ''; - switch (request.status) { - case 404: - errorMessage = 'Page not found. '; - // path is empty for the home page of an entity's docs site - if (!path) { - errorMessage += - 'This could be because there is no index.md file in the root of the docs directory of this repository.'; - } - throw new NotFoundError(errorMessage); - case 500: - errorMessage = - 'Could not generate documentation or an error in the TechDocs backend. '; - throw new Error(errorMessage); - default: - // Do nothing - break; - } - - return request.text(); - } - - /** - * Check if docs are on the latest version and trigger rebuild if not - * - * @param {EntityName} entityId Object containing entity data like name, namespace, etc. - * @returns {boolean} Whether documents are currently synchronized to newest version - * @throws {Error} Throws error on error from sync endpoint in Techdocs Backend - */ - async syncEntityDocs(entityId: EntityName) { - const { kind, namespace, name } = entityId; - - const apiOrigin = await this.getApiOrigin(); - const url = `${apiOrigin}/sync/${namespace}/${kind}/${name}`; - const token = await this.identityApi.getIdToken(); - let request; - let attempts: number = 0; - // retry if request times out, up to 5 times - // can happen due to docs taking too long to generate - while (!request || (request.status === 408 && attempts < 5)) { - attempts++; - request = await fetch(url, { - headers: token ? { Authorization: `Bearer ${token}` } : {}, - }); - } - - switch (request.status) { - case 404: - throw new NotFoundError((await request.json()).error); - case 200: - case 201: - case 304: - return true; - // for timeout and misc errors, handle without error to allow viewing older docs - // if older docs not available, - // Reader will show 404 error coming from getEntityDocs - case 408: - default: - return false; - } - } - - async getBaseUrl( - oldBaseUrl: string, - entityId: EntityName, - path: string, - ): Promise<string> { - const { kind, namespace, name } = entityId; - - const apiOrigin = await this.getApiOrigin(); - return new URL( - oldBaseUrl, - `${apiOrigin}/static/docs/${namespace}/${kind}/${name}/${path}`, - ).toString(); - } + getEntityMetadata(entityId: EntityName): Promise<TechDocsEntityMetadata>; } diff --git a/plugins/techdocs/src/api.test.ts b/plugins/techdocs/src/client.test.ts similarity index 87% rename from plugins/techdocs/src/api.test.ts rename to plugins/techdocs/src/client.test.ts index 2260cc7d39..e8fc8f042f 100644 --- a/plugins/techdocs/src/api.test.ts +++ b/plugins/techdocs/src/client.test.ts @@ -15,7 +15,7 @@ */ import { Config } from '@backstage/config'; import { UrlPatternDiscovery } from '@backstage/core'; -import { TechDocsStorageApi } from './api'; +import { TechDocsStorageClient } from './client'; const mockEntity = { kind: 'Component', @@ -23,7 +23,7 @@ const mockEntity = { name: 'test-component', }; -describe('TechDocsStorageApi', () => { +describe('TechDocsStorageClient', () => { const mockBaseUrl = 'http://backstage:9191/api/techdocs'; const configApi = { getOptionalString: () => 'http://backstage:9191/api/techdocs', @@ -32,7 +32,7 @@ describe('TechDocsStorageApi', () => { it('should return correct base url based on defined storage', async () => { // @ts-ignore Partial<Config> not assignable to Config. - const storageApi = new TechDocsStorageApi({ configApi, discoveryApi }); + const storageApi = new TechDocsStorageClient({ configApi, discoveryApi }); await expect( storageApi.getBaseUrl('test.js', mockEntity, ''), @@ -43,7 +43,7 @@ describe('TechDocsStorageApi', () => { it('should return base url with correct entity structure', async () => { // @ts-ignore Partial<Config> not assignable to Config. - const storageApi = new TechDocsStorageApi({ configApi, discoveryApi }); + const storageApi = new TechDocsStorageClient({ configApi, discoveryApi }); await expect( storageApi.getBaseUrl('test/', mockEntity, ''), diff --git a/plugins/techdocs/src/client.ts b/plugins/techdocs/src/client.ts new file mode 100644 index 0000000000..245cfb0154 --- /dev/null +++ b/plugins/techdocs/src/client.ts @@ -0,0 +1,244 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { EntityName } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { DiscoveryApi, IdentityApi } from '@backstage/core'; +import { NotFoundError } from '@backstage/errors'; +import { TechDocsApi, TechDocsStorageApi } from './api'; +import { TechDocsEntityMetadata, TechDocsMetadata } from './types'; + +/** + * API to talk to techdocs-backend. + * + * @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API + */ +export class TechDocsClient implements TechDocsApi { + public configApi: Config; + public discoveryApi: DiscoveryApi; + public identityApi: IdentityApi; + + constructor({ + configApi, + discoveryApi, + identityApi, + }: { + configApi: Config; + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + }) { + this.configApi = configApi; + this.discoveryApi = discoveryApi; + this.identityApi = identityApi; + } + + async getApiOrigin(): Promise<string> { + return ( + this.configApi.getOptionalString('techdocs.requestUrl') ?? + (await this.discoveryApi.getBaseUrl('techdocs')) + ); + } + + /** + * Retrieve TechDocs metadata. + * + * When docs are built, we generate a techdocs_metadata.json and store it along with the generated + * static files. It includes necessary data about the docs site. This method requests techdocs-backend + * which retrieves the TechDocs metadata. + * + * @param {EntityName} entityId Object containing entity data like name, namespace, etc. + */ + async getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata> { + const { kind, namespace, name } = entityId; + + const apiOrigin = await this.getApiOrigin(); + const requestUrl = `${apiOrigin}/metadata/techdocs/${namespace}/${kind}/${name}`; + const token = await this.identityApi.getIdToken(); + + const request = await fetch(`${requestUrl}`, { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); + const res = await request.json(); + + return res; + } + + /** + * Retrieve metadata about an entity. + * + * This method requests techdocs-backend which uses the catalog APIs to respond with filtered + * information required here. + * + * @param {EntityName} entityId Object containing entity data like name, namespace, etc. + */ + async getEntityMetadata( + entityId: EntityName, + ): Promise<TechDocsEntityMetadata> { + const { kind, namespace, name } = entityId; + + const apiOrigin = await this.getApiOrigin(); + const requestUrl = `${apiOrigin}/metadata/entity/${namespace}/${kind}/${name}`; + const token = await this.identityApi.getIdToken(); + + const request = await fetch(`${requestUrl}`, { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); + const res = await request.json(); + + return res; + } +} + +/** + * API which talks to TechDocs storage to fetch files to render. + * + * @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API + */ +export class TechDocsStorageClient implements TechDocsStorageApi { + public configApi: Config; + public discoveryApi: DiscoveryApi; + public identityApi: IdentityApi; + + constructor({ + configApi, + discoveryApi, + identityApi, + }: { + configApi: Config; + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + }) { + this.configApi = configApi; + this.discoveryApi = discoveryApi; + this.identityApi = identityApi; + } + + async getApiOrigin(): Promise<string> { + return ( + this.configApi.getOptionalString('techdocs.requestUrl') ?? + (await this.discoveryApi.getBaseUrl('techdocs')) + ); + } + + async getStorageUrl(): Promise<string> { + return ( + this.configApi.getOptionalString('techdocs.storageUrl') ?? + `${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs` + ); + } + + async getBuilder(): Promise<string> { + return this.configApi.getString('techdocs.builder'); + } + + /** + * Fetch HTML content as text for an individual docs page in an entity's docs site. + * + * @param {EntityName} entityId Object containing entity data like name, namespace, etc. + * @param {string} path The unique path to an individual docs page e.g. overview/what-is-new + * @returns {string} HTML content of the docs page as string + * @throws {Error} Throws error when the page is not found. + */ + async getEntityDocs(entityId: EntityName, path: string): Promise<string> { + const { kind, namespace, name } = entityId; + + const storageUrl = await this.getStorageUrl(); + const url = `${storageUrl}/${namespace}/${kind}/${name}/${path}`; + const token = await this.identityApi.getIdToken(); + + const request = await fetch( + `${url.endsWith('/') ? url : `${url}/`}index.html`, + { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }, + ); + + let errorMessage = ''; + switch (request.status) { + case 404: + errorMessage = 'Page not found. '; + // path is empty for the home page of an entity's docs site + if (!path) { + errorMessage += + 'This could be because there is no index.md file in the root of the docs directory of this repository.'; + } + throw new NotFoundError(errorMessage); + case 500: + errorMessage = + 'Could not generate documentation or an error in the TechDocs backend. '; + throw new Error(errorMessage); + default: + // Do nothing + break; + } + + return request.text(); + } + + /** + * Check if docs are on the latest version and trigger rebuild if not + * + * @param {EntityName} entityId Object containing entity data like name, namespace, etc. + * @returns {boolean} Whether documents are currently synchronized to newest version + * @throws {Error} Throws error on error from sync endpoint in Techdocs Backend + */ + async syncEntityDocs(entityId: EntityName): Promise<boolean> { + const { kind, namespace, name } = entityId; + + const apiOrigin = await this.getApiOrigin(); + const url = `${apiOrigin}/sync/${namespace}/${kind}/${name}`; + const token = await this.identityApi.getIdToken(); + let request; + let attempts: number = 0; + // retry if request times out, up to 5 times + // can happen due to docs taking too long to generate + while (!request || (request.status === 408 && attempts < 5)) { + attempts++; + request = await fetch(url, { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); + } + + switch (request.status) { + case 404: + throw new NotFoundError((await request.json()).error); + case 200: + case 201: + case 304: + return true; + // for timeout and misc errors, handle without error to allow viewing older docs + // if older docs not available, + // Reader will show 404 error coming from getEntityDocs + case 408: + default: + return false; + } + } + + async getBaseUrl( + oldBaseUrl: string, + entityId: EntityName, + path: string, + ): Promise<string> { + const { kind, namespace, name } = entityId; + + const apiOrigin = await this.getApiOrigin(); + return new URL( + oldBaseUrl, + `${apiOrigin}/static/docs/${namespace}/${kind}/${name}/${path}`, + ).toString(); + } +} diff --git a/plugins/techdocs/src/index.ts b/plugins/techdocs/src/index.ts index b33b91e2c5..3bdf8bfec1 100644 --- a/plugins/techdocs/src/index.ts +++ b/plugins/techdocs/src/index.ts @@ -14,17 +14,20 @@ * limitations under the License. */ +export * from './api'; +export { techdocsApiRef, techdocsStorageApiRef } from './api'; +export type { TechDocsApi, TechDocsStorageApi } from './api'; +export { TechDocsClient, TechDocsStorageClient } from './client'; +export type { PanelType } from './home/components/TechDocsCustomHome'; export { - techdocsPlugin, - techdocsPlugin as plugin, - TechdocsPage, - EntityTechdocsContent, DocsCardGrid, DocsTable, + EntityTechdocsContent, TechDocsCustomHome, + TechdocsPage, + techdocsPlugin as plugin, + techdocsPlugin, TechDocsReaderPage, } from './plugin'; -export { Router, EmbeddedDocsRouter } from './Router'; export * from './reader'; -export * from './api'; -export type { PanelType } from './home/components/TechDocsCustomHome'; +export { EmbeddedDocsRouter, Router } from './Router'; diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index d9b38a2c76..97dd6f2150 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -30,21 +30,17 @@ */ import { - createPlugin, - createRouteRef, - createApiFactory, configApiRef, + createApiFactory, + createComponentExtension, + createPlugin, + createRoutableExtension, + createRouteRef, discoveryApiRef, identityApiRef, - createRoutableExtension, - createComponentExtension, } from '@backstage/core'; -import { - techdocsStorageApiRef, - TechDocsStorageApi, - techdocsApiRef, - TechDocsApi, -} from './api'; +import { techdocsApiRef, techdocsStorageApiRef } from './api'; +import { TechDocsClient, TechDocsStorageClient } from './client'; export const rootRouteRef = createRouteRef({ path: '', @@ -72,7 +68,7 @@ export const techdocsPlugin = createPlugin({ identityApi: identityApiRef, }, factory: ({ configApi, discoveryApi, identityApi }) => - new TechDocsStorageApi({ + new TechDocsStorageClient({ configApi, discoveryApi, identityApi, @@ -86,7 +82,7 @@ export const techdocsPlugin = createPlugin({ identityApi: identityApiRef, }, factory: ({ configApi, discoveryApi, identityApi }) => - new TechDocsApi({ + new TechDocsClient({ configApi, discoveryApi, identityApi, diff --git a/plugins/techdocs/src/types.ts b/plugins/techdocs/src/types.ts index 36cc4e187b..fb068bee09 100644 --- a/plugins/techdocs/src/types.ts +++ b/plugins/techdocs/src/types.ts @@ -14,7 +14,11 @@ * limitations under the License. */ +import { Entity, Location } from '@backstage/catalog-model'; + export type TechDocsMetadata = { site_name: string; site_description: string; }; + +export type TechDocsEntityMetadata = Entity & { locationMetadata?: Location }; From bf905d9bdeba84c81d7e84e4b506867e662c10ce Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 12:43:28 +0200 Subject: [PATCH 116/262] Comment out datadog configuration Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- app-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index ac59874878..3c4f2d7ea5 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -2,9 +2,9 @@ app: title: Backstage Example App baseUrl: http://localhost:3000 googleAnalyticsTrackingId: # UA-000000-0 - datadogRum: - clientToken: '123456789' - applicationId: qwerty + #datadogRum: + # clientToken: '123456789' + # applicationId: qwerty # site: # datadoghq.eu default = datadoghq.com # env: # optional From a3048a3b7fcebea0394489c1c09ff2e814336bd4 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 13:08:20 +0200 Subject: [PATCH 117/262] Fix some remaining typing issues Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .../src/reader/components/TechDocsPage.test.tsx | 15 +++++++++++++-- .../src/reader/components/TechDocsPage.tsx | 8 ++++---- .../src/reader/transformers/addBaseUrl.test.ts | 7 +++++-- .../src/reader/transformers/addBaseUrl.ts | 4 ++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx index 4b578bef38..52ddd3794e 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx @@ -51,8 +51,19 @@ describe('<TechDocsPage />', () => { }); const techdocsApi: Partial<TechDocsApi> = { - getEntityMetadata: () => Promise.resolve([]), - getTechDocsMetadata: () => Promise.resolve([]), + getEntityMetadata: () => + Promise.resolve({ + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'backstage', + }, + }), + getTechDocsMetadata: () => + Promise.resolve({ + site_name: 'string', + site_description: 'string', + }), }; const techdocsStorageApi: Partial<TechDocsStorageApi> = { getEntityDocs: (): Promise<string> => Promise.resolve('String'), diff --git a/plugins/techdocs/src/reader/components/TechDocsPage.tsx b/plugins/techdocs/src/reader/components/TechDocsPage.tsx index f2635c0dfb..c15f3a6a44 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPage.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ +import { Content, Page, useApi } from '@backstage/core'; import React, { useState } from 'react'; import { useParams } from 'react-router-dom'; -import { Content, Page, useApi } from '@backstage/core'; -import { Reader } from './Reader'; import { useAsync } from 'react-use'; -import { TechDocsPageHeader } from './TechDocsPageHeader'; import { techdocsApiRef } from '../../api'; +import { Reader } from './Reader'; +import { TechDocsPageHeader } from './TechDocsPageHeader'; export const TechDocsPage = () => { const [documentReady, setDocumentReady] = useState<boolean>(false); @@ -33,7 +33,7 @@ export const TechDocsPage = () => { return techdocsApi.getTechDocsMetadata({ kind, namespace, name }); } - return Promise.resolve({ loading: true }); + return Promise.resolve(undefined); }, [kind, namespace, name, techdocsApi, documentReady]); const entityMetadataRequest = useAsync(() => { diff --git a/plugins/techdocs/src/reader/transformers/addBaseUrl.test.ts b/plugins/techdocs/src/reader/transformers/addBaseUrl.test.ts index 5ba86e42ca..4311de5dae 100644 --- a/plugins/techdocs/src/reader/transformers/addBaseUrl.test.ts +++ b/plugins/techdocs/src/reader/transformers/addBaseUrl.test.ts @@ -16,14 +16,17 @@ import { createTestShadowDom } from '../../test-utils'; import { addBaseUrl } from '../transformers'; -import { TechDocsStorage } from '../../api'; +import { TechDocsStorageApi } from '../../api'; const DOC_STORAGE_URL = 'https://example-host.storage.googleapis.com'; -const techdocsStorageApi: TechDocsStorage = { +const techdocsStorageApi: TechDocsStorageApi = { getBaseUrl: jest.fn(() => Promise.resolve(DOC_STORAGE_URL)), getEntityDocs: () => new Promise(resolve => resolve('yes!')), syncEntityDocs: () => new Promise(resolve => resolve(true)), + getApiOrigin: jest.fn(), + getBuilder: jest.fn(), + getStorageUrl: jest.fn(), }; const fixture = ` diff --git a/plugins/techdocs/src/reader/transformers/addBaseUrl.ts b/plugins/techdocs/src/reader/transformers/addBaseUrl.ts index 2872ad36cc..17070dcfe0 100644 --- a/plugins/techdocs/src/reader/transformers/addBaseUrl.ts +++ b/plugins/techdocs/src/reader/transformers/addBaseUrl.ts @@ -15,10 +15,10 @@ */ import { EntityName } from '@backstage/catalog-model'; import type { Transformer } from './index'; -import { TechDocsStorage } from '../../api'; +import { TechDocsStorageApi } from '../../api'; type AddBaseUrlOptions = { - techdocsStorageApi: TechDocsStorage; + techdocsStorageApi: TechDocsStorageApi; entityId: EntityName; path: string; }; From 21fddf45244e9a335411627fdbc68cac9250a9b7 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Thu, 22 Apr 2021 15:51:55 +0200 Subject: [PATCH 118/262] Rename changeset Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .../{swift-waves-sleep.md => techdocs-swift-waves-sleep.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{swift-waves-sleep.md => techdocs-swift-waves-sleep.md} (100%) diff --git a/.changeset/swift-waves-sleep.md b/.changeset/techdocs-swift-waves-sleep.md similarity index 100% rename from .changeset/swift-waves-sleep.md rename to .changeset/techdocs-swift-waves-sleep.md From 92cc589201170b05689d0c310132e3448b8b9602 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Fri, 23 Apr 2021 13:16:10 +0200 Subject: [PATCH 119/262] Remove duplicate @backstage/test-utils dependency Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- plugins/techdocs/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index e526f028d5..7bde151663 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -35,7 +35,6 @@ "@backstage/catalog-model": "^0.7.7", "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/test-utils": "^0.1.9", "@backstage/theme": "^0.2.6", "@backstage/errors": "^0.1.1", "@material-ui/core": "^4.11.0", From 38f076c0dffccfa0619de77451326fcc4f6fc4ff Mon Sep 17 00:00:00 2001 From: Eric Peterson <ericpeterson@spotify.com> Date: Fri, 23 Apr 2021 14:34:33 +0200 Subject: [PATCH 120/262] Tweak search code ownership. Signed-off-by: Eric Peterson <ericpeterson@spotify.com> --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 803ebd6445..b07519824b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,6 +16,8 @@ /plugins/search-* @backstage/techdocs-core /plugins/techdocs @backstage/techdocs-core /plugins/techdocs-backend @backstage/techdocs-core +/packages/search-common @backstage/techdocs-core /packages/techdocs-common @backstage/techdocs-core /.changeset/cost-insights-* @backstage/silver-lining +/.changeset/search-* @backstage/techdocs-core /.changeset/techdocs-* @backstage/techdocs-core From cdda9c671d500c26a58759d276d3cd9b4591a6ac Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Fri, 23 Apr 2021 15:03:32 +0200 Subject: [PATCH 121/262] move refresh loop to builder and use configured refreshInterval Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- packages/backend/src/plugins/search.ts | 7 +--- .../search-backend-node/src/IndexBuilder.ts | 37 ++++++++++--------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index a980661c85..da7ee193b4 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { useHotCleanup } from '@backstage/backend-common'; import { createRouter } from '@backstage/plugin-search-backend'; import { IndexBuilder, @@ -35,11 +34,7 @@ export default async function createPlugin({ collator: new DefaultCatalogCollator(discovery), }); - // TODO: Move refresh loop logic into the builder. - const timerId = setInterval(() => { - indexBuilder.build(); - }, 60000); - useHotCleanup(module, () => clearInterval(timerId)); + indexBuilder.build(); return await createRouter({ engine: indexBuilder.getSearchEngine(), diff --git a/plugins/search-backend-node/src/IndexBuilder.ts b/plugins/search-backend-node/src/IndexBuilder.ts index 0f5a287037..199cb7f923 100644 --- a/plugins/search-backend-node/src/IndexBuilder.ts +++ b/plugins/search-backend-node/src/IndexBuilder.ts @@ -100,28 +100,31 @@ export class IndexBuilder { async build() { return Promise.all( Object.keys(this.collators).map(async type => { - const decorators: DocumentDecorator[] = ( - this.decorators['*'] || [] - ).concat(this.decorators[type] || []); + setInterval(async () => { + const decorators: DocumentDecorator[] = ( + this.decorators['*'] || [] + ).concat(this.decorators[type] || []); - this.logger.info( - `Collating documents for ${type} via ${this.collators[type].collate.constructor.name}`, - ); - let documents = await this.collators[type].collate.execute(); - for (let i = 0; i < decorators.length; i++) { this.logger.info( - `Decorating ${type} documents via ${decorators[i].constructor.name}`, + `Collating documents for ${type} via ${this.collators[type].collate.constructor.name}`, ); - documents = await decorators[i].execute(documents); - } + let documents = await this.collators[type].collate.execute(); + for (let i = 0; i < decorators.length; i++) { + this.logger.info( + `Decorating ${type} documents via ${decorators[i].constructor.name}`, + ); + documents = await decorators[i].execute(documents); + } - if (!documents || documents.length === 0) { - this.logger.info(`No documents for type "${type}" to index`); - return; - } + if (!documents || documents.length === 0) { + this.logger.info(`No documents for type "${type}" to index`); + return; + } - // pushing documents to index to a configured search engine. - this.searchEngine.index(type, documents); + // pushing documents to index to a configured search engine. + this.searchEngine.index(type, documents); + // refreshInterval configured in seconds, setInterval want milliseconds + }, this.collators[type].refreshInterval * 1000); }), ); } From f5ba99d61c5acc77b2bc7b6cc0dad0d2a6796993 Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Fri, 23 Apr 2021 15:07:12 +0200 Subject: [PATCH 122/262] add changeset Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- .changeset/odd-ads-invite.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/odd-ads-invite.md diff --git a/.changeset/odd-ads-invite.md b/.changeset/odd-ads-invite.md new file mode 100644 index 0000000000..d487df47d3 --- /dev/null +++ b/.changeset/odd-ads-invite.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-node': patch +--- + +Moved refresh loop to builder and use configured refreshInterval for each collator From 23769512a393445391f020b676ee5941ffbedcd6 Mon Sep 17 00:00:00 2001 From: Dominik Henneke <dominik.henneke@sda-se.com> Date: Fri, 23 Apr 2021 15:03:30 +0200 Subject: [PATCH 123/262] Support anyOf schemas in the scaffolder template Signed-off-by: Dominik Henneke <dominik.henneke@sda-se.com> --- .changeset/tough-planes-jump.md | 5 + .../MultistepJsonForm/schema.test.ts | 120 ++++++++++++++++++ .../components/MultistepJsonForm/schema.ts | 35 +++-- 3 files changed, 146 insertions(+), 14 deletions(-) create mode 100644 .changeset/tough-planes-jump.md diff --git a/.changeset/tough-planes-jump.md b/.changeset/tough-planes-jump.md new file mode 100644 index 0000000000..a30315e9e4 --- /dev/null +++ b/.changeset/tough-planes-jump.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Support anyOf schemas in the scaffolder template diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts index b83725c2bb..edfde0ea90 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts @@ -70,4 +70,124 @@ describe('transformSchemaToProps', () => { uiSchema: expectedUiSchema, }); }); + + it('transforms schema with anyOf fields', () => { + const inputSchema = { + type: 'object', + anyOf: [ + { + properties: { + field3: { + type: 'string', + default: 'Value 1', + 'ui:readonly': true, + }, + }, + }, + { + properties: { + field3: { + type: 'string', + default: 'Value 2', + 'ui:readonly': true, + }, + }, + }, + ], + properties: { + field1: { + type: 'object', + anyOf: [ + { + properties: { + field3: { + type: 'string', + default: 'Value 1', + 'ui:readonly': true, + }, + }, + }, + { + properties: { + field3: { + type: 'string', + default: 'Value 2', + 'ui:readonly': true, + }, + }, + }, + ], + }, + field2: { + type: 'string', + 'ui:derp': 'xerp', + }, + }, + }; + const expectedSchema = { + type: 'object', + anyOf: [ + { + properties: { + field3: { + type: 'string', + default: 'Value 1', + }, + }, + }, + { + properties: { + field3: { + type: 'string', + default: 'Value 2', + }, + }, + }, + ], + properties: { + field1: { + type: 'object', + anyOf: [ + { + properties: { + field3: { + type: 'string', + default: 'Value 1', + }, + }, + }, + { + properties: { + field3: { + type: 'string', + default: 'Value 2', + }, + }, + }, + ], + }, + field2: { + type: 'string', + }, + }, + }; + const expectedUiSchema = { + field3: { + 'ui:readonly': true, + }, + field1: { + field3: { + 'ui:readonly': true, + }, + }, + field2: { + 'ui:derp': 'xerp', + }, + }; + + expect(transformSchemaToProps(inputSchema)).toEqual({ + schema: expectedSchema, + uiSchema: expectedUiSchema, + }); + }); }); diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts index e591589bd8..c189bbf1a7 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts @@ -26,7 +26,7 @@ function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { return; } - const { properties } = schema; + const { properties, anyOf } = schema; for (const propName in schema) { if (!schema.hasOwnProperty(propName)) { @@ -39,22 +39,29 @@ function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { } } - if (!isObject(properties)) { - return; + if (isObject(properties)) { + for (const propName in properties) { + if (!properties.hasOwnProperty(propName)) { + continue; + } + + const schemaNode = properties[propName]; + if (!isObject(schemaNode)) { + continue; + } + const innerUiSchema = {}; + uiSchema[propName] = innerUiSchema; + extractUiSchema(schemaNode, innerUiSchema); + } } - for (const propName in properties) { - if (!properties.hasOwnProperty(propName)) { - continue; + if (Array.isArray(anyOf)) { + for (const schemaNode of anyOf) { + if (!isObject(schemaNode)) { + continue; + } + extractUiSchema(schemaNode, uiSchema); } - - const schemaNode = properties[propName]; - if (!isObject(schemaNode)) { - continue; - } - const innerUiSchema = {}; - uiSchema[propName] = innerUiSchema; - extractUiSchema(schemaNode, innerUiSchema); } } From 6f015b7689694bdbe2e90709b93b675cc66d9715 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 23 Apr 2021 19:38:51 +0200 Subject: [PATCH 124/262] e2e: added read tree tests to add github, gitlab and azure read URLs Signed-off-by: blam <ben@blam.sh> --- cypress/cypress.json | 2 +- cypress/src/integration/integrations.ts | 64 +++++++++++++++++-------- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/cypress/cypress.json b/cypress/cypress.json index 59f7516c47..ebbbe59901 100644 --- a/cypress/cypress.json +++ b/cypress/cypress.json @@ -1,5 +1,5 @@ { - "baseUrl": "http://localhost:3000", + "baseUrl": "http://localhost:7000", "integrationFolder": "./src/integration", "supportFile": "./src/support", "fixturesFolder": "./src/fixures", diff --git a/cypress/src/integration/integrations.ts b/cypress/src/integration/integrations.ts index 839159d34e..5ee077502a 100644 --- a/cypress/src/integration/integrations.ts +++ b/cypress/src/integration/integrations.ts @@ -18,33 +18,59 @@ import 'os'; describe('Integrations', () => { describe('ReadTree', () => { - // it('should work for azure', () => { - // cy.loginAsGuest(); - - // cy.visit('/catalog-import'); - - // cy.get('input[name=url]').type( - // 'https://dev.azure.com/backstage-verification/_git/test-repo?path=%2Fnested%2F*', - // ); - - // cy.contains('Analyze').click(); - // }); - it('should work for github', () => { cy.loginAsGuest(); - cy.visit('/catalog-import'); - - cy.get('input[name=url]').type( - 'https://github.com/backstage-verification/test-repo', - ); - cy.request('/api/catalog/locations', { + cy.request('POST', '/api/catalog/locations', { target: 'https://github.com/backstage-verification/test-repo/blob/main/**/*', type: 'url', }); - cy.contains('Analyze').click(); + cy.visit('/catalog'); + cy.contains('All').click(); + cy.get('table').should('contain', 'github-repo'); + cy.get('table').should('contain', 'github-repo-nested'); + }); + + // it('should work for azure', () => { + // cy.loginAsGuest(); + + // cy.request('POST', '/api/catalog/locations', { + // target: + // 'https://dev.azure.com/backstage-verification/_git/test-repo?path=*', + // type: 'url', + // }); + // }); + + it('should work for gitlab', () => { + cy.loginAsGuest(); + + cy.request('POST', '/api/catalog/locations', { + target: + 'https://gitlab.com/backstage-verification/test-repo/-/tree/master/**/*', + type: 'url', + }); + + cy.visit('/catalog'); + cy.contains('All').click(); + cy.get('table').should('contain', 'gitlab-repo'); + cy.get('table').should('contain', 'gitlab-repo-nested'); + }); + + it('should work for bitbucket', () => { + cy.loginAsGuest(); + + cy.request('POST', '/api/catalog/locations', { + target: + 'https://bitbucket.org/backstage-verification/test-repo/src/master/**/*', + type: 'url', + }); + + cy.visit('/catalog'); + cy.contains('All').click(); + cy.get('table').should('contain', 'bitbucket-repo'); + cy.get('table').should('contain', 'bitbucket-repo-nested'); }); }); }); From 3b3bc4d120feb4d51656451b9f4830e8f10c2068 Mon Sep 17 00:00:00 2001 From: Tim Hansen <timbonicus@gmail.com> Date: Fri, 23 Apr 2021 12:13:13 -0600 Subject: [PATCH 125/262] Add healthcheck to k8s doc Signed-off-by: Tim Hansen <timbonicus@gmail.com> --- docs/deployment/k8s.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/deployment/k8s.md b/docs/deployment/k8s.md index 9dbf447740..81f7150a53 100644 --- a/docs/deployment/k8s.md +++ b/docs/deployment/k8s.md @@ -357,6 +357,14 @@ spec: name: postgres-secrets - secretRef: name: backstage-secrets + readinessProbe: + httpGet: + port: 7000 + path: /healthcheck + livenessProbe: + httpGet: + port: 7000 + path: /healthcheck ``` For production deployments, the `image` reference will usually be a full URL to From ba86f0290d7715e7c1189600fbab7d7f1b92bcc8 Mon Sep 17 00:00:00 2001 From: Tim Hansen <timbonicus@gmail.com> Date: Fri, 23 Apr 2021 12:34:46 -0600 Subject: [PATCH 126/262] Comment health checks with note Signed-off-by: Tim Hansen <timbonicus@gmail.com> --- docs/deployment/k8s.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/deployment/k8s.md b/docs/deployment/k8s.md index 81f7150a53..2c52e0e308 100644 --- a/docs/deployment/k8s.md +++ b/docs/deployment/k8s.md @@ -357,14 +357,16 @@ spec: name: postgres-secrets - secretRef: name: backstage-secrets - readinessProbe: - httpGet: - port: 7000 - path: /healthcheck - livenessProbe: - httpGet: - port: 7000 - path: /healthcheck +# Uncomment if health checks are enabled in your app: +# https://backstage.io/docs/plugins/observability#health-checks +# readinessProbe: +# httpGet: +# port: 7000 +# path: /healthcheck +# livenessProbe: +# httpGet: +# port: 7000 +# path: /healthcheck ``` For production deployments, the `image` reference will usually be a full URL to From e0c9ed759d9e6ef12ce8b04a1fe53ae77b4796f0 Mon Sep 17 00:00:00 2001 From: Phil Kuang <pkuang@factset.com> Date: Fri, 23 Apr 2021 16:18:07 -0400 Subject: [PATCH 127/262] feat(EntityLayout): add 'if' prop to Route component Signed-off-by: Phil Kuang <pkuang@factset.com> --- .changeset/small-ways-hunt.md | 6 ++ .../core/src/components/TabbedLayout/index.ts | 1 + plugins/catalog/package.json | 1 + .../EntityLayout/EntityLayout.test.tsx | 35 ++++++++++ .../components/EntityLayout/EntityLayout.tsx | 67 +++++++++++++++++-- 5 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 .changeset/small-ways-hunt.md diff --git a/.changeset/small-ways-hunt.md b/.changeset/small-ways-hunt.md new file mode 100644 index 0000000000..f0b8dc88cc --- /dev/null +++ b/.changeset/small-ways-hunt.md @@ -0,0 +1,6 @@ +--- +'@backstage/core': patch +'@backstage/plugin-catalog': patch +--- + +Add `if` prop to `EntityLayout.Route` to conditionally render tabs diff --git a/packages/core/src/components/TabbedLayout/index.ts b/packages/core/src/components/TabbedLayout/index.ts index 744b56959e..fe72b199ec 100644 --- a/packages/core/src/components/TabbedLayout/index.ts +++ b/packages/core/src/components/TabbedLayout/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { TabbedLayout } from './TabbedLayout'; +export { RoutedTabs } from './RoutedTabs'; diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index b6b306c260..d87ca5b7d9 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -33,6 +33,7 @@ "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", "@backstage/core": "^0.7.6", + "@backstage/core-api": "^0.2.17", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 7356ccc27b..c5b51b8334 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -101,4 +101,39 @@ describe('EntityLayout', () => { expect(rendered.getByText('tabbed-test-title-2')).toBeInTheDocument(); expect(rendered.queryByText('tabbed-test-content-2')).toBeInTheDocument(); }); + + it('should conditionally render tabs', async () => { + const shouldRenderTab = (e: Entity) => e.metadata.name === 'my-entity'; + const shouldNotRenderTab = (e: Entity) => e.metadata.name === 'some-entity'; + + const rendered = await renderInTestApp( + <ApiProvider apis={mockApis}> + <EntityContext.Provider value={mockEntityData}> + <EntityLayout> + <EntityLayout.Route path="/" title="tabbed-test-title"> + <div>tabbed-test-content</div> + </EntityLayout.Route> + <EntityLayout.Route + path="/some-other-path" + title="tabbed-test-title-2" + if={shouldNotRenderTab} + > + <div>tabbed-test-content-2</div> + </EntityLayout.Route> + <EntityLayout.Route + path="/some-other-other-path" + title="tabbed-test-title-3" + if={shouldRenderTab} + > + <div>tabbed-test-content-3</div> + </EntityLayout.Route> + </EntityLayout> + </EntityContext.Provider> + </ApiProvider>, + ); + + expect(rendered.queryByText('tabbed-test-title')).toBeInTheDocument(); + expect(rendered.queryByText('tabbed-test-title-2')).not.toBeInTheDocument(); + expect(rendered.queryByText('tabbed-test-title-3')).toBeInTheDocument(); + }); }); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 6a9fa38e73..e3a8a89b71 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -26,7 +26,7 @@ import { IconComponent, Page, Progress, - TabbedLayout, + RoutedTabs, } from '@backstage/core'; import { EntityContext, @@ -34,14 +34,70 @@ import { getEntityRelations, useEntityCompoundName, } from '@backstage/plugin-catalog-react'; -import { Box } from '@material-ui/core'; +import { attachComponentData } from '@backstage/core-api'; +import { Box, TabProps } from '@material-ui/core'; import { Alert } from '@material-ui/lab'; -import { default as React, useContext, useState } from 'react'; +import { + default as React, + Children, + Fragment, + isValidElement, + useContext, + useState, +} from 'react'; import { useNavigate } from 'react-router'; import { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu'; import { FavouriteEntity } from '../FavouriteEntity/FavouriteEntity'; import { UnregisterEntityDialog } from '../UnregisterEntityDialog/UnregisterEntityDialog'; +type SubRoute = { + path: string; + title: string; + children: JSX.Element; + if?: (entity: Entity) => boolean; + tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>; +}; + +const Route: (props: SubRoute) => null = () => null; + +// This causes all mount points that are discovered within this route to use the path of the route itself +attachComponentData(Route, 'core.gatherMountPoints', true); + +function createSubRoutesFromChildren( + childrenProps: React.ReactNode, + entity: Entity | undefined, +): SubRoute[] { + // Directly comparing child.type with Route will not work with in + // combination with react-hot-loader in storybook + // https://github.com/gaearon/react-hot-loader/issues/304 + const routeType = ( + <Route path="" title=""> + <div /> + </Route> + ).type; + + return Children.toArray(childrenProps).flatMap(child => { + if (!isValidElement(child)) { + return []; + } + + if (child.type === Fragment) { + return createSubRoutesFromChildren(child.props.children, entity); + } + + if (child.type !== routeType) { + throw new Error('Child of EntityLayout must be an EntityLayout.Route'); + } + + const { path, title, children, if: condition, tabProps } = child.props; + if (condition && entity && !condition(entity)) { + return []; + } + + return [{ path, title, children, tabProps }]; + }); +} + const EntityLayoutTitle = ({ entity, title, @@ -139,6 +195,7 @@ export const EntityLayout = ({ const { kind, namespace, name } = useEntityCompoundName(); const { entity, loading, error } = useContext(EntityContext); + const routes = createSubRoutesFromChildren(children, entity); const { headerTitle, headerType } = headerProps( kind, namespace, @@ -175,7 +232,7 @@ export const EntityLayout = ({ {loading && <Progress />} - {entity && <TabbedLayout>{children}</TabbedLayout>} + {entity && <RoutedTabs routes={routes} />} {error && ( <Content> @@ -192,4 +249,4 @@ export const EntityLayout = ({ ); }; -EntityLayout.Route = TabbedLayout.Route; +EntityLayout.Route = Route; From d47c2628b7c35fb35376727d1cafbf3ef2266aab Mon Sep 17 00:00:00 2001 From: Erik Larsson <erik.larsson@schibsted.com> Date: Sat, 24 Apr 2021 06:51:24 +0200 Subject: [PATCH 128/262] fix: include migrations in code-coverage-backend plugin Signed-off-by: Erik Larsson <erik.larsson@schibsted.com> --- .changeset/pink-islands-help.md | 5 +++++ plugins/code-coverage-backend/package.json | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .changeset/pink-islands-help.md diff --git a/.changeset/pink-islands-help.md b/.changeset/pink-islands-help.md new file mode 100644 index 0000000000..c7672f484f --- /dev/null +++ b/.changeset/pink-islands-help.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-coverage-backend': patch +--- + +Include migrations diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 3fc238ce61..3ae76e3fe0 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -44,6 +44,7 @@ "xml2js": "^0.4.23" }, "files": [ - "dist" + "dist", + "migrations/**/*.{js,d.ts}" ] } From f940c3837802434cc7ae45f522a2782357eb5412 Mon Sep 17 00:00:00 2001 From: Taras <tarasm@gmail.com> Date: Sat, 24 Apr 2021 11:23:56 -0400 Subject: [PATCH 129/262] Prevent uncaught exception in download of Techdocs Azure Blob Storage publisher Signed-off-by: Taras <tarasm@gmail.com> --- .../techdocs-common/src/stages/publish/azureBlobStorage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts index 1a823c3d19..f6567abe49 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts @@ -221,7 +221,8 @@ export class AzureBlobStoragePublish implements PublisherBase { .on('end', () => { resolve(Buffer.concat(fileStreamChunks)); }); - }); + }) + .catch(reject); }); } From f4af06ebe339f2aeccce5a84b140b453f643033c Mon Sep 17 00:00:00 2001 From: Taras <tarasm@gmail.com> Date: Sat, 24 Apr 2021 11:34:41 -0400 Subject: [PATCH 130/262] Add changeset Signed-off-by: Taras <tarasm@gmail.com> --- .changeset/six-rocks-allow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/six-rocks-allow.md diff --git a/.changeset/six-rocks-allow.md b/.changeset/six-rocks-allow.md new file mode 100644 index 0000000000..f207654f45 --- /dev/null +++ b/.changeset/six-rocks-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/techdocs-common': patch +--- + +Gracefully handle HTTP request failures in download method of AzureBlobStorage publisher. From 15cbe6815611d15d9d993ff18a2c7491515f26a1 Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" <ftt.adrian.ke@grabtaxi.com> Date: Mon, 26 Apr 2021 11:59:51 +0800 Subject: [PATCH 131/262] fix techdocs landing page table wrong copied link Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com> --- .changeset/techdocs-mean-humans-hammer.md | 5 +++++ plugins/techdocs/src/home/components/DocsTable.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/techdocs-mean-humans-hammer.md diff --git a/.changeset/techdocs-mean-humans-hammer.md b/.changeset/techdocs-mean-humans-hammer.md new file mode 100644 index 0000000000..7697650250 --- /dev/null +++ b/.changeset/techdocs-mean-humans-hammer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Fix TechDocs landing page table wrong copied link diff --git a/plugins/techdocs/src/home/components/DocsTable.tsx b/plugins/techdocs/src/home/components/DocsTable.tsx index cb0a3b4329..5b4a337dea 100644 --- a/plugins/techdocs/src/home/components/DocsTable.tsx +++ b/plugins/techdocs/src/home/components/DocsTable.tsx @@ -76,7 +76,7 @@ export const DocsTable = ({ <Tooltip title="Click to copy documentation link to clipboard"> <IconButton onClick={() => - copyToClipboard(`${window.location.origin}/${row.docsUrl}`) + copyToClipboard(`${window.location.href}/${row.docsUrl}`) } > <ShareIcon /> From 7e5b73d73341c872f4ec1182748a59a0a11b0b13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Apr 2021 04:34:56 +0000 Subject: [PATCH 132/262] chore(deps-dev): bump @types/supertest from 2.0.10 to 2.0.11 Bumps [@types/supertest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/supertest) from 2.0.10 to 2.0.11. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/supertest) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ba1b3bfe73..056f7257db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6727,9 +6727,9 @@ "@types/node" "*" "@types/supertest@^2.0.8": - version "2.0.10" - resolved "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.10.tgz#630d79b4d82c73e043e43ff777a9ca98d457cab7" - integrity sha512-Xt8TbEyZTnD5Xulw95GLMOkmjGICrOQyJ2jqgkSjAUR3mm7pAIzSR0NFBaMcwlzVvlpCjNwbATcWWwjNiZiFrQ== + version "2.0.11" + resolved "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.11.tgz#2e70f69f220bc77b4f660d72c2e1a4231f44a77d" + integrity sha512-uci4Esokrw9qGb9bvhhSVEjd6rkny/dk5PK/Qz4yxKiyppEI+dOPlNrZBahE3i+PoKFYyDxChVXZ/ysS/nrm1Q== dependencies: "@types/superagent" "*" From 43db3d6892115eded93b3e5a655889658554c0a6 Mon Sep 17 00:00:00 2001 From: Martina Iglesias Fernandez <martina@roadie.io> Date: Fri, 23 Apr 2021 19:02:01 +0200 Subject: [PATCH 133/262] [docker] Fix error in docker build Before: ``` Step 7/8 : RUN tar xzf bundle.tar.gz && rm bundle.tar.gz ---> Running in 91107ee4a847 tar (child): bundle.tar.gz: Cannot open: No such file or directory tar (child): Error is not recoverable: exiting now tar: Child returned status 2 tar: Error is not recoverable: exiting now ``` Signed-off-by: Martina Iglesias Fernandez <martina@roadie.io> --- packages/backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index 02aab45609..31231a3a4a 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -22,7 +22,7 @@ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" # Then copy the rest of the backend bundle, along with any other files we might want. -ADD packages/backend/dist/bundle.tar.gz app-config.yaml ./ +COPY packages/backend/dist/bundle.tar.gz app-config.yaml ./ RUN tar xzf bundle.tar.gz && rm bundle.tar.gz CMD ["node", "packages/backend", "--config", "app-config.yaml"] From 8c0184a1c8858e1bc1673438ae44e0f4b94f019e Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 13:37:27 +0200 Subject: [PATCH 134/262] use timers in tests Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- plugins/search-backend-node/src/index.test.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/plugins/search-backend-node/src/index.test.ts b/plugins/search-backend-node/src/index.test.ts index 0c66db372a..86233425e7 100644 --- a/plugins/search-backend-node/src/index.test.ts +++ b/plugins/search-backend-node/src/index.test.ts @@ -54,29 +54,32 @@ describe('IndexBuilder', () => { describe('addCollator', () => { it('adds a collator', async () => { + jest.useFakeTimers(); const collatorSpy = jest.spyOn(testCollator, 'execute'); // Add a collator. testIndexBuilder.addCollator({ type: 'anything', - defaultRefreshIntervalSeconds: 600, + defaultRefreshIntervalSeconds: 6, collator: testCollator, }); // Build the index and ensure the collator was invoked. await testIndexBuilder.build(); + jest.advanceTimersByTime(6000); expect(collatorSpy).toHaveBeenCalled(); }); }); describe('addDecorator', () => { it('adds a decorator', async () => { + jest.useFakeTimers(); const decoratorSpy = jest.spyOn(testDecorator, 'execute'); // Add a collator. testIndexBuilder.addCollator({ type: 'anything', - defaultRefreshIntervalSeconds: 600, + defaultRefreshIntervalSeconds: 6, collator: testCollator, }); @@ -87,10 +90,14 @@ describe('IndexBuilder', () => { // Build the index and ensure the decorator was invoked. await testIndexBuilder.build(); + jest.advanceTimersByTime(6000); + // wait for async decorator execution + await Promise.resolve(); expect(decoratorSpy).toHaveBeenCalled(); }); it('adds a type-specific decorator', async () => { + jest.useFakeTimers(); const expectedType = 'an-expected-type'; const docFixture = { title: 'Test', @@ -105,7 +112,7 @@ describe('IndexBuilder', () => { // Add a collator. testIndexBuilder.addCollator({ type: expectedType, - defaultRefreshIntervalSeconds: 600, + defaultRefreshIntervalSeconds: 6, collator: testCollator, }); @@ -117,6 +124,9 @@ describe('IndexBuilder', () => { // Build the index and ensure the decorator was invoked. await testIndexBuilder.build(); + jest.advanceTimersByTime(6000); + // wait for async decorator execution + await Promise.resolve(); expect(decoratorSpy).toHaveBeenCalled(); expect(decoratorSpy).toHaveBeenCalledWith([docFixture]); }); @@ -136,7 +146,7 @@ describe('IndexBuilder', () => { // Add a collator. testIndexBuilder.addCollator({ type: expectedType, - defaultRefreshIntervalSeconds: 600, + defaultRefreshIntervalSeconds: 6, collator: testCollator, }); @@ -148,6 +158,7 @@ describe('IndexBuilder', () => { // Build the index and ensure the decorator was not invoked. await testIndexBuilder.build(); + jest.advanceTimersByTime(6000); expect(decoratorSpy).not.toHaveBeenCalled(); }); }); From 1c2d8436ab1af5c5424d78b8c5ac04647b3e24fe Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 13:38:15 +0200 Subject: [PATCH 135/262] change log severity from info to debug Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- plugins/search-backend-node/src/IndexBuilder.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/search-backend-node/src/IndexBuilder.ts b/plugins/search-backend-node/src/IndexBuilder.ts index 199cb7f923..0fc881c262 100644 --- a/plugins/search-backend-node/src/IndexBuilder.ts +++ b/plugins/search-backend-node/src/IndexBuilder.ts @@ -105,19 +105,19 @@ export class IndexBuilder { this.decorators['*'] || [] ).concat(this.decorators[type] || []); - this.logger.info( + this.logger.debug( `Collating documents for ${type} via ${this.collators[type].collate.constructor.name}`, ); let documents = await this.collators[type].collate.execute(); for (let i = 0; i < decorators.length; i++) { - this.logger.info( + this.logger.debug( `Decorating ${type} documents via ${decorators[i].constructor.name}`, ); documents = await decorators[i].execute(documents); } if (!documents || documents.length === 0) { - this.logger.info(`No documents for type "${type}" to index`); + this.logger.debug(`No documents for type "${type}" to index`); return; } From d0b69236542f8cf31043c1f48facc74783c428d5 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Mon, 26 Apr 2021 14:05:04 +0200 Subject: [PATCH 136/262] Adjust changeset Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/techdocs-swift-waves-sleep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/techdocs-swift-waves-sleep.md b/.changeset/techdocs-swift-waves-sleep.md index 831ecc0001..79d10931cd 100644 --- a/.changeset/techdocs-swift-waves-sleep.md +++ b/.changeset/techdocs-swift-waves-sleep.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-techdocs': patch +'@backstage/plugin-techdocs': minor --- Make `techdocsStorageApiRef` and `techdocsApiRef` use interfaces instead of the From a3f090b2f391d47c9a36e8aeb53041798a9e02ac Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 21 Apr 2021 19:58:02 +0200 Subject: [PATCH 137/262] catalog-backend: WIP EntityProvider mutation interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: blam <ben@blam.sh> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .../next/DefaultCatalogProcessingEngine.ts | 15 ++-- .../src/next/DefaultLocationStore.ts | 68 ++++++++++--------- .../src/next/NextCatalogBuilder.ts | 3 +- plugins/catalog-backend/src/next/types.ts | 21 +++--- 4 files changed, 55 insertions(+), 52 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 934ab3a1cc..b423b61041 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -19,6 +19,8 @@ import { CatalogProcessingEngine, EntityProvider, EntityMessage, + EntityProviderConnection, + EntityProviderMutation, ProcessingStateManager, CatalogProcessingOrchestrator, } from './types'; @@ -27,8 +29,13 @@ import { Logger } from 'winston'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { Stitcher } from './Stitcher'; +class Connection implements EntityProviderConnection { + constructor(private readonly stateManager: ProcessingStateManager) {} + + async applyMutation(mutation: EntityProviderMutation): Promise<void> {} +} + export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { - private subscriptions: Subscription[] = []; private running: boolean = false; constructor( @@ -41,11 +48,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async start() { for (const provider of this.entityProviders) { - const id = 'databaseProvider'; - const subscription = provider - .entityChange$() - .subscribe({ next: m => this.onNext(id, m) }); - this.subscriptions.push(subscription); + provider.connect(new Connection(this.stateManager)); } this.running = true; diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index b21fe9da02..a6b4adcca4 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -16,24 +16,29 @@ import { LocationSpec, Location } from '@backstage/catalog-model'; import { Database } from '../database'; -import { LocationStore } from './types'; +import { + LocationStore, + EntityProvider, + EntityProviderConnection, +} from './types'; import { v4 as uuidv4 } from 'uuid'; +import { locationSpecToLocationEntity } from './util'; import { ConflictError } from '@backstage/errors'; -import { Observable } from '@backstage/core'; -import ObservableImpl from 'zen-observable'; export type LocationMessage = | { all: Location[] } | { added: Location[]; removed: Location[] }; -export class DefaultLocationStore implements LocationStore { - private subscribers = new Set< - ZenObservable.SubscriptionObserver<LocationMessage> - >(); +export class DefaultLocationStore implements LocationStore, EntityProvider { + private _connection: EntityProviderConnection | undefined; constructor(private readonly db: Database) {} createLocation(spec: LocationSpec): Promise<Location> { + if (!this.connection) { + throw new Error('location store is not initialized'); + } + return this.db.transaction(async tx => { // TODO: id should really be type and target combined and not a uuid. @@ -55,7 +60,11 @@ export class DefaultLocationStore implements LocationStore { target: spec.target, }); - this.notifyAddition(location); + await this.connection.applyMutation({ + type: 'delta', + added: [locationSpecToLocationEntity(location)], + removed: [], + }); return location; }); @@ -75,40 +84,33 @@ export class DefaultLocationStore implements LocationStore { } deleteLocation(id: string): Promise<void> { + if (!this.connection) { + throw new Error('location store is not initialized'); + } + return this.db.transaction(async tx => { const location = await this.db.location(id); if (!location) { throw new ConflictError(`No location found with id: ${id}`); } await this.db.removeLocation(tx, id); - this.notifyDeletion(location); - }); - } - - private notifyAddition(location: Location) { - for (const subscriber of this.subscribers) { - subscriber.next({ - added: [location], - removed: [], - }); - } - } - - private notifyDeletion(location: Location) { - for (const subscriber of this.subscribers) { - subscriber.next({ + await this.connection.applyMutation({ + type: 'delta', added: [], - removed: [location], + removed: [locationSpecToLocationEntity(location)], }); - } + }); } - location$(): Observable<LocationMessage> { - return new ObservableImpl<LocationMessage>(subscriber => { - this.subscribers.add(subscriber); - return () => { - this.subscribers.delete(subscriber); - }; - }); + private get connection(): EntityProviderConnection { + if (!this._connection) { + throw new Error('location store is not initialized'); + } + + return this._connection; + } + + async connect(connection: EntityProviderConnection): Promise<void> { + this._connection = connection; } } diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index c3e0a6bd9c..1796847164 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -272,11 +272,10 @@ export class NextCatalogBuilder { const entitiesCatalog = new NextEntitiesCatalog(dbClient); const locationStore = new DefaultLocationStore(db); - const dbLocationProvider = new DatabaseLocationProvider(locationStore); const stitcher = new Stitcher(dbClient, logger); const processingEngine = new DefaultCatalogProcessingEngine( logger, - [dbLocationProvider], // entityproviders + [locationStore], // entityproviders stateManager, orchestrator, stitcher, diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index 0aeb290224..c3854d631f 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Entity, EntityName, @@ -21,7 +22,6 @@ import { EntityRelationSpec, } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/config'; -import { Observable } from '@backstage/core'; // << nooo export interface LocationEntity { apiVersion: 'backstage.io/v1alpha1'; @@ -45,20 +45,11 @@ export interface LocationService { deleteLocation(id: string): Promise<void>; } -export type EntityMessage = - | { all: Entity[] } - | { added: Entity[]; removed: EntityName[] }; - export interface LocationStore { - // extends EntityProvider createLocation(spec: LocationSpec): Promise<Location>; listLocations(): Promise<Location[]>; getLocation(id: string): Promise<Location>; deleteLocation(id: string): Promise<void>; - - location$(): Observable< - { all: Location[] } | { added: Location[]; removed: Location[] } - >; } export interface CatalogProcessingEngine { @@ -66,8 +57,16 @@ export interface CatalogProcessingEngine { stop(): Promise<void>; } +export type EntityProviderMutation = + | { type: 'full'; entities: Iterable<Entity> } + | { type: 'delta'; added: Iterable<Entity>; removed: Iterable<Entity> }; + +export interface EntityProviderConnection { + applyMutation(mutation: EntityProviderMutation): Promise<void>; +} + export interface EntityProvider { - entityChange$(): Observable<EntityMessage>; + connect(connection: EntityProviderConnection): Promise<void>; } export type EntityProcessingRequest = { From 92a4a4832beccc622f83473328555f03d094bba7 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Thu, 22 Apr 2021 19:41:40 +0200 Subject: [PATCH 138/262] chore: worked on some more of the new catalog migration with fixing deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Co-authored-by: Johan Haals <johan.haals@gmail.com> Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Signed-off-by: blam <ben@blam.sh> --- .../20210302150147_refresh_state.js | 33 ++-- .../next/DefaultCatalogProcessingEngine.ts | 38 +++- .../src/next/DefaultLocationStore.ts | 4 - .../src/next/DefaultProcessingStateManager.ts | 13 +- .../src/next/database/DatabaseManager.ts | 114 +++++++++++ .../DefaultProcessingDatabase.test.ts | 31 +++ .../database/DefaultProcessingDatabase.ts | 180 +++++++++++++++++- .../src/next/database/types.ts | 17 ++ plugins/catalog-backend/src/next/types.ts | 21 +- 9 files changed, 405 insertions(+), 46 deletions(-) create mode 100644 plugins/catalog-backend/src/next/database/DatabaseManager.ts create mode 100644 plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 6abab6270b..14c75b2530 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -59,13 +59,14 @@ exports.up = async function up(knex) { .notNullable() .comment('JSON array containing all errors related to entity'); table - .dateTime('next_update_at') + .dateTime('next_update_at') // TOOD: timezone or change to epoch-millis or similar .notNullable() .comment('Timestamp of when entity should be updated'); table - .dateTime('last_discovery_at') + .dateTime('last_discovery_at') // TOOD: timezone or change to epoch-millis or similar .notNullable() .comment('The last timestamp of which this entity was discovered'); + table.index('entity_id', 'refresh_state_entity_id_idx'); table.index('entity_ref', 'refresh_state_entity_ref_idx'); table.index('next_update_at', 'refresh_state_next_update_at_idx'); }); @@ -94,38 +95,35 @@ exports.up = async function up(knex) { 'Holds edges between refresh state rows. Every time when an entity is processed and emits another entity, an edge will be stored to represent that fact. This is used to detect orphans and ultimately deletions.', ); table - .text('source_special_key') + .text('source_key') .nullable() .comment( 'When the reference source is not an entity, this is an opaque identifier for that source.', ); table - .text('source_entity_id') + .text('source_entity_ref') .nullable() - .references('entity_id') + .references('entity_ref') .inTable('refresh_state') .onDelete('CASCADE') .comment( - 'When the reference source is an entity, this is the ID of the source entity.', + 'When the reference source is an entity, this is the EntityRef of the source entity.', ); table - .text('target_entity_id') + .text('target_entity_ref') .notNullable() - .references('entity_id') + .references('entity_ref') .inTable('refresh_state') .onDelete('CASCADE') - .comment('The ID of the target entity.'); + .comment('The EntityRef of the target entity.'); + table.index('source_key', 'refresh_state_references_source_key_idx'); table.index( - 'source_special_key', - 'refresh_state_references_source_special_key_idx', + 'source_entity_ref', + 'refresh_state_references_source_entity_ref_idx', ); table.index( - 'source_entity_id', - 'refresh_state_references_source_entity_id_idx', - ); - table.index( - 'target_entity_id', - 'refresh_state_references_target_entity_id_idx', + 'target_entity_ref', + 'refresh_state_references_target_entity_ref_idx', ); }); @@ -165,6 +163,7 @@ exports.down = async function down(knex) { table.dropIndex([], 'refresh_state_references_target_entity_id_idx'); }); await knex.schema.alterTable('refresh_state', table => { + table.dropIndex([], 'refresh_state_entity_id_idx'); table.dropIndex([], 'refresh_state_entity_ref_idx'); table.dropIndex([], 'refresh_state_next_update_at_idx'); }); diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index b423b61041..7f49bf832d 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -30,9 +30,31 @@ import { stringifyEntityRef } from '@backstage/catalog-model'; import { Stitcher } from './Stitcher'; class Connection implements EntityProviderConnection { - constructor(private readonly stateManager: ProcessingStateManager) {} + constructor( + private readonly config: { + stateManager: ProcessingStateManager; + id: string; + }, + ) {} - async applyMutation(mutation: EntityProviderMutation): Promise<void> {} + async applyMutation(mutation: EntityProviderMutation): Promise<void> { + if (mutation.type === 'full') { + await this.config.stateManager.replaceProcessingItems({ + id: this.config.id, + type: 'full', + items: mutation.entities, + }); + + return; + } + + await this.config.stateManager.replaceProcessingItems({ + id: this.config.id, + type: 'delta', + added: mutation.added, + removed: mutation.removed, + }); + } } export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { @@ -48,7 +70,9 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async start() { for (const provider of this.entityProviders) { - provider.connect(new Connection(this.stateManager)); + // TODO: this ID should be some form of identifier for the EntityProvider + const id = 'databaseProvider'; + provider.connect(new Connection({ stateManager: this.stateManager, id })); } this.running = true; @@ -57,12 +81,12 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { const { id, entity, - state: intialState, + state: initialState, } = await this.stateManager.getNextProcessingItem(); const result = await this.orchestrator.process({ entity, - state: intialState, + state: initialState, }); for (const error of result.errors) { @@ -95,10 +119,6 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async stop() { this.running = false; - - for (const subscription of this.subscriptions) { - subscription.unsubscribe(); - } } private async onNext(id: string, message: EntityMessage) { diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index a6b4adcca4..dff424b1a9 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -35,10 +35,6 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { constructor(private readonly db: Database) {} createLocation(spec: LocationSpec): Promise<Location> { - if (!this.connection) { - throw new Error('location store is not initialized'); - } - return this.db.transaction(async tx => { // TODO: id should really be type and target combined and not a uuid. diff --git a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts index 91090bc139..d2765c3101 100644 --- a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts +++ b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts @@ -17,14 +17,23 @@ import { ProcessingDatabase, RefreshStateItem } from './database/types'; import { AddProcessingItemRequest, - ProccessingItem, + ProcessingItem, ProcessingItemResult, ProcessingStateManager, + ReplaceProcessingItemsRequest, } from './types'; export class DefaultProcessingStateManager implements ProcessingStateManager { constructor(private readonly db: ProcessingDatabase) {} + replaceProcessingItems( + request: ReplaceProcessingItemsRequest, + ): Promise<void> { + return this.db.transaction(async tx => { + await this.db.replaceUnprocessedEntities(tx, request); + }); + } + async setProcessingItemResult(result: ProcessingItemResult) { return this.db.transaction(async tx => { await this.db.updateProcessedEntity(tx, { @@ -44,7 +53,7 @@ export class DefaultProcessingStateManager implements ProcessingStateManager { }); } - async getNextProcessingItem(): Promise<ProccessingItem> { + async getNextProcessingItem(): Promise<ProcessingItem> { const entities = await new Promise<RefreshStateItem[]>(resolve => this.popFromQueue(resolve), ); diff --git a/plugins/catalog-backend/src/next/database/DatabaseManager.ts b/plugins/catalog-backend/src/next/database/DatabaseManager.ts new file mode 100644 index 0000000000..4c9e45950f --- /dev/null +++ b/plugins/catalog-backend/src/next/database/DatabaseManager.ts @@ -0,0 +1,114 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger, resolvePackagePath } from '@backstage/backend-common'; +import knexFactory, { Knex } from 'knex'; +import { v4 as uuidv4 } from 'uuid'; +import { Logger } from 'winston'; +import { CommonDatabase } from '../../database/CommonDatabase'; +import { Database } from '../../database/types'; +import fs from 'fs-extra'; + +export type CreateDatabaseOptions = { + logger: Logger; +}; + +const defaultOptions: CreateDatabaseOptions = { + logger: getVoidLogger(), +}; + +export class DatabaseManager { + public static async createDatabase( + knex: Knex, + options: Partial<CreateDatabaseOptions> = {}, + ): Promise<Database> { + const allMigrations = resolvePackagePath( + '@backstage/plugin-catalog-backend', + 'migrations', + ); + + const migrationsDir = resolvePackagePath( + '@backstage/plugin-catalog-backend', + 'migrationsv2', + ); + await fs.copy(allMigrations, migrationsDir); + + await knex.migrate.latest({ + directory: migrationsDir, + }); + const { logger } = { ...defaultOptions, ...options }; + return new CommonDatabase(knex, logger); + } + + public static async createInMemoryDatabase(): Promise<Database> { + const knex = await this.createInMemoryDatabaseConnection(); + return await this.createDatabase(knex); + } + + public static async createInMemoryDatabaseConnection(): Promise<Knex> { + const knex = knexFactory({ + client: 'sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }); + + knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { + resource.run('PRAGMA foreign_keys = ON', () => {}); + }); + + return knex; + } + + public static async createTestDatabase(): Promise<Database> { + const knex = await this.createTestDatabaseConnection(); + return await this.createDatabase(knex); + } + + public static async createTestDatabaseConnection(): Promise<Knex> { + const config: Knex.Config<any> = { + /* + client: 'pg', + connection: { + host: 'localhost', + user: 'postgres', + password: 'postgres', + }, + */ + client: 'sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }; + + let knex = knexFactory(config); + if (typeof config.connection !== 'string') { + const tempDbName = `d${uuidv4().replace(/-/g, '')}`; + await knex.raw(`CREATE DATABASE ${tempDbName};`); + knex = knexFactory({ + ...config, + connection: { + ...config.connection, + database: tempDbName, + }, + }); + } + + knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { + resource.run('PRAGMA foreign_keys = ON', () => {}); + }); + + return knex; + } +} diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts new file mode 100644 index 0000000000..fd2e9e6750 --- /dev/null +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { DefaultProcessingDatabase } from './DefaultProcessingDatabase'; +import { DatabaseManager } from './DatabaseManager'; +import { Knex } from 'knex'; + +describe('Default Processing Database', () => { + let db: Knex | undefined; + + beforeEach(async () => { + db = await DatabaseManager.createTestDatabaseConnection(); + await DatabaseManager.createDatabase(db); + }); + + it('should write some stuff', async () => { + await db('refresh_state_referencess').select(); + }); +}); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index cf2d4e121c..b799bd6284 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -15,6 +15,7 @@ */ import { ConflictError, NotFoundError } from '@backstage/errors'; +import { stringifyEntityRef, Entity } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { Transaction } from '../../database'; import lodash from 'lodash'; @@ -24,20 +25,21 @@ import { AddUnprocessedEntitiesOptions, UpdateProcessedEntityOptions, GetProcessableEntitiesResult, + ReplaceUnprocessedEntitiesOptions, } from './types'; import type { Logger } from 'winston'; -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; + import { v4 as uuid } from 'uuid'; export type DbRefreshStateRow = { entity_id: string; entity_ref: string; unprocessed_entity: string; - processed_entity: string; - cache: string; + processed_entity?: string; + cache?: string; next_update_at: string; last_discovery_at: string; // remove? - errors: string; + errors?: string; }; export type DbRelationsRow = { @@ -47,10 +49,10 @@ export type DbRelationsRow = { type: string; }; -export type DbRefreshStateReferences = { - source_special_key?: string; - source_entity_id?: string; - target_entity_id: string; +export type DbRefreshStateReferencesRow = { + source_key?: string; + source_entity_ref?: string; + target_entity_ref: string; }; // The number of items that are sent per batch to the database layer, when @@ -128,6 +130,164 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); } + async replaceUnprocessedEntities( + txOpaque: Transaction, + options: ReplaceUnprocessedEntitiesOptions, + ): Promise<void> { + const tx = txOpaque as Knex.Transaction; + const entityIds = new Array<string>(); + + if (options.type === 'full') { + const oldRefs = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .where({ source_key: options.sourceKey }) + .select('target_entity_ref') + .then(rows => rows.map(r => r.target_entity_ref)); + + const items = options.items.map(entity => ({ + entity, + ref: stringifyEntityRef(entity), + id: uuid(), + })); + + const oldRefsSet = new Set(oldRefs); + const newRefsSet = new Set(items.map(item => item.ref)); + const toAdd = items.filter(item => !oldRefsSet.has(item.ref)); + const toRemove = oldRefs.filter(ref => !newRefsSet.has(ref)); + + if (toRemove.length) { + // TODO(freben): Batch split, to not hit variable limits? + + // get all refs where source = any of the toRemove + // delete all state rows matching any of the toRemove + // revisit the targets of all of those refs + // verify if they have references, otherwise delete from refresh_state + + const current = [...toRemove]; + while (true) { + + tx.withRecursive('r', function refs() { + return tx.select({ }) + .from({ r1: 'refresh_state_references' }) + .where({ source_key: options.sourceKey }) + .whereIn('target_entity_ref', toRemove) + .unionAll(function recurse() { + return tx.select({ }) + .from({ r2: 'refresh_state_references' }) + .whereNotExists() + }) + }) + .select().from('refs'); + + const nextLayerToRemove = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .whereIn('source_entity_ref', toRemove) + .leftOuterJoin('refresh_state_references AS b', function f() { + + }) + + .whereNotNull('b.source_target_ref') + .select('target_entity_ref'); + + await tx<DbRefreshStateRow>('refresh_state') + .whereIn('entity_ref', toRemove) + .delete(); + + const refsThatStillHaveASourcePointingAtThe = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .whereIn('target_entity_ref', nextLayerTargetRefs) + .groupBy('target_entity_ref') + .select('target_entity_ref'); + + } + + + + + if (toAdd.length) { + const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(item => ({ + entity_id: item.id, + entity_ref: item.ref, + unprocessed_entity: JSON.stringify(item.entity), + errors: '', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + })); + const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( + item => ({ + source_key: options.sourceKey, + target_entity_ref: item.ref, + }), + ); + // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense + await tx.batchInsert('refresh_state', state, BATCH_SIZE); + await tx.batchInsert('refresh_state_references', stateReferences, BATCH_SIZE); + } + + + for (const entity of options.items) { + const entityRef = stringifyEntityRef(entity); + await tx<DbRefreshStateRow>('refresh_state') + .insert({ + entity_id: uuid(), + entity_ref: entityRef, + unprocessed_entity: JSON.stringify(entity), + errors: '', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + }) + .onConflict('entity_ref') + .merge(['unprocessed_entity', 'last_discovery_at']); + + const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( + 'refresh_state', + ).where({ entity_ref: entityRef }); + entityIds.push(entityId); + } + const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( + entityId => ({ + source_key: options.sourceKey, + target_entityRef: entityRef, + }), + ); + await tx.batchInsert( + 'refresh_state_references', + referenceRows, + BATCH_SIZE, + ); + return; + } + + for (const entity of options.removed) { + const entityRef = stringifyEntityRef(entity); + const [result] = await tx<DbRefreshStateRow>('refresh_state') + .where({ entity_ref: entityRef }) + .select('entity_id'); + + if (!result) { + this.logger.info( + `Unable to delete entity '${entityRef}', entity does not exist in refresh state`, + ); + continue; + } + + const referenceResults = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + // todo correct key? + .where({ source_entity_id: result.entity_id }) + .select(); + + await tx<DbRefreshStateReferencesRow>('refresh_state_references') + // todo correct key? + .where({ source_entity_id: result.entity_id }) + .delete(); + } + } + async addUnprocessedEntities( txOpaque: Transaction, options: AddUnprocessedEntitiesOptions, @@ -160,11 +320,11 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ? { source_special_key: options.id } : { source_entity_id: options.id }; // copied from update refs - await tx<DbRefreshStateReferences>('refresh_state_references') + await tx<DbRefreshStateReferencesRow>('refresh_state_references') .where(key) .delete(); - const referenceRows: DbRefreshStateReferences[] = entityIds.map( + const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( entityId => ({ ...key, target_entity_id: entityId, diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index 22e9e90c8e..b926676887 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -50,6 +50,19 @@ export type GetProcessableEntitiesResult = { items: RefreshStateItem[]; }; +export type ReplaceUnprocessedEntitiesOptions = + | { + sourceKey: string; + items: Entity[]; + type: 'full'; + } + | { + sourceKey: string; + added: Entity[]; + removed: Entity[]; + type: 'delta'; + }; + export interface ProcessingDatabase { transaction<T>(fn: (tx: Transaction) => Promise<T>): Promise<T>; @@ -58,6 +71,10 @@ export interface ProcessingDatabase { options: AddUnprocessedEntitiesOptions, ): Promise<void>; + replaceUnprocessedEntities( + txOpaque: Transaction, + options: ReplaceUnprocessedEntitiesOptions, + ): Promise<void>; getProcessableEntities( txOpaque: Transaction, request: { processBatchSize: number }, diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index c3854d631f..f8b4de1c41 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -58,8 +58,8 @@ export interface CatalogProcessingEngine { } export type EntityProviderMutation = - | { type: 'full'; entities: Iterable<Entity> } - | { type: 'delta'; added: Iterable<Entity>; removed: Iterable<Entity> }; + | { type: 'full'; entities: Entity[] } + | { type: 'delta'; added: Entity[]; removed: Entity[] }; export interface EntityProviderConnection { applyMutation(mutation: EntityProviderMutation): Promise<void>; @@ -108,14 +108,27 @@ export type AddProcessingItemRequest = { entities: Entity[]; }; -export type ProccessingItem = { +export type ProcessingItem = { id: string; entity: Entity; state: Map<string, JsonObject>; }; +export type ReplaceProcessingItemsRequest = + | { + id: string; + items: Entity[]; + type: 'full'; + } + | { + id: string; + added: Entity[]; + removed: Entity[]; + type: 'delta'; + }; export interface ProcessingStateManager { setProcessingItemResult(result: ProcessingItemResult): Promise<void>; - getNextProcessingItem(): Promise<ProccessingItem>; + getNextProcessingItem(): Promise<ProcessingItem>; addProcessingItems(request: AddProcessingItemRequest): Promise<void>; + replaceProcessingItems(request: ReplaceProcessingItemsRequest): Promise<void>; } From f62db5992f7b9ba66dbcb291a9d88ab1264aca07 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 23 Apr 2021 15:05:04 +0200 Subject: [PATCH 139/262] feat: added support for full sync replace with an awesome sql statement courtesy of @freben MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: Johan Haals <johan.haals@gmail.com> Signed-off-by: blam <ben@blam.sh> --- .../20210302150147_refresh_state.js | 3 + .../DefaultProcessingDatabase.test.ts | 271 +++++++++++++++++- .../database/DefaultProcessingDatabase.ts | 220 +++++++------- 3 files changed, 390 insertions(+), 104 deletions(-) diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 14c75b2530..2afeda02c0 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -94,6 +94,9 @@ exports.up = async function up(knex) { table.comment( 'Holds edges between refresh state rows. Every time when an entity is processed and emits another entity, an edge will be stored to represent that fact. This is used to detect orphans and ultimately deletions.', ); + table + .increments('id') + .comment('Primary key to distinguish unique lines from each other'); table .text('source_key') .nullable() diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index fd2e9e6750..ee04a2baf8 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -16,16 +16,283 @@ // import { DefaultProcessingDatabase } from './DefaultProcessingDatabase'; import { DatabaseManager } from './DatabaseManager'; import { Knex } from 'knex'; +import { + DbRefreshStateReferencesRow, + DbRefreshStateRow, + DefaultProcessingDatabase, +} from './DefaultProcessingDatabase'; + +import { Entity } from '@backstage/catalog-model'; +import * as uuid from 'uuid'; +import { getVoidLogger } from '@backstage/backend-common'; describe('Default Processing Database', () => { let db: Knex | undefined; + let processingDatabase: DefaultProcessingDatabase | undefined; + + const logger = getVoidLogger(); beforeEach(async () => { db = await DatabaseManager.createTestDatabaseConnection(); await DatabaseManager.createDatabase(db); + + processingDatabase = new DefaultProcessingDatabase(db!, logger); }); - it('should write some stuff', async () => { - await db('refresh_state_referencess').select(); + describe('replaceUnprocessedEntities', () => { + const insertRefRow = async (ref: DbRefreshStateReferencesRow) => { + return db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).insert(ref); + }; + + const insertRefreshStateRow = async (ref: DbRefreshStateRow) => { + await db!<DbRefreshStateRow>('refresh_state').insert(ref); + }; + + const createLocations = async (entityRefs: string[]) => { + for (const ref of entityRefs) { + await insertRefreshStateRow({ + entity_id: uuid.v4(), + entity_ref: ref, + unprocessed_entity: '{}', + processed_entity: '{}', + errors: '', + next_update_at: 'now()', + last_discovery_at: 'now()', + }); + } + }; + + it('replaces all existing state correctly for simple dependency chains', async () => { + /* + config -> location:default/root -> location:default/root-1 -> location:default/root-2 + database -> location:default/second -> location:default/root-2 + */ + await createLocations([ + 'location:default/root', + 'location:default/root-1', + 'location:default/root-2', + 'location:default/second', + ]); + + await insertRefRow({ + source_key: 'config', + target_entity_ref: 'location:default/root', + }); + + await insertRefRow({ + source_key: 'database', + target_entity_ref: 'location:default/second', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root', + target_entity_ref: 'location:default/root-1', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root-1', + target_entity_ref: 'location:default/root-2', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/second', + target_entity_ref: 'location:default/root-2', + }); + + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'config', + items: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + for (const ref of ['location:default/root', 'location:default/root-1']) { + expect(currentRefreshState.some(t => t.entity_ref === ref)).toBeFalsy(); + } + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root' && + t.target_entity_ref === 'location:default/root-1', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root-1' && + t.target_entity_ref === 'location:default/root-2', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.target_entity_ref === 'location:default/root-1' && + t.source_key === 'config', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.target_entity_ref === 'location:default/new-root' && + t.source_key === 'config', + ), + ).toBeTruthy(); + }); + + it('should work for more complex chains', async () => { + /* + config -> location:default/root -> location:default/root-1 -> location:default/root-2 + config -> location:default/root -> location:default/root-1a -> location:default/root-2 + */ + await createLocations([ + 'location:default/root', + 'location:default/root-1', + 'location:default/root-2', + 'location:default/root-1a', + ]); + + await insertRefRow({ + source_key: 'config', + target_entity_ref: 'location:default/root', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root', + target_entity_ref: 'location:default/root-1', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root', + target_entity_ref: 'location:default/root-1a', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root-1', + target_entity_ref: 'location:default/root-2', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root-1a', + target_entity_ref: 'location:default/root-2', + }); + + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'config', + items: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + const deletedRefs = [ + 'location:default/root', + 'location:default/root-1', + 'location:default/root-1a', + 'location:default/root-2', + ]; + + for (const ref of deletedRefs) { + expect(currentRefreshState.some(t => t.entity_ref === ref)).toBeFalsy(); + } + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'config' && + t.target_entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'config' && + t.target_entity_ref === 'location:default/root', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root' && + t.target_entity_ref === 'location:default/root-1', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root' && + t.target_entity_ref === 'location:default/root-1a', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root-1' && + t.target_entity_ref === 'location:default/root-2', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root-1a' && + t.target_entity_ref === 'location:default/root-2', + ), + ).toBeFalsy(); + }); }); }); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index b799bd6284..f0c5443651 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -135,7 +135,6 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { options: ReplaceUnprocessedEntitiesOptions, ): Promise<void> { const tx = txOpaque as Knex.Transaction; - const entityIds = new Array<string>(); if (options.type === 'full') { const oldRefs = await tx<DbRefreshStateReferencesRow>( @@ -158,55 +157,95 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (toRemove.length) { // TODO(freben): Batch split, to not hit variable limits? - - // get all refs where source = any of the toRemove - // delete all state rows matching any of the toRemove - // revisit the targets of all of those refs - // verify if they have references, otherwise delete from refresh_state - - const current = [...toRemove]; - while (true) { - - tx.withRecursive('r', function refs() { - return tx.select({ }) - .from({ r1: 'refresh_state_references' }) - .where({ source_key: options.sourceKey }) - .whereIn('target_entity_ref', toRemove) - .unionAll(function recurse() { - return tx.select({ }) - .from({ r2: 'refresh_state_references' }) - .whereNotExists() - }) + /* + WITH RECURSIVE + -- All the refs that can be reached from each individual root + root_reach(id, entity_ref) AS ( + -- Start with all roots + SELECT id, target_entity_ref + FROM refresh_state_references + WHERE source_key IS NOT NULL + UNION + -- For each match, select all children + SELECT root_reach.id, target_entity_ref + FROM refresh_state_references, root_reach + WHERE source_entity_ref = root_reach.entity_ref + ) + -- Start out with our own matching row (see the WHERE that + -- matches on source_key and target_entity_ref below) + SELECT us.entity_ref + FROM refresh_state_references + -- Expand the entire tree that emanates from that row + JOIN root_reach AS us + ON us.id = refresh_state_references.id + -- Expand with all roots that target the same node but + -- aren't ourselves + LEFT OUTER JOIN root_reach AS them + ON them.entity_ref = us.entity_ref + AND them.id != us.id + -- Keep only the matches that had no other rooots + WHERE refresh_state_references.source_key = "R1" + AND refresh_state_references.target_entity_ref = "A" + AND them.id IS NULL; + */ + const removedCount = await tx<DbRefreshStateRow>('refresh_state') + .whereIn('entity_ref', function orphanedEntityRefs(orphans) { + return ( + orphans + // All the refs that can be reached from each individual root + .withRecursive('root_reach', function rootReach(outer) { + // Start with all roots + return outer + .select({ id: 'id', entity_ref: 'target_entity_ref' }) + .from('refresh_state_references') + .whereNotNull('source_key') + .union(function recurse(inner) { + return ( + inner + // For each match, select all children + .select({ + id: 'root_reach.id', + entity_ref: + 'refresh_state_references.target_entity_ref', + }) + .from('refresh_state_references') + .crossJoin('root_reach', { + 'root_reach.entity_ref': + 'refresh_state_references.source_entity_ref', + }) + ); + }); + }) + .select('us.entity_ref') + // Start out with our own matching row + .from('refresh_state_references') + .where('source_key', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + // Expand the entire tree that emanates from that row + .leftJoin({ us: 'root_reach' }, function us() { + this.on('us.id', '=', 'refresh_state_references.id'); + }) + // Expand with all roots that target the same node but aren't ourselves + .leftOuterJoin({ them: 'root_reach' }, function them() { + this.on('them.entity_ref', '=', 'us.entity_ref'); + this.andOn('them.id', '!=', 'us.id'); + }) + // Keep only the matches that had no other rooots + .whereNull('them.id') + ); }) - .select().from('refs'); + .delete(); - const nextLayerToRemove = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .whereIn('source_entity_ref', toRemove) - .leftOuterJoin('refresh_state_references AS b', function f() { - - }) - - .whereNotNull('b.source_target_ref') - .select('target_entity_ref'); - - await tx<DbRefreshStateRow>('refresh_state') - .whereIn('entity_ref', toRemove) - .delete(); - - const refsThatStillHaveASourcePointingAtThe = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .whereIn('target_entity_ref', nextLayerTargetRefs) - .groupBy('target_entity_ref') - .select('target_entity_ref'); + await tx<DbRefreshStateReferencesRow>('refresh_state_references') + .where('source_key', '=', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + .delete(); + console.log( + `REMOVED, ${removedCount} entities: ${JSON.stringify(toRemove)}`, + ); } - - - if (toAdd.length) { const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(item => ({ entity_id: item.id, @@ -224,67 +263,44 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense await tx.batchInsert('refresh_state', state, BATCH_SIZE); - await tx.batchInsert('refresh_state_references', stateReferences, BATCH_SIZE); - } - - - for (const entity of options.items) { - const entityRef = stringifyEntityRef(entity); - await tx<DbRefreshStateRow>('refresh_state') - .insert({ - entity_id: uuid(), - entity_ref: entityRef, - unprocessed_entity: JSON.stringify(entity), - errors: '', - next_update_at: tx.fn.now(), - last_discovery_at: tx.fn.now(), - }) - .onConflict('entity_ref') - .merge(['unprocessed_entity', 'last_discovery_at']); - - const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( - 'refresh_state', - ).where({ entity_ref: entityRef }); - entityIds.push(entityId); - } - const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( - entityId => ({ - source_key: options.sourceKey, - target_entityRef: entityRef, - }), - ); - await tx.batchInsert( - 'refresh_state_references', - referenceRows, - BATCH_SIZE, - ); - return; - } - - for (const entity of options.removed) { - const entityRef = stringifyEntityRef(entity); - const [result] = await tx<DbRefreshStateRow>('refresh_state') - .where({ entity_ref: entityRef }) - .select('entity_id'); - - if (!result) { - this.logger.info( - `Unable to delete entity '${entityRef}', entity does not exist in refresh state`, + await tx.batchInsert( + 'refresh_state_references', + stateReferences, + BATCH_SIZE, ); - continue; } - const referenceResults = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - // todo correct key? - .where({ source_entity_id: result.entity_id }) - .select(); + // for (const entity of options.items) { + // const entityRef = stringifyEntityRef(entity); + // await tx<DbRefreshStateRow>('refresh_state') + // .insert({ + // entity_id: uuid(), + // entity_ref: entityRef, + // unprocessed_entity: JSON.stringify(entity), + // errors: '', + // next_update_at: tx.fn.now(), + // last_discovery_at: tx.fn.now(), + // }) + // .onConflict('entity_ref') + // .merge(['unprocessed_entity', 'last_discovery_at']); - await tx<DbRefreshStateReferencesRow>('refresh_state_references') - // todo correct key? - .where({ source_entity_id: result.entity_id }) - .delete(); + // const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( + // 'refresh_state', + // ).where({ entity_ref: entityRef }); + // entityIds.push(entityId); + // } + // const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( + // entityId => ({ + // source_key: options.sourceKey, + // target_entityRef: entityRef, + // }), + // ); + // await tx.batchInsert( + // 'refresh_state_references', + // referenceRows, + // BATCH_SIZE, + // ); + // return; } } From 6e545108e7418ee0bd9f57678f59f1a14e27f9be Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 23 Apr 2021 16:01:36 +0200 Subject: [PATCH 140/262] feat: support delta and full sync with the same code and simplify things MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: Johan Haals <johan.haals@gmail.com> Signed-off-by: blam <ben@blam.sh> --- .../DefaultProcessingDatabase.test.ts | 89 +++++++ .../database/DefaultProcessingDatabase.ts | 242 ++++++++---------- 2 files changed, 201 insertions(+), 130 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index ee04a2baf8..c4784c081d 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -294,5 +294,94 @@ describe('Default Processing Database', () => { ), ).toBeFalsy(); }); + + it('should add new locations using the delta options', async () => { + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'delta', + sourceKey: 'lols', + removed: [], + added: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'lols' && + t.target_entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + }); + + it('should remove old locations using the delta options', async () => { + await createLocations(['location:default/new-root']); + + await insertRefRow({ + source_key: 'lols', + target_entity_ref: 'location:default/new-root', + }); + + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'delta', + sourceKey: 'lols', + added: [], + removed: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'lols' && + t.target_entity_ref === 'location:default/new-root', + ), + ).toBeFalsy(); + }); }); }); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index f0c5443651..a80325d469 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -130,34 +130,48 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); } + private async createDelta( + tx: Knex.Transaction, + options: ReplaceUnprocessedEntitiesOptions, + ): Promise<{ toAdd: Entity[]; toRemove: string[] }> { + if (options.type === 'delta') { + return { + toAdd: options.added, + toRemove: options.removed.map(e => stringifyEntityRef(e)), + }; + } + + const oldRefs = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .where({ source_key: options.sourceKey }) + .select('target_entity_ref') + .then(rows => rows.map(r => r.target_entity_ref)); + + const items = options.items.map(entity => ({ + entity, + ref: stringifyEntityRef(entity), + })); + + const oldRefsSet = new Set(oldRefs); + const newRefsSet = new Set(items.map(item => item.ref)); + const toAdd = items.filter(item => !oldRefsSet.has(item.ref)); + const toRemove = oldRefs.filter(ref => !newRefsSet.has(ref)); + + return { toAdd: toAdd.map(({ entity }) => entity), toRemove }; + } + async replaceUnprocessedEntities( txOpaque: Transaction, options: ReplaceUnprocessedEntitiesOptions, ): Promise<void> { const tx = txOpaque as Knex.Transaction; - if (options.type === 'full') { - const oldRefs = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .where({ source_key: options.sourceKey }) - .select('target_entity_ref') - .then(rows => rows.map(r => r.target_entity_ref)); + const { toAdd, toRemove } = await this.createDelta(tx, options); - const items = options.items.map(entity => ({ - entity, - ref: stringifyEntityRef(entity), - id: uuid(), - })); - - const oldRefsSet = new Set(oldRefs); - const newRefsSet = new Set(items.map(item => item.ref)); - const toAdd = items.filter(item => !oldRefsSet.has(item.ref)); - const toRemove = oldRefs.filter(ref => !newRefsSet.has(ref)); - - if (toRemove.length) { - // TODO(freben): Batch split, to not hit variable limits? - /* + if (toRemove.length) { + // TODO(freben): Batch split, to not hit variable limits? + /* WITH RECURSIVE -- All the refs that can be reached from each individual root root_reach(id, entity_ref) AS ( @@ -188,119 +202,87 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { AND refresh_state_references.target_entity_ref = "A" AND them.id IS NULL; */ - const removedCount = await tx<DbRefreshStateRow>('refresh_state') - .whereIn('entity_ref', function orphanedEntityRefs(orphans) { - return ( - orphans - // All the refs that can be reached from each individual root - .withRecursive('root_reach', function rootReach(outer) { - // Start with all roots - return outer - .select({ id: 'id', entity_ref: 'target_entity_ref' }) - .from('refresh_state_references') - .whereNotNull('source_key') - .union(function recurse(inner) { - return ( - inner - // For each match, select all children - .select({ - id: 'root_reach.id', - entity_ref: - 'refresh_state_references.target_entity_ref', - }) - .from('refresh_state_references') - .crossJoin('root_reach', { - 'root_reach.entity_ref': - 'refresh_state_references.source_entity_ref', - }) - ); - }); - }) - .select('us.entity_ref') - // Start out with our own matching row - .from('refresh_state_references') - .where('source_key', options.sourceKey) - .whereIn('target_entity_ref', toRemove) - // Expand the entire tree that emanates from that row - .leftJoin({ us: 'root_reach' }, function us() { - this.on('us.id', '=', 'refresh_state_references.id'); - }) - // Expand with all roots that target the same node but aren't ourselves - .leftOuterJoin({ them: 'root_reach' }, function them() { - this.on('them.entity_ref', '=', 'us.entity_ref'); - this.andOn('them.id', '!=', 'us.id'); - }) - // Keep only the matches that had no other rooots - .whereNull('them.id') - ); - }) - .delete(); + const removedCount = await tx<DbRefreshStateRow>('refresh_state') + .whereIn('entity_ref', function orphanedEntityRefs(orphans) { + return ( + orphans + // All the refs that can be reached from each individual root + .withRecursive('root_reach', function rootReach(outer) { + // Start with all roots + return outer + .select({ id: 'id', entity_ref: 'target_entity_ref' }) + .from('refresh_state_references') + .whereNotNull('source_key') + .union(function recurse(inner) { + return ( + inner + // For each match, select all children + .select({ + id: 'root_reach.id', + entity_ref: + 'refresh_state_references.target_entity_ref', + }) + .from('refresh_state_references') + .crossJoin('root_reach', { + 'root_reach.entity_ref': + 'refresh_state_references.source_entity_ref', + }) + ); + }); + }) + .select('us.entity_ref') + // Start out with our own matching row + .from('refresh_state_references') + .where('source_key', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + // Expand the entire tree that emanates from that row + .leftJoin({ us: 'root_reach' }, function us() { + this.on('us.id', '=', 'refresh_state_references.id'); + }) + // Expand with all roots that target the same node but aren't ourselves + .leftOuterJoin({ them: 'root_reach' }, function them() { + this.on('them.entity_ref', '=', 'us.entity_ref'); + this.andOn('them.id', '!=', 'us.id'); + }) + // Keep only the matches that had no other rooots + .whereNull('them.id') + ); + }) + .delete(); - await tx<DbRefreshStateReferencesRow>('refresh_state_references') - .where('source_key', '=', options.sourceKey) - .whereIn('target_entity_ref', toRemove) - .delete(); + await tx<DbRefreshStateReferencesRow>('refresh_state_references') + .where('source_key', '=', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + .delete(); - console.log( - `REMOVED, ${removedCount} entities: ${JSON.stringify(toRemove)}`, - ); - } + this.logger.debug( + `removed, ${removedCount} entities: ${JSON.stringify(toRemove)}`, + ); + } - if (toAdd.length) { - const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(item => ({ - entity_id: item.id, - entity_ref: item.ref, - unprocessed_entity: JSON.stringify(item.entity), - errors: '', - next_update_at: tx.fn.now(), - last_discovery_at: tx.fn.now(), - })); - const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( - item => ({ - source_key: options.sourceKey, - target_entity_ref: item.ref, - }), - ); - // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense - await tx.batchInsert('refresh_state', state, BATCH_SIZE); - await tx.batchInsert( - 'refresh_state_references', - stateReferences, - BATCH_SIZE, - ); - } + if (toAdd.length) { + const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(entity => ({ + entity_id: uuid(), + entity_ref: stringifyEntityRef(entity), + unprocessed_entity: JSON.stringify(entity), + errors: '', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + })); - // for (const entity of options.items) { - // const entityRef = stringifyEntityRef(entity); - // await tx<DbRefreshStateRow>('refresh_state') - // .insert({ - // entity_id: uuid(), - // entity_ref: entityRef, - // unprocessed_entity: JSON.stringify(entity), - // errors: '', - // next_update_at: tx.fn.now(), - // last_discovery_at: tx.fn.now(), - // }) - // .onConflict('entity_ref') - // .merge(['unprocessed_entity', 'last_discovery_at']); - - // const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( - // 'refresh_state', - // ).where({ entity_ref: entityRef }); - // entityIds.push(entityId); - // } - // const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( - // entityId => ({ - // source_key: options.sourceKey, - // target_entityRef: entityRef, - // }), - // ); - // await tx.batchInsert( - // 'refresh_state_references', - // referenceRows, - // BATCH_SIZE, - // ); - // return; + const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( + entity => ({ + source_key: options.sourceKey, + target_entity_ref: stringifyEntityRef(entity), + }), + ); + // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense + await tx.batchInsert('refresh_state', state, BATCH_SIZE); + await tx.batchInsert( + 'refresh_state_references', + stateReferences, + BATCH_SIZE, + ); } } From b8e80eab23b8e4aadd79b75de16a42839c6e4c45 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 10:14:45 +0200 Subject: [PATCH 141/262] catalog-backend: Remove obervables Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/package.json | 4 +- .../src/next/DatabaseLocationProvider.ts | 71 ------------------- .../next/DefaultCatalogProcessingEngine.ts | 27 +------ .../src/next/DefaultLocationStore.ts | 4 -- plugins/catalog-backend/src/next/types.ts | 5 +- 5 files changed, 5 insertions(+), 106 deletions(-) delete mode 100644 plugins/catalog-backend/src/next/DatabaseLocationProvider.ts diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 9afb537637..5f70ec60e1 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -33,7 +33,6 @@ "@backstage/backend-common": "^0.6.3", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", "@backstage/plugin-search-backend-node": "^0.1.3", @@ -61,8 +60,7 @@ "winston": "^3.2.1", "yaml": "^1.9.2", "yn": "^4.0.0", - "yup": "^0.29.3", - "zen-observable": "^0.8.15" + "yup": "^0.29.3" }, "devDependencies": { "@backstage/cli": "^0.6.9", diff --git a/plugins/catalog-backend/src/next/DatabaseLocationProvider.ts b/plugins/catalog-backend/src/next/DatabaseLocationProvider.ts deleted file mode 100644 index eaf5a78556..0000000000 --- a/plugins/catalog-backend/src/next/DatabaseLocationProvider.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2021 Spotify AB - * - * 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 { Observable } from '@backstage/core'; -import { ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; -import { EntityProvider, LocationStore, EntityMessage } from './types'; -import ObservableImpl from 'zen-observable'; -import { - locationSpecToLocationEntity, - locationSpecToMetadataName, -} from './util'; - -export class DatabaseLocationProvider implements EntityProvider { - private subscribers = new Set< - ZenObservable.SubscriptionObserver<EntityMessage> - >(); - - constructor(private readonly store: LocationStore) { - store.location$().subscribe({ - next: locations => { - if ('all' in locations) { - this.notify({ - all: locations.all.map(l => locationSpecToLocationEntity(l)), - }); - } else { - this.notify({ - added: locations.added.map(l => locationSpecToLocationEntity(l)), - removed: locations.removed.map(l => ({ - kind: 'Location', - namespace: ENTITY_DEFAULT_NAMESPACE, - name: locationSpecToMetadataName(l), - })), - }); - } - }, - }); - } - - private notify(message: EntityMessage) { - for (const subscriber of this.subscribers) { - subscriber.next(message); - } - } - - entityChange$(): Observable<EntityMessage> { - return new ObservableImpl(subscriber => { - this.store.listLocations().then(locations => { - subscriber.next({ - all: locations.map(l => locationSpecToLocationEntity(l)), - }); - this.subscribers.add(subscriber); - }); - return () => { - this.subscribers.delete(subscriber); - }; - }); - } -} diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 7f49bf832d..b71b2c1045 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -14,11 +14,9 @@ * limitations under the License. */ -import { Subscription } from '@backstage/core'; import { CatalogProcessingEngine, EntityProvider, - EntityMessage, EntityProviderConnection, EntityProviderMutation, ProcessingStateManager, @@ -40,7 +38,7 @@ class Connection implements EntityProviderConnection { async applyMutation(mutation: EntityProviderMutation): Promise<void> { if (mutation.type === 'full') { await this.config.stateManager.replaceProcessingItems({ - id: this.config.id, + sourceKey: this.config.id, type: 'full', items: mutation.entities, }); @@ -49,7 +47,7 @@ class Connection implements EntityProviderConnection { } await this.config.stateManager.replaceProcessingItems({ - id: this.config.id, + sourceKey: this.config.id, type: 'delta', added: mutation.added, removed: mutation.removed, @@ -120,25 +118,4 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async stop() { this.running = false; } - - private async onNext(id: string, message: EntityMessage) { - if ('all' in message) { - // TODO unhandled rejection - await this.stateManager.addProcessingItems({ - id, - type: 'provider', - entities: message.all, - }); - } - - if ('added' in message) { - await this.stateManager.addProcessingItems({ - id, - type: 'provider', - entities: message.added, - }); - - // TODO deletions of message.removed - } - } } diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index dff424b1a9..21206f0a7b 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -25,10 +25,6 @@ import { v4 as uuidv4 } from 'uuid'; import { locationSpecToLocationEntity } from './util'; import { ConflictError } from '@backstage/errors'; -export type LocationMessage = - | { all: Location[] } - | { added: Location[]; removed: Location[] }; - export class DefaultLocationStore implements LocationStore, EntityProvider { private _connection: EntityProviderConnection | undefined; diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index f8b4de1c41..a39ab9a8ff 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -16,7 +16,6 @@ import { Entity, - EntityName, LocationSpec, Location, EntityRelationSpec, @@ -116,12 +115,12 @@ export type ProcessingItem = { export type ReplaceProcessingItemsRequest = | { - id: string; + sourceKey: string; items: Entity[]; type: 'full'; } | { - id: string; + sourceKey: string; added: Entity[]; removed: Entity[]; type: 'delta'; From 464863419888171a95d805f3d51cc44bd8950de8 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 13:56:32 +0200 Subject: [PATCH 142/262] Refactor deferredEntities processing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/DefaultLocationStore.ts | 8 + .../src/next/DefaultProcessingStateManager.ts | 39 ++- .../src/next/NextCatalogBuilder.ts | 1 - plugins/catalog-backend/src/next/Stitcher.ts | 4 +- .../DefaultProcessingDatabase.test.ts | 83 ++++-- .../database/DefaultProcessingDatabase.ts | 236 ++++++++++-------- .../src/next/database/types.ts | 7 +- 7 files changed, 222 insertions(+), 156 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index 21206f0a7b..40870cff7b 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -104,5 +104,13 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { async connect(connection: EntityProviderConnection): Promise<void> { this._connection = connection; + const locations = await this.db.locations(); + const entities = locations.map(location => { + return locationSpecToLocationEntity(location); + }); + await this.connection.applyMutation({ + type: 'full', + entities, + }); } } diff --git a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts index d2765c3101..0003b7a7cf 100644 --- a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts +++ b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts @@ -49,35 +49,28 @@ export class DefaultProcessingStateManager implements ProcessingStateManager { async addProcessingItems(request: AddProcessingItemRequest) { return this.db.transaction(async tx => { - await this.db.addUnprocessedEntities(tx, request); + // await this.db.addUnprocessedEntities(tx, request); }); } async getNextProcessingItem(): Promise<ProcessingItem> { - const entities = await new Promise<RefreshStateItem[]>(resolve => - this.popFromQueue(resolve), - ); - const { id, state, unprocessedEntity } = entities[0]; - return { - id, - entity: unprocessedEntity, - state, - }; - } - - async popFromQueue(resolve: (rows: RefreshStateItem[]) => void) { - const entities = await this.db.transaction(async tx => { - return this.db.getProcessableEntities(tx, { - processBatchSize: 1, + for (;;) { + const { items } = await this.db.transaction(async tx => { + return this.db.getProcessableEntities(tx, { + processBatchSize: 1, + }); }); - }); - // No entities require refresh, wait and try again. - if (!entities.items.length) { - setTimeout(() => this.popFromQueue(resolve), 1000); - return; + if (items.length) { + const { id, state, unprocessedEntity } = items[0]; + return { + id, + entity: unprocessedEntity, + state, + }; + } + + await new Promise<void>(resolve => setTimeout(resolve, 1000)); } - - resolve(entities.items); } } diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 1796847164..d720bd331a 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -67,7 +67,6 @@ import { LocationAnalyzer } from '../ingestion/types'; import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; import { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; -import { DatabaseLocationProvider } from '../next/DatabaseLocationProvider'; import { DefaultLocationStore } from './DefaultLocationStore'; import { DefaultProcessingStateManager } from './DefaultProcessingStateManager'; import { CatalogProcessingEngine } from '../next/types'; diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index 3e5e3ac24b..f53b7c6fad 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -76,8 +76,8 @@ export class Stitcher { const [reference_count_result] = await tx<DbRefreshStateReferences>( 'refresh_state_references', ) - .where({ target_entity_id: entity.metadata.uid }) - .count({ reference_count: 'target_entity_id' }); + .where({ target_entity_ref: entityRef }) + .count({ reference_count: 'target_entity_ref' }); if (Number(reference_count_result.reference_count) === 0) { this.logger.debug(`${entityRef} is orphan`); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index c4784c081d..14990a2a79 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -27,27 +27,26 @@ import * as uuid from 'uuid'; import { getVoidLogger } from '@backstage/backend-common'; describe('Default Processing Database', () => { - let db: Knex | undefined; - let processingDatabase: DefaultProcessingDatabase | undefined; - + let db: Knex; + let processingDatabase: DefaultProcessingDatabase; const logger = getVoidLogger(); beforeEach(async () => { db = await DatabaseManager.createTestDatabaseConnection(); await DatabaseManager.createDatabase(db); - processingDatabase = new DefaultProcessingDatabase(db!, logger); + processingDatabase = new DefaultProcessingDatabase(db, logger); }); describe('replaceUnprocessedEntities', () => { const insertRefRow = async (ref: DbRefreshStateReferencesRow) => { - return db!<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ).insert(ref); + return db<DbRefreshStateReferencesRow>('refresh_state_references').insert( + ref, + ); }; const insertRefreshStateRow = async (ref: DbRefreshStateRow) => { - await db!<DbRefreshStateRow>('refresh_state').insert(ref); + await db<DbRefreshStateRow>('refresh_state').insert(ref); }; const createLocations = async (entityRefs: string[]) => { @@ -101,8 +100,8 @@ describe('Default Processing Database', () => { target_entity_ref: 'location:default/root-2', }); - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'full', sourceKey: 'config', items: [ @@ -117,11 +116,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); @@ -205,8 +204,8 @@ describe('Default Processing Database', () => { target_entity_ref: 'location:default/root-2', }); - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'full', sourceKey: 'config', items: [ @@ -221,11 +220,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); @@ -296,8 +295,8 @@ describe('Default Processing Database', () => { }); it('should add new locations using the delta options', async () => { - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'delta', sourceKey: 'lols', removed: [], @@ -313,11 +312,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); @@ -336,6 +335,42 @@ describe('Default Processing Database', () => { ).toBeTruthy(); }); + it('should not remove locations that are referenced elsewhere', async () => { + /* + config-1 -> location:default/root + config-2 -> location:default/root + */ + await createLocations(['location:default/root']); + + await insertRefRow({ + source_key: 'config-1', + target_entity_ref: 'location:default/root', + }); + await insertRefRow({ + source_key: 'config-2', + target_entity_ref: 'location:default/root', + }); + + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'config-1', + items: [], + }); + }); + + const currentRefRowState = await db<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + expect(currentRefRowState).toEqual({ + source_key: 'config-2', + target_entity_ref: 'location:default/root', + }); + + // TODO: assert that root wasn't removed + }); + it('should remove old locations using the delta options', async () => { await createLocations(['location:default/new-root']); @@ -344,8 +379,8 @@ describe('Default Processing Database', () => { target_entity_ref: 'location:default/new-root', }); - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'delta', sourceKey: 'lols', added: [], @@ -361,11 +396,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index a80325d469..dc5e6036f5 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -26,10 +26,12 @@ import { UpdateProcessedEntityOptions, GetProcessableEntitiesResult, ReplaceUnprocessedEntitiesOptions, + RefreshStateItem, } from './types'; import type { Logger } from 'winston'; import { v4 as uuid } from 'uuid'; +import { JsonObject } from '@backstage/config'; export type DbRefreshStateRow = { entity_id: string; @@ -88,7 +90,6 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { errors, }) .where('entity_id', id); - if (refreshResult === 0) { throw new NotFoundError(`Processing state not found for ${id}`); } @@ -96,8 +97,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { // Schedule all deferred entities for future processing. await this.addUnprocessedEntities(tx, { entities: deferredEntities, - id, - type: 'entity', + entityRef: stringifyEntityRef(processedEntity), }); // Update fragments @@ -172,80 +172,104 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (toRemove.length) { // TODO(freben): Batch split, to not hit variable limits? /* - WITH RECURSIVE - -- All the refs that can be reached from each individual root - root_reach(id, entity_ref) AS ( - -- Start with all roots - SELECT id, target_entity_ref - FROM refresh_state_references - WHERE source_key IS NOT NULL - UNION - -- For each match, select all children - SELECT root_reach.id, target_entity_ref - FROM refresh_state_references, root_reach - WHERE source_entity_ref = root_reach.entity_ref - ) - -- Start out with our own matching row (see the WHERE that - -- matches on source_key and target_entity_ref below) - SELECT us.entity_ref - FROM refresh_state_references - -- Expand the entire tree that emanates from that row - JOIN root_reach AS us - ON us.id = refresh_state_references.id - -- Expand with all roots that target the same node but - -- aren't ourselves - LEFT OUTER JOIN root_reach AS them - ON them.entity_ref = us.entity_ref - AND them.id != us.id - -- Keep only the matches that had no other rooots - WHERE refresh_state_references.source_key = "R1" - AND refresh_state_references.target_entity_ref = "A" - AND them.id IS NULL; - */ + WITH RECURSIVE + -- All the nodes that can be reached downwards from our root + descendants(root_id, entity_ref) AS ( + SELECT id, target_entity_ref + FROM refresh_state_references + WHERE source_key = "R1" AND target_entity_ref = "A" + UNION + SELECT descendants.root_id, target_entity_ref + FROM descendants + JOIN refresh_state_references ON source_entity_ref = descendants.entity_ref + ), + -- All the nodes that can be reached upwards from the descendants + ancestors(root_id, via_entity_ref, to_entity_ref) AS ( + SELECT NULL, entity_ref, entity_ref + FROM descendants + UNION + SELECT + CASE WHEN source_key IS NOT NULL THEN id ELSE NULL END, + source_entity_ref, + ancestors.to_entity_ref + FROM ancestors + JOIN refresh_state_references ON target_entity_ref = ancestors.via_entity_ref + ) + -- Start out with all of the descendants + SELECT descendants.entity_ref + FROM descendants + -- Expand with all ancestors that point to those, but aren't the current root + LEFT OUTER JOIN ancestors + ON ancestors.to_entity_ref = descendants.entity_ref + AND ancestors.root_id IS NOT NULL + AND ancestors.root_id != descendants.root_id + -- Exclude all lines that had such a foreign ancestor + WHERE ancestors.root_id IS NULL; + */ const removedCount = await tx<DbRefreshStateRow>('refresh_state') .whereIn('entity_ref', function orphanedEntityRefs(orphans) { return ( orphans - // All the refs that can be reached from each individual root - .withRecursive('root_reach', function rootReach(outer) { - // Start with all roots + // All the nodes that can be reached downwards from our root + .withRecursive('descendants', function descendants(outer) { return outer - .select({ id: 'id', entity_ref: 'target_entity_ref' }) + .select({ root_id: 'id', entity_ref: 'target_entity_ref' }) .from('refresh_state_references') - .whereNotNull('source_key') - .union(function recurse(inner) { - return ( - inner - // For each match, select all children - .select({ - id: 'root_reach.id', - entity_ref: - 'refresh_state_references.target_entity_ref', - }) - .from('refresh_state_references') - .crossJoin('root_reach', { - 'root_reach.entity_ref': - 'refresh_state_references.source_entity_ref', - }) - ); + .where('source_key', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + .union(function recursive(inner) { + return inner + .select({ + root_id: 'descendants.root_id', + entity_ref: + 'refresh_state_references.target_entity_ref', + }) + .from('descendants') + .join('refresh_state_references', { + 'descendants.entity_ref': + 'refresh_state_references.source_entity_ref', + }); }); }) - .select('us.entity_ref') - // Start out with our own matching row - .from('refresh_state_references') - .where('source_key', options.sourceKey) - .whereIn('target_entity_ref', toRemove) - // Expand the entire tree that emanates from that row - .leftJoin({ us: 'root_reach' }, function us() { - this.on('us.id', '=', 'refresh_state_references.id'); + // All the nodes that can be reached upwards from the descendants + .withRecursive('ancestors', function ancestors(outer) { + return outer + .select({ + root_id: tx.raw('NULL', []), + via_entity_ref: 'entity_ref', + to_entity_ref: 'entity_ref', + }) + .from('descendants') + .union(function recursive(inner) { + return inner + .select({ + root_id: tx.raw( + 'CASE WHEN source_key IS NOT NULL THEN id ELSE NULL END', + [], + ), + via_entity_ref: 'source_entity_ref', + to_entity_ref: 'ancestors.to_entity_ref', + }) + .from('ancestors') + .join('refresh_state_references', { + target_entity_ref: 'ancestors.via_entity_ref', + }); + }); }) - // Expand with all roots that target the same node but aren't ourselves - .leftOuterJoin({ them: 'root_reach' }, function them() { - this.on('them.entity_ref', '=', 'us.entity_ref'); - this.andOn('them.id', '!=', 'us.id'); + // Start out with all of the descendants + .select('descendants.entity_ref') + .from('descendants') + // Expand with all ancestors that point to those, but aren't the current root + .leftOuterJoin('ancestors', function keepaliveRoots() { + this.on( + 'ancestors.to_entity_ref', + '=', + 'descendants.entity_ref', + ); + this.andOnNotNull('ancestors.root_id'); + this.andOn('ancestors.root_id', '!=', 'descendants.root_id'); }) - // Keep only the matches that had no other rooots - .whereNull('them.id') + .whereNull('ancestors.root_id') ); }) .delete(); @@ -291,44 +315,45 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { options: AddUnprocessedEntitiesOptions, ): Promise<void> { const tx = txOpaque as Knex.Transaction; - const entityIds = new Array<string>(); - for (const entity of options.entities) { - const entityRef = stringifyEntityRef(entity); - await tx<DbRefreshStateRow>('refresh_state') - .insert({ + const stateRows = options.entities.map( + entity => + ({ entity_id: uuid(), - entity_ref: entityRef, + entity_ref: stringifyEntityRef(entity), unprocessed_entity: JSON.stringify(entity), errors: '', next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), - }) + } as Knex.DbRecord<DbRefreshStateRow>), + ); + const stateReferenceRows = stateRows.map( + stateRow => + ({ + source_entity_ref: options.entityRef, + target_entity_ref: stateRow.entity_ref, + } as Knex.DbRecord<DbRefreshStateReferencesRow>), + ); + + // Upsert all of the unprocessed entities into the refresh_state table, by + // their entity ref. + // TODO(freben): Can this be batched somehow? + for (const row of stateRows) { + await tx<DbRefreshStateRow>('refresh_state') + .insert(row) .onConflict('entity_ref') .merge(['unprocessed_entity', 'last_discovery_at']); - - const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( - 'refresh_state', - ).where({ entity_ref: entityRef }); - entityIds.push(entityId); } - const key = - options.type === 'provider' - ? { source_special_key: options.id } - : { source_entity_id: options.id }; - // copied from update refs + // Replace all references for the originating entity before creating new ones await tx<DbRefreshStateReferencesRow>('refresh_state_references') - .where(key) + .where({ source_entity_ref: options.entityRef }) .delete(); - - const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( - entityId => ({ - ...key, - target_entity_id: entityId, - }), + await tx.batchInsert( + 'refresh_state_references', + stateReferenceRows, + BATCH_SIZE, ); - await tx.batchInsert('refresh_state_references', referenceRows, BATCH_SIZE); } async getProcessableEntities( @@ -356,16 +381,23 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { }); return { - items: items.map(i => ({ - id: i.entity_id, - entityRef: i.entity_ref, - unprocessedEntity: JSON.parse(i.unprocessed_entity) as Entity, - processedEntity: JSON.parse(i.processed_entity) as Entity, - nextUpdateAt: i.next_update_at, - lastDiscoveryAt: i.last_discovery_at, - state: JSON.parse(i.cache), - errors: i.errors, - })), + items: items.map( + i => + ({ + id: i.entity_id, + entityRef: i.entity_ref, + unprocessedEntity: JSON.parse(i.unprocessed_entity) as Entity, + processedEntity: i.processed_entity + ? (JSON.parse(i.processed_entity) as Entity) + : undefined, + nextUpdateAt: i.next_update_at, + lastDiscoveryAt: i.last_discovery_at, + state: i.cache + ? JSON.parse(i.cache) + : new Map<string, JsonObject>(), + errors: i.errors, + } as RefreshStateItem), + ), }; } diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index b926676887..d7a1dcd20b 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -19,8 +19,7 @@ import { JsonObject } from '@backstage/config'; import { Transaction } from '../../database/types'; export type AddUnprocessedEntitiesOptions = { - type: 'entity' | 'provider'; - id: string; + entityRef: string; entities: Entity[]; }; @@ -39,11 +38,11 @@ export type RefreshStateItem = { id: string; entityRef: string; unprocessedEntity: Entity; - processedEntity: Entity; + processedEntity?: Entity; nextUpdateAt: string; lastDiscoveryAt: string; // remove? state: Map<string, JsonObject>; - errors: string; + errors?: string; }; export type GetProcessableEntitiesResult = { From f22ac8403507761e188e28ae25bb49433c694d2d Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 14:02:41 +0200 Subject: [PATCH 143/262] Remove addProcessingItems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/src/next/Stitcher.ts | 4 ++-- plugins/catalog-backend/src/next/types.ts | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index f53b7c6fad..57f5ae9167 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -19,7 +19,7 @@ import { Logger } from 'winston'; import { Transaction } from '../database'; import { ConflictError } from '@backstage/errors'; import { - DbRefreshStateReferences, + DbRefreshStateReferencesRow, DbRefreshStateRow, DbRelationsRow, } from './database/DefaultProcessingDatabase'; @@ -73,7 +73,7 @@ export class Stitcher { return; } - const [reference_count_result] = await tx<DbRefreshStateReferences>( + const [reference_count_result] = await tx<DbRefreshStateReferencesRow>( 'refresh_state_references', ) .where({ target_entity_ref: entityRef }) diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index a39ab9a8ff..ef3bab797b 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -101,12 +101,6 @@ export type ProcessingItemResult = { deferredEntities: Entity[]; }; -export type AddProcessingItemRequest = { - type: 'entity' | 'provider'; - id: string; - entities: Entity[]; -}; - export type ProcessingItem = { id: string; entity: Entity; @@ -128,6 +122,5 @@ export type ReplaceProcessingItemsRequest = export interface ProcessingStateManager { setProcessingItemResult(result: ProcessingItemResult): Promise<void>; getNextProcessingItem(): Promise<ProcessingItem>; - addProcessingItems(request: AddProcessingItemRequest): Promise<void>; replaceProcessingItems(request: ReplaceProcessingItemsRequest): Promise<void>; } From d77f5fea4406de005f25d052a90423f494d8bfcb Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 14:12:57 +0200 Subject: [PATCH 144/262] Add moar tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../DefaultProcessingDatabase.test.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index 14990a2a79..f67b8603db 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -359,16 +359,26 @@ describe('Default Processing Database', () => { }); }); + const currentRefreshState = await db<DbRefreshStateRow>( + 'refresh_state', + ).select(); + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); - expect(currentRefRowState).toEqual({ - source_key: 'config-2', - target_entity_ref: 'location:default/root', - }); + expect(currentRefRowState).toEqual([ + expect.objectContaining({ + source_key: 'config-2', + target_entity_ref: 'location:default/root', + }), + ]); - // TODO: assert that root wasn't removed + expect(currentRefreshState).toEqual([ + expect.objectContaining({ + entity_ref: 'location:default/root', + }), + ]); }); it('should remove old locations using the delta options', async () => { From c1156a4b4748dfe9661ca9727e11184065d35d87 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 14:15:29 +0200 Subject: [PATCH 145/262] Remove dead code Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/DefaultProcessingStateManager.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts index 0003b7a7cf..9c1d20ae9c 100644 --- a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts +++ b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts @@ -14,9 +14,8 @@ * limitations under the License. */ -import { ProcessingDatabase, RefreshStateItem } from './database/types'; +import { ProcessingDatabase } from './database/types'; import { - AddProcessingItemRequest, ProcessingItem, ProcessingItemResult, ProcessingStateManager, @@ -47,12 +46,6 @@ export class DefaultProcessingStateManager implements ProcessingStateManager { }); } - async addProcessingItems(request: AddProcessingItemRequest) { - return this.db.transaction(async tx => { - // await this.db.addUnprocessedEntities(tx, request); - }); - } - async getNextProcessingItem(): Promise<ProcessingItem> { for (;;) { const { items } = await this.db.transaction(async tx => { From e0f43ae45391149d1d7bba5e91689d4690c0dde3 Mon Sep 17 00:00:00 2001 From: Adam Harvey <adaharve@cisco.com> Date: Mon, 26 Apr 2021 09:21:09 -0400 Subject: [PATCH 146/262] Clarify token exposure Signed-off-by: Adam Harvey <adaharve@cisco.com> --- .github/workflows/chromatic-storybook-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/chromatic-storybook-test.yml b/.github/workflows/chromatic-storybook-test.yml index bb14e1c38b..89df848c76 100644 --- a/.github/workflows/chromatic-storybook-test.yml +++ b/.github/workflows/chromatic-storybook-test.yml @@ -48,5 +48,7 @@ jobs: - uses: chromaui/action@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + # projetToken intentionally shared to allow collaborators to run Chromatic on forks + # https://www.chromatic.com/docs/custom-ci-provider#run-chromatic-on-external-forks-of-open-source-projects projectToken: 9tzak77m9nj storybookBuildDir: 'packages/storybook/dist' From 656e1d82b281f4f3a9518e27d1bfe014393c2c91 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 15:38:31 +0200 Subject: [PATCH 147/262] Add all migration files to migrationsv2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../migrationsv2/20200511113813_init.js | 133 ++++++++++ ...0200520140700_location_update_log_table.js | 43 ++++ ...7114117_location_update_log_latest_view.js | 45 ++++ .../migrationsv2/20200702153613_entities.js | 236 ++++++++++++++++++ ..._location_update_log_latest_deduplicate.js | 44 ++++ ...904_location_update_log_duplication_fix.js | 87 +++++++ .../20200807120600_entitySearch.js | 41 +++ .../20200809202832_add_bootstrap_location.js | 42 ++++ .../20200923104503_case_insensitivity.js | 32 +++ .../20201005122705_add_entity_full_name.js | 60 +++++ .../20201006130744_entity_data_column.js | 66 +++++ ...6203131_entity_remove_redundant_columns.js | 50 ++++ .../20201007201501_index_entity_search.js | 37 +++ .../20201019130742_add_relations_table.js | 54 ++++ .../20201123205611_relations_table_uniq.js | 93 +++++++ .../migrationsv2/20201210185851_fk_index.js | 45 ++++ .../20201230103504_update_log_varchar.js | 73 ++++++ .../20210209121210_locations_fk_index.js | 45 ++++ .../src/next/database/DatabaseManager.ts | 15 -- 19 files changed, 1226 insertions(+), 15 deletions(-) create mode 100644 plugins/catalog-backend/migrationsv2/20200511113813_init.js create mode 100644 plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js create mode 100644 plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js create mode 100644 plugins/catalog-backend/migrationsv2/20200702153613_entities.js create mode 100644 plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js create mode 100644 plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js create mode 100644 plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js create mode 100644 plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js create mode 100644 plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js create mode 100644 plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js create mode 100644 plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js create mode 100644 plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js create mode 100644 plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js create mode 100644 plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js create mode 100644 plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js create mode 100644 plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js create mode 100644 plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js create mode 100644 plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js diff --git a/plugins/catalog-backend/migrationsv2/20200511113813_init.js b/plugins/catalog-backend/migrationsv2/20200511113813_init.js new file mode 100644 index 0000000000..7f3d75e35c --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200511113813_init.js @@ -0,0 +1,133 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + return ( + knex.schema + // + // locations + // + .createTable('locations', table => { + table.comment( + 'Registered locations that shall be contiuously scanned for catalog item updates', + ); + table + .uuid('id') + .primary() + .notNullable() + .comment('Auto-generated ID of the location'); + table.string('type').notNullable().comment('The type of location'); + table + .string('target') + .notNullable() + .comment('The actual target of the location'); + }) + // + // entities + // + .createTable('entities', table => { + table.comment('All entities currently stored in the catalog'); + table.uuid('id').primary().comment('Auto-generated ID of the entity'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .nullable() + .comment('The location that originated the entity'); + table + .string('etag') + .notNullable() + .comment( + 'An opaque string that changes for each update operation to any part of the entity, including metadata.', + ); + table + .string('generation') + .notNullable() + .unsigned() + .comment( + 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', + ); + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table + .string('kind') + .notNullable() + .comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + table + .string('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .string('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + }) + .alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); + }) + // + // entities_search + // + .createTable('entities_search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + }) + ); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + return knex.schema + .dropTable('entities_search') + .alterTable('entities', table => { + table.dropUnique([], 'entities_unique_name'); + }) + .dropTable('entities') + .dropTable('locations'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js b/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js new file mode 100644 index 0000000000..d8093fc9b4 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js @@ -0,0 +1,43 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + return knex.schema.createTable('location_update_log', table => { + table.uuid('id').primary(); + table.enum('status', ['success', 'fail']).notNullable(); + table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); + table.string('message'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .onUpdate('CASCADE') + .onDelete('CASCADE'); + table.string('entity_name').nullable(); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + return knex.schema.dropTableIfExists('location_update_log'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js b/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js new file mode 100644 index 0000000000..a0f0f33a65 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Get list sorted by created_at timestamp in descending order + // Grouped by location_id + return knex.schema.raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(created_at) AS MAXDATE + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.created_at = t2.MAXDATE + ORDER BY created_at DESC; + `); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + return knex.schema.raw(`DROP VIEW location_update_log_latest;`); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200702153613_entities.js b/plugins/catalog-backend/migrationsv2/20200702153613_entities.js new file mode 100644 index 0000000000..0f1c204f9b --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200702153613_entities.js @@ -0,0 +1,236 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // SQLite does not support FK and PK + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.dropForeign(['entity_id']); + }); + await knex.schema.alterTable('entities', table => { + table.dropPrimary('entities_pkey'); + }); + } + await knex.schema.alterTable('entities', table => { + table.dropUnique([], 'entities_unique_name'); + }); + // Setup temporary tables + await knex.schema.renameTable('entities_search', 'tmp_entities_search'); + await knex.schema.renameTable('entities', 'tmp_entities'); + + // + // entities + // + await knex.schema + .createTable('entities', table => { + table.comment('All entities currently stored in the catalog'); + table.uuid('id').primary().comment('Auto-generated ID of the entity'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .nullable() + .comment('The location that originated the entity'); + table + .string('etag') + .notNullable() + .comment( + 'An opaque string that changes for each update operation to any part of the entity, including metadata.', + ); + table + .string('generation') + .notNullable() + .unsigned() + .comment( + 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', + ); + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table + .string('kind') + .notNullable() + .comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + table + .text('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .text('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + }) + .alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); + }); + + await knex.schema.raw(`INSERT INTO entities SELECT * FROM tmp_entities`); + + // + // entities_search + // + await knex.schema.createTable('entities_search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + }); + await knex.schema.raw( + `INSERT INTO entities_search SELECT * FROM tmp_entities_search`, + ); + + // Clean up + await knex.schema.dropTable('tmp_entities'); + return knex.schema.dropTable('tmp_entities_search'); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + // SQLite does not support FK and PK + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.dropForeign(['entity_id']); + }); + await knex.schema.alterTable('entities', table => { + table.dropPrimary('entities_pkey'); + }); + } + await knex.schema.alterTable('entities', table => { + table.dropUnique([], 'entities_unique_name'); + }); + + // Setup temporary tables + await knex.schema.renameTable('entities_search', 'tmp_entities_search'); + await knex.schema.renameTable('entities', 'tmp_entities'); + + // + // entities + // + await knex.schema + .createTable('entities', table => { + table.comment('All entities currently stored in the catalog'); + table.uuid('id').primary().comment('Auto-generated ID of the entity'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .nullable() + .comment('The location that originated the entity'); + table + .string('etag') + .notNullable() + .comment( + 'An opaque string that changes for each update operation to any part of the entity, including metadata.', + ); + table + .string('generation') + .notNullable() + .unsigned() + .comment( + 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', + ); + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table + .string('kind') + .notNullable() + .comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + table + .string('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .string('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + }) + .alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); + }); + + await knex.schema.raw(`INSERT INTO entities SELECT * FROM tmp_entities`); + + // + // entities_search + // + await knex.schema.createTable('entities_search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + }); + await knex.schema.raw( + `INSERT INTO entities_search SELECT * FROM tmp_entities_search`, + ); + + // Clean up + await knex.schema.dropTable('tmp_entities'); + return knex.schema.dropTable('tmp_entities_search'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js b/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js new file mode 100644 index 0000000000..87b41a80fc --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js @@ -0,0 +1,44 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = function up(knex) { + return knex.schema.raw(`DROP VIEW location_update_log_latest;`).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(created_at) AS MAXDATE + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.created_at = t2.MAXDATE + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; +`); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = function down(knex) { + knex.schema.raw(`DROP VIEW location_update_log_latest;`); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js b/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js new file mode 100644 index 0000000000..de2b194cff --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js @@ -0,0 +1,87 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = function up(knex) { + return knex.schema + .raw('DROP VIEW location_update_log_latest;') + .dropTable('location_update_log') + .createTable('location_update_log', table => { + table.bigIncrements('id').primary(); // instead of uuid, so we can MAX it + table.enum('status', ['success', 'fail']).notNullable(); + table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); + table.string('message'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .onUpdate('CASCADE') + .onDelete('CASCADE'); + table.string('entity_name').nullable(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(id) AS MAXID + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.id = t2.MAXID + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = function down(knex) { + return knex.schema + .raw('DROP VIEW location_update_log_latest;') + .dropTable('location_update_log') + .createTable('location_update_log', table => { + table.uuid('id').primary(); + table.enum('status', ['success', 'fail']).notNullable(); + table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); + table.string('message'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .onUpdate('CASCADE') + .onDelete('CASCADE'); + table.string('entity_name').nullable(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(created_at) AS MAXDATE + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.created_at = t2.MAXDATE + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js b/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js new file mode 100644 index 0000000000..45226e53b4 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Sqlite does not support alter column. + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.text('value').nullable().alter(); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + // Sqlite does not support alter column. + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.string('value').nullable().alter(); + }); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js b/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js new file mode 100644 index 0000000000..a90813fe85 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js @@ -0,0 +1,42 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Adds a single 'bootstrap' location that can be used to trigger work in processors. + // This is primarily here to fulfill foreign key constraints. + await knex('locations').insert({ + id: require('uuid').v4(), + type: 'bootstrap', + target: 'bootstrap', + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex('locations') + .where({ + type: 'bootstrap', + target: 'bootstrap', + }) + .del(); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js b/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js new file mode 100644 index 0000000000..ea5ba9e58d --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex('entities') + .where({ namespace: null }) + .update({ namespace: 'default' }); + await knex('entities_search').update({ + key: knex.raw('LOWER(key)'), + value: knex.raw('LOWER(value)'), + }); +}; + +exports.down = async function down() {}; diff --git a/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js b/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js new file mode 100644 index 0000000000..aae1861658 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js @@ -0,0 +1,60 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities', table => { + table.text('full_name').nullable(); + }); + + await knex('entities').update({ + full_name: knex.raw( + "LOWER(kind) || ':' || LOWER(COALESCE(namespace, 'default')) || '/' || LOWER(name)", + ), + }); + + // SQLite does not support alter column + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.text('full_name').notNullable().alter(); + }); + } + + await knex.schema.alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['full_name'], 'entities_unique_full_name'); + table.dropUnique([], 'entities_unique_name'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.dropUnique([], 'entities_unique_full_name'); + table.unique(['kind', 'namespace', 'name'], 'entities_unique_name'); + }); + + await knex.schema.alterTable('entities_search', table => { + table.dropColumn('full_name'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js b/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js new file mode 100644 index 0000000000..a8964efbf6 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js @@ -0,0 +1,66 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities', table => { + table + .text('data') + .nullable() + .comment('The entire JSON data blob of the entity'); + }); + + await knex('entities').update({ + // apiVersion and kind should not contain any JSON unsafe chars, and both + // metadata and spec are already valid serialized JSON + data: knex.raw( + `'{"apiVersion":"' || api_version || '","kind":"' || kind || '","metadata":' || metadata || COALESCE(',"spec":' || spec, '') || '}'`, + ), + }); + + await knex.schema.alterTable('entities', table => { + table.dropColumn('metadata'); + table.dropColumn('spec'); + }); + + // SQLite does not support ALTER COLUMN. + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.text('data').notNullable().alter(); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities', table => { + table + .text('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .text('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + table.dropColumn('data'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js b/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js new file mode 100644 index 0000000000..f40df5f73e --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js @@ -0,0 +1,50 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities', table => { + table.dropColumn('api_version'); + table.dropColumn('kind'); + table.dropColumn('name'); + table.dropColumn('namespace'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities', table => { + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table.string('kind').notNullable().comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js b/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js new file mode 100644 index 0000000000..77bf0529eb --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities_search', table => { + table.index(['key'], 'entities_search_key'); + table.index(['value'], 'entities_search_value'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities_search', table => { + table.dropIndex('', 'entities_search_key'); + table.dropIndex('', 'entities_search_value'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js b/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js new file mode 100644 index 0000000000..85e729f814 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.createTable('entities_relations', table => { + table.comment('All relations between entities in the catalog'); + table + .uuid('originating_entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .notNullable() + .comment('The entity that provided the relation'); + table + .string('source_full_name') + .notNullable() + .comment('The full name of the source entity of the relation'); + table + .string('type') + .notNullable() + .comment('The type of the relation between the entities'); + table + .string('target_full_name') + .notNullable() + .comment('The full name of the target entity of the relation'); + + table.primary(['source_full_name', 'type', 'target_full_name']); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.dropTable('entities_relations'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js b/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js new file mode 100644 index 0000000000..9e8198b5eb --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js @@ -0,0 +1,93 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client === 'sqlite3') { + // sqlite doesn't support dropPrimary so we recreate it properly instead + await knex.schema.dropTable('entities_relations'); + await knex.schema.createTable('entities_relations', table => { + table.comment('All relations between entities in the catalog'); + table + .uuid('originating_entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .notNullable() + .comment('The entity that provided the relation'); + table + .string('source_full_name') + .notNullable() + .comment('The full name of the source entity of the relation'); + table + .string('type') + .notNullable() + .comment('The type of the relation between the entities'); + table + .string('target_full_name') + .notNullable() + .comment('The full name of the target entity of the relation'); + table.index('source_full_name', 'source_full_name_idx'); + }); + } else { + await knex.schema.alterTable('entities_relations', table => { + table.dropPrimary(); + table.index('source_full_name', 'source_full_name_idx'); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client === 'sqlite3') { + await knex.schema.dropTable('entities_relations'); + await knex.schema.createTable('entities_relations', table => { + table.comment('All relations between entities in the catalog'); + table + .uuid('originating_entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .notNullable() + .comment('The entity that provided the relation'); + table + .string('source_full_name') + .notNullable() + .comment('The full name of the source entity of the relation'); + table + .string('type') + .notNullable() + .comment('The type of the relation between the entities'); + table + .string('target_full_name') + .notNullable() + .comment('The full name of the target entity of the relation'); + + table.primary(['source_full_name', 'type', 'target_full_name']); + }); + } else { + await knex.schema.alterTable('entities_relations', table => { + table.dropIndex([], 'source_full_name_idx'); + table.primary(['source_full_name', 'type', 'target_full_name']); + }); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js b/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js new file mode 100644 index 0000000000..abb26cd5fc --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_relations', table => { + table.index('originating_entity_id', 'originating_entity_id_idx'); + }); + await knex.schema.alterTable('entities_search', table => { + table.index('entity_id', 'entity_id_idx'); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_relations', table => { + table.dropIndex([], 'originating_entity_id_idx'); + }); + await knex.schema.alterTable('entities_relations', table => { + table.dropIndex([], 'entity_id_idx'); + }); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js b/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js new file mode 100644 index 0000000000..d924b0414a --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js @@ -0,0 +1,73 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client !== 'sqlite3') { + // We actually just want to widen columns, but can't do that while a + // view is dependent on them - so we just reconstruct it exactly as it was + await knex.schema + .raw('DROP VIEW location_update_log_latest;') + .alterTable('location_update_log', table => { + table.text('message').alter(); + table.text('entity_name').nullable().alter(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(id) AS MAXID + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.id = t2.MAXID + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema + .raw('DROP VIEW location_update_log_latest;') + .alterTable('location_update_log', table => { + table.string('message').alter(); + table.string('entity_name').nullable().alter(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(id) AS MAXID + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.id = t2.MAXID + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js b/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js new file mode 100644 index 0000000000..ccfb1faffb --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.index('location_id', 'entity_location_id_idx'); + }); + await knex.schema.alterTable('location_update_log', table => { + table.index('location_id', 'update_log_location_id_idx'); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.dropIndex([], 'entity_location_id_idx'); + }); + await knex.schema.alterTable('location_update_log', table => { + table.dropIndex([], 'update_log_location_id_idx'); + }); + } +}; diff --git a/plugins/catalog-backend/src/next/database/DatabaseManager.ts b/plugins/catalog-backend/src/next/database/DatabaseManager.ts index 4c9e45950f..f660f73ecb 100644 --- a/plugins/catalog-backend/src/next/database/DatabaseManager.ts +++ b/plugins/catalog-backend/src/next/database/DatabaseManager.ts @@ -20,7 +20,6 @@ import { v4 as uuidv4 } from 'uuid'; import { Logger } from 'winston'; import { CommonDatabase } from '../../database/CommonDatabase'; import { Database } from '../../database/types'; -import fs from 'fs-extra'; export type CreateDatabaseOptions = { logger: Logger; @@ -35,16 +34,10 @@ export class DatabaseManager { knex: Knex, options: Partial<CreateDatabaseOptions> = {}, ): Promise<Database> { - const allMigrations = resolvePackagePath( - '@backstage/plugin-catalog-backend', - 'migrations', - ); - const migrationsDir = resolvePackagePath( '@backstage/plugin-catalog-backend', 'migrationsv2', ); - await fs.copy(allMigrations, migrationsDir); await knex.migrate.latest({ directory: migrationsDir, @@ -79,14 +72,6 @@ export class DatabaseManager { public static async createTestDatabaseConnection(): Promise<Knex> { const config: Knex.Config<any> = { - /* - client: 'pg', - connection: { - host: 'localhost', - user: 'postgres', - password: 'postgres', - }, - */ client: 'sqlite3', connection: ':memory:', useNullAsDefault: true, From fae7eb02965c17534168b0c85580ea5367e05477 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 15:43:22 +0200 Subject: [PATCH 148/262] Add configLocationProvider and provider identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/ConfigLocationProvider.ts | 49 +++++++++++++++++++ .../next/DefaultCatalogProcessingEngine.ts | 9 ++-- .../src/next/DefaultLocationStore.ts | 4 ++ .../src/next/NextCatalogBuilder.ts | 7 +-- plugins/catalog-backend/src/next/types.ts | 1 + 5 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 plugins/catalog-backend/src/next/ConfigLocationProvider.ts diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts new file mode 100644 index 0000000000..5b93fcfd98 --- /dev/null +++ b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { EntityProviderConnection, EntityProvider } from './types'; +import path from 'path'; +import { Config } from '@backstage/config'; +import { locationSpecToLocationEntity } from './util'; + +export class ConfigLocationProvider implements EntityProvider { + private connection: EntityProviderConnection | undefined; + + constructor(private readonly config: Config) {} + + getProviderName(): string { + return 'ConfigLocationProvider'; + } + + async connect(connection: EntityProviderConnection): Promise<void> { + this.connection = connection; + + const locationConfigs = + this.config.getOptionalConfigArray('catalog.locations') ?? []; + + const entities = locationConfigs.map(location => + locationSpecToLocationEntity({ + type: location.getString('type'), + target: path.resolve(location.getString('target')), + }), + ); + + await this.connection.applyMutation({ + type: 'full', + entities, + }); + } +} diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index b71b2c1045..1934b0aea7 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -68,9 +68,12 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async start() { for (const provider of this.entityProviders) { - // TODO: this ID should be some form of identifier for the EntityProvider - const id = 'databaseProvider'; - provider.connect(new Connection({ stateManager: this.stateManager, id })); + provider.connect( + new Connection({ + stateManager: this.stateManager, + id: provider.getProviderName(), + }), + ); } this.running = true; diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index 40870cff7b..a56e5d1585 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -30,6 +30,10 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { constructor(private readonly db: Database) {} + getProviderName(): string { + return 'DefaultLocationStore'; + } + createLocation(spec: LocationSpec): Promise<Location> { return this.db.transaction(async tx => { // TODO: id should really be type and target combined and not a uuid. diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index d720bd331a..0699a13f58 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -50,6 +50,7 @@ import { GithubDiscoveryProcessor, GithubOrgReaderProcessor, LdapOrgReaderProcessor, + LocationEntityProcessor, MicrosoftGraphOrgReaderProcessor, PlaceholderProcessor, PlaceholderResolver, @@ -73,6 +74,7 @@ import { CatalogProcessingEngine } from '../next/types'; import { NextEntitiesCatalog } from './NextEntitiesCatalog'; import { Stitcher } from './Stitcher'; import { CommonDatabase } from '../database/CommonDatabase'; +import { ConfigLocationProvider } from './ConfigLocationProvider'; export type CatalogEnvironment = { logger: Logger; @@ -272,9 +274,10 @@ export class NextCatalogBuilder { const locationStore = new DefaultLocationStore(db); const stitcher = new Stitcher(dbClient, logger); + const configLocationProvider = new ConfigLocationProvider(config); const processingEngine = new DefaultCatalogProcessingEngine( logger, - [locationStore], // entityproviders + [locationStore, configLocationProvider], stateManager, orchestrator, stitcher, @@ -322,7 +325,6 @@ export class NextCatalogBuilder { // These are always there no matter what const processors: CatalogProcessor[] = [ - StaticLocationProcessor.fromConfig(config), new PlaceholderProcessor({ resolvers: placeholderResolvers, reader }), new BuiltinKindsEntityProcessor(), ]; @@ -338,7 +340,6 @@ export class NextCatalogBuilder { MicrosoftGraphOrgReaderProcessor.fromConfig(config, { logger }), new UrlReaderProcessor({ reader, logger }), CodeOwnersProcessor.fromConfig(config, { logger, reader }), - // new LocationEntityProcessor({ integrations }), new AnnotateLocationEntityProcessor({ integrations }), ); } diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index ef3bab797b..e0616fb336 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -65,6 +65,7 @@ export interface EntityProviderConnection { } export interface EntityProvider { + getProviderName(): string; connect(connection: EntityProviderConnection): Promise<void>; } From 19a4dd7103b806122fede7bdf2a8952204f81f84 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Mon, 26 Apr 2021 16:00:09 +0200 Subject: [PATCH 149/262] plugins: removed unused swr dependency Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/rare-parrots-share.md | 6 ++++++ plugins/catalog/package.json | 3 +-- plugins/scaffolder/package.json | 1 - yarn.lock | 7 ------- 4 files changed, 7 insertions(+), 10 deletions(-) create mode 100644 .changeset/rare-parrots-share.md diff --git a/.changeset/rare-parrots-share.md b/.changeset/rare-parrots-share.md new file mode 100644 index 0000000000..917ec5a18e --- /dev/null +++ b/.changeset/rare-parrots-share.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog': patch +'@backstage/plugin-scaffolder': patch +--- + +Removed unused `swr` dependency. diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index b6b306c260..965a0b327b 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -49,8 +49,7 @@ "react-helmet": "6.1.0", "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", - "react-use": "^15.3.3", - "swr": "^0.3.0" + "react-use": "^15.3.3" }, "devDependencies": { "@backstage/cli": "^0.6.9", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 4d4563df2f..2b4feecb7b 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -55,7 +55,6 @@ "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", "react-use": "^15.3.3", - "swr": "^0.3.0", "use-immer": "^0.5.1", "zen-observable": "^0.8.15" }, diff --git a/yarn.lock b/yarn.lock index ba1b3bfe73..f2c2bee93c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24792,13 +24792,6 @@ swap-case@^2.0.1: dependencies: tslib "^2.0.3" -swr@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/swr/-/swr-0.3.0.tgz#69602953dd50ab07fe60c920fd63199256645675" - integrity sha512-3p0p5TWH0qiaKAph5wBkMwqe2WjNseITfjmdVoNzjqRZGn/gnpRi6whMDjhMVb/vp/yyDtKWPlyjid8QZH+UhA== - dependencies: - fast-deep-equal "2.0.1" - symbol-observable@1.2.0, symbol-observable@^1.0.3, symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" From da489d2cd3a29f30749829e804ff8f9668153e0f Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 16:38:34 +0200 Subject: [PATCH 150/262] add new Scheduler Class Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- plugins/search-backend-node/src/Scheduler.ts | 75 ++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 plugins/search-backend-node/src/Scheduler.ts diff --git a/plugins/search-backend-node/src/Scheduler.ts b/plugins/search-backend-node/src/Scheduler.ts new file mode 100644 index 0000000000..e54a837cee --- /dev/null +++ b/plugins/search-backend-node/src/Scheduler.ts @@ -0,0 +1,75 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { Logger } from 'winston'; + +type TaskEnvelope = { + task: Function; + interval: number; +}; + +/** + * TODO: coordination, error handling + */ + +export class Scheduler { + private logger: Logger; + private schedule: TaskEnvelope[]; + private intervalTimeouts: NodeJS.Timeout[] = []; + + constructor({ logger }: { logger: Logger }) { + this.logger = logger; + this.schedule = []; + } + + /** + * Adds each task and interval to the schedule + * + */ + addToSchedule(task: Function, interval: number) { + if (this.intervalTimeouts.length) { + throw new Error( + 'Cannot add task to schedule that has already been started.', + ); + } + this.schedule.push({ task, interval }); + } + + /** + * Starts the scheduling process for each task + */ + start() { + this.logger.info('Starting all scheduled search tasks.'); + this.schedule.forEach(({ task, interval }) => { + this.intervalTimeouts.push( + setInterval(() => { + task(); + }, interval), + ); + }); + } + + /** + * Stop all scheduled tasks. + */ + stop() { + this.logger.info('Stopping all scheduled search tasks.'); + this.intervalTimeouts.forEach(timeout => { + clearInterval(timeout); + }); + this.intervalTimeouts = []; + } +} From 0b9eac3a819e3185c98a339124871f85fb2383e8 Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 16:39:33 +0200 Subject: [PATCH 151/262] refactor build method in indexBuilder Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- .../search-backend-node/src/IndexBuilder.ts | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/plugins/search-backend-node/src/IndexBuilder.ts b/plugins/search-backend-node/src/IndexBuilder.ts index 0fc881c262..768dee5b67 100644 --- a/plugins/search-backend-node/src/IndexBuilder.ts +++ b/plugins/search-backend-node/src/IndexBuilder.ts @@ -16,7 +16,7 @@ import { DocumentCollator, DocumentDecorator } from '@backstage/search-common'; import { Logger } from 'winston'; - +import { Scheduler } from './index'; import { RegisterCollatorParameters, RegisterDecoratorParameters, @@ -92,40 +92,42 @@ export class IndexBuilder { } /** - * Starts the process of executing collators and decorators and building the - * search index. - * - * TODO: But like with coordination, timing, error handling, and what have you. + * Compiles collators and decorators into tasks, which are added to a + * scheduler returned to the caller. */ - async build() { - return Promise.all( - Object.keys(this.collators).map(async type => { - setInterval(async () => { - const decorators: DocumentDecorator[] = ( - this.decorators['*'] || [] - ).concat(this.decorators[type] || []); + async build(): Promise<{ scheduler: Scheduler }> { + const scheduler = new Scheduler({ logger: this.logger }); + Object.keys(this.collators).map(type => { + scheduler.addToSchedule(async () => { + // Collate, Decorate, Index. + const decorators: DocumentDecorator[] = ( + this.decorators['*'] || [] + ).concat(this.decorators[type] || []); + + this.logger.debug( + `Collating documents for ${type} via ${this.collators[type].collate.constructor.name}`, + ); + let documents = await this.collators[type].collate.execute(); + for (let i = 0; i < decorators.length; i++) { this.logger.debug( - `Collating documents for ${type} via ${this.collators[type].collate.constructor.name}`, + `Decorating ${type} documents via ${decorators[i].constructor.name}`, ); - let documents = await this.collators[type].collate.execute(); - for (let i = 0; i < decorators.length; i++) { - this.logger.debug( - `Decorating ${type} documents via ${decorators[i].constructor.name}`, - ); - documents = await decorators[i].execute(documents); - } + documents = await decorators[i].execute(documents); + } - if (!documents || documents.length === 0) { - this.logger.debug(`No documents for type "${type}" to index`); - return; - } + if (!documents || documents.length === 0) { + this.logger.debug(`No documents for type "${type}" to index`); + return; + } - // pushing documents to index to a configured search engine. - this.searchEngine.index(type, documents); - // refreshInterval configured in seconds, setInterval want milliseconds - }, this.collators[type].refreshInterval * 1000); - }), - ); + // pushing documents to index to a configured search engine. + this.searchEngine.index(type, documents); + }, this.collators[type].refreshInterval * 1000); + }); + + return { + scheduler, + }; } } From 9dff1a9839704af0ae722372a728b504ebe27bec Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 16:43:58 +0200 Subject: [PATCH 152/262] use scheduler and fix tests Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- packages/backend/src/plugins/search.ts | 5 ++++- plugins/search-backend-node/src/index.test.ts | 15 ++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index da7ee193b4..03c7d44a18 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -34,7 +34,10 @@ export default async function createPlugin({ collator: new DefaultCatalogCollator(discovery), }); - indexBuilder.build(); + const { scheduler } = await indexBuilder.build(); + + scheduler.start(); + useHotCleanup(module, () => scheduler.stop()); return await createRouter({ engine: indexBuilder.getSearchEngine(), diff --git a/plugins/search-backend-node/src/index.test.ts b/plugins/search-backend-node/src/index.test.ts index 86233425e7..e1dc511b97 100644 --- a/plugins/search-backend-node/src/index.test.ts +++ b/plugins/search-backend-node/src/index.test.ts @@ -65,7 +65,8 @@ describe('IndexBuilder', () => { }); // Build the index and ensure the collator was invoked. - await testIndexBuilder.build(); + const { scheduler } = await testIndexBuilder.build(); + scheduler.start(); jest.advanceTimersByTime(6000); expect(collatorSpy).toHaveBeenCalled(); }); @@ -89,7 +90,8 @@ describe('IndexBuilder', () => { }); // Build the index and ensure the decorator was invoked. - await testIndexBuilder.build(); + const { scheduler } = await testIndexBuilder.build(); + scheduler.start(); jest.advanceTimersByTime(6000); // wait for async decorator execution await Promise.resolve(); @@ -123,7 +125,8 @@ describe('IndexBuilder', () => { }); // Build the index and ensure the decorator was invoked. - await testIndexBuilder.build(); + const { scheduler } = await testIndexBuilder.build(); + scheduler.start(); jest.advanceTimersByTime(6000); // wait for async decorator execution await Promise.resolve(); @@ -138,7 +141,7 @@ describe('IndexBuilder', () => { text: 'Test text.', location: '/test/location', }; - jest + const collatorSpy = jest .spyOn(testCollator, 'execute') .mockImplementation(async () => [docFixture]); const decoratorSpy = jest.spyOn(testDecorator, 'execute'); @@ -157,8 +160,10 @@ describe('IndexBuilder', () => { }); // Build the index and ensure the decorator was not invoked. - await testIndexBuilder.build(); + const { scheduler } = await testIndexBuilder.build(); + scheduler.start(); jest.advanceTimersByTime(6000); + expect(collatorSpy).toHaveBeenCalled(); expect(decoratorSpy).not.toHaveBeenCalled(); }); }); From 50b15bfeb3495f623f0bce521ad9e5d5b383951d Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 16:44:32 +0200 Subject: [PATCH 153/262] imports and exports Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- packages/backend/src/plugins/search.ts | 1 + plugins/search-backend-node/src/index.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index 03c7d44a18..dcd48aaf40 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { useHotCleanup } from '@backstage/backend-common'; import { createRouter } from '@backstage/plugin-search-backend'; import { IndexBuilder, diff --git a/plugins/search-backend-node/src/index.ts b/plugins/search-backend-node/src/index.ts index a3a0eb855e..7ee75e3d59 100644 --- a/plugins/search-backend-node/src/index.ts +++ b/plugins/search-backend-node/src/index.ts @@ -15,5 +15,6 @@ */ export { IndexBuilder } from './IndexBuilder'; +export { Scheduler } from './Scheduler'; export { LunrSearchEngine } from './engines'; export type { SearchEngine } from './types'; From fafd8043649dd7432bde654eaee11cf58539544f Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 16:49:32 +0200 Subject: [PATCH 154/262] update changeset Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- .changeset/odd-ads-invite.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/odd-ads-invite.md b/.changeset/odd-ads-invite.md index d487df47d3..0dde3d0c1f 100644 --- a/.changeset/odd-ads-invite.md +++ b/.changeset/odd-ads-invite.md @@ -2,4 +2,4 @@ '@backstage/plugin-search-backend-node': patch --- -Moved refresh loop to builder and use configured refreshInterval for each collator +Introduced Scheduler which is responsible for adding new tasks to a schedule together with it's interval timer as well as starting and stopping the scheduler processes. From e00ba124546a742639973fd26edb39635dff5351 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 16:53:44 +0200 Subject: [PATCH 155/262] chore: remove unused imports Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/src/next/NextCatalogBuilder.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 0699a13f58..24b763a098 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -50,11 +50,9 @@ import { GithubDiscoveryProcessor, GithubOrgReaderProcessor, LdapOrgReaderProcessor, - LocationEntityProcessor, MicrosoftGraphOrgReaderProcessor, PlaceholderProcessor, PlaceholderResolver, - StaticLocationProcessor, UrlReaderProcessor, } from '../ingestion'; import { RepoLocationAnalyzer } from '../ingestion/LocationAnalyzer'; From 17915e29b31acb6ebfbacee71db655888ae5602e Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Mon, 26 Apr 2021 16:53:28 +0200 Subject: [PATCH 156/262] Rework state management to avoid rendering multiple while navigating between pages Closes #5184 Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/techdocs-young-walls-decide.md | 5 ++ .../techdocs/src/reader/components/Reader.tsx | 38 ++++++------- .../src/reader/components/TechDocsPage.tsx | 6 +-- .../src/reader/components/useRawPage.ts | 54 +++++++++++++++++++ 4 files changed, 81 insertions(+), 22 deletions(-) create mode 100644 .changeset/techdocs-young-walls-decide.md create mode 100644 plugins/techdocs/src/reader/components/useRawPage.ts diff --git a/.changeset/techdocs-young-walls-decide.md b/.changeset/techdocs-young-walls-decide.md new file mode 100644 index 0000000000..8dc0373234 --- /dev/null +++ b/.changeset/techdocs-young-walls-decide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Rework state management to avoid rendering multiple while navigating between pages. diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index ff4f47dca0..6e5e0b5920 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { EntityName } from '@backstage/catalog-model'; -import { useApi, configApiRef } from '@backstage/core'; +import { configApiRef, useApi } from '@backstage/core'; import { BackstageTheme } from '@backstage/theme'; import { useTheme } from '@material-ui/core'; import { Alert } from '@material-ui/lab'; @@ -24,6 +24,7 @@ import { useAsync } from 'react-use'; import { techdocsStorageApiRef } from '../../api'; import transformer, { addBaseUrl, + addGitFeedbackLink, addLinkClickListener, injectCss, onCssReady, @@ -31,10 +32,10 @@ import transformer, { rewriteDocLinks, sanitizeDOM, simplifyMkdocsFooter, - addGitFeedbackLink, } from '../transformers'; import { TechDocsNotFound } from './TechDocsNotFound'; import TechDocsProgressBar from './TechDocsProgressBar'; +import { useRawPage } from './useRawPage'; type Props = { entityId: EntityName; @@ -69,20 +70,20 @@ export const Reader = ({ entityId, onReady }: Props) => { }); } return techdocsStorageApi.syncEntityDocs({ kind, namespace, name }); - }); + }, [techdocsStorageApi, kind, namespace, name]); const { value: rawPage, loading: docLoading, error: docLoadError, - } = useAsync(async () => { - // do not automatically load same page again if URL has not changed, - // happens when generating new docs finishes - if (newerDocsExist && path === loadedPath) { - return null; + retry, + } = useRawPage(path, kind, namespace, name); + + useEffect(() => { + if (isSynced && newerDocsExist && path !== loadedPath) { + retry(); } - return techdocsStorageApi.getEntityDocs({ kind, namespace, name }, path); - }, [techdocsStorageApi, kind, namespace, name, path, isSynced]); + }); useEffect(() => { const updateSidebarPosition = () => { @@ -134,12 +135,12 @@ export const Reader = ({ entityId, onReady }: Props) => { onReady(); } // Pre-render - const transformedElement = transformer(rawPage as string, [ + const transformedElement = transformer(rawPage.content, [ sanitizeDOM(), addBaseUrl({ techdocsStorageApi, - entityId: entityId, - path, + entityId: rawPage.entityId, + path: rawPage.path, }), rewriteDocLinks(), removeMkdocsHeader(), @@ -304,16 +305,15 @@ export const Reader = ({ entityId, onReady }: Props) => { ]); }, [ rawPage, - entityId, navigate, onReady, shadowDomRef, - path, techdocsStorageApi, - theme, - kind, - namespace, - name, + theme.typography.fontFamily, + theme.palette.text.primary, + theme.palette.primary.main, + theme.palette.background.paper, + theme.palette.background.default, newerDocsExist, isSynced, configApi, diff --git a/plugins/techdocs/src/reader/components/TechDocsPage.tsx b/plugins/techdocs/src/reader/components/TechDocsPage.tsx index c15f3a6a44..338088be4d 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPage.tsx @@ -15,7 +15,7 @@ */ import { Content, Page, useApi } from '@backstage/core'; -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { useParams } from 'react-router-dom'; import { useAsync } from 'react-use'; import { techdocsApiRef } from '../../api'; @@ -40,9 +40,9 @@ export const TechDocsPage = () => { return techdocsApi.getEntityMetadata({ kind, namespace, name }); }, [kind, namespace, name, techdocsApi]); - const onReady = () => { + const onReady = useCallback(() => { setDocumentReady(true); - }; + }, [setDocumentReady]); return ( <Page themeId="documentation"> diff --git a/plugins/techdocs/src/reader/components/useRawPage.ts b/plugins/techdocs/src/reader/components/useRawPage.ts new file mode 100644 index 0000000000..1bc23d2a45 --- /dev/null +++ b/plugins/techdocs/src/reader/components/useRawPage.ts @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { EntityName } from '@backstage/catalog-model'; +import { useApi } from '@backstage/core'; +import { useAsyncRetry } from 'react-use'; +import { AsyncState } from 'react-use/lib/useAsync'; +import { techdocsStorageApiRef } from '../../api'; + +export type RawPage = { + content: string; + path: string; + entityId: EntityName; +}; + +export function useRawPage( + path: string, + kind: string, + namespace: string, + name: string, +): AsyncState<RawPage> & { + retry(): void; +} { + const techdocsStorageApi = useApi(techdocsStorageApiRef); + + return useAsyncRetry(async () => { + const content = await techdocsStorageApi.getEntityDocs( + { kind, namespace, name }, + path, + ); + + return { + content, + path, + entityId: { + kind, + name, + namespace, + }, + }; + }, [techdocsStorageApi, kind, namespace, name, path]); +} From cb8c848a38d2e100288b46ba767258e83f5d9b15 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Mon, 26 Apr 2021 17:16:59 +0200 Subject: [PATCH 157/262] Disable color transitions on links to avoid issues in dark mode Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/techdocs-red-donkeys-share.md | 5 +++++ plugins/techdocs/src/reader/components/Reader.tsx | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 .changeset/techdocs-red-donkeys-share.md diff --git a/.changeset/techdocs-red-donkeys-share.md b/.changeset/techdocs-red-donkeys-share.md new file mode 100644 index 0000000000..29d932d0b8 --- /dev/null +++ b/.changeset/techdocs-red-donkeys-share.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Disable color transitions on links to avoid issues in dark mode. diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index ff4f47dca0..14fcb43700 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -197,10 +197,21 @@ export const Reader = ({ entityId, onReady }: Props) => { } .md-nav--primary > .md-nav__title [for="none"] { padding-top: 0; - } + } } `, }), + injectCss({ + // Disable CSS animations on link colors as they lead to issues in dark + // mode. The dark mode color theme is applied later and theirfore there + // is always an animation from light to dark mode when navigation + // between pages. + css: ` + .md-nav__link, .md-typeset a, .md-typeset a::before, .md-typeset .headerlink { + transition: none; + } + `, + }), injectCss({ // Admonitions and others are using SVG masks to define icons. These // masks are defined as CSS variables. From e1e757569fbb2f3b9b30ab48229ec2ef97cc0c7f Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Mon, 26 Apr 2021 17:32:54 +0200 Subject: [PATCH 158/262] prefix changeset with search Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- .changeset/{odd-ads-invite.md => search-odd-ads-invite.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{odd-ads-invite.md => search-odd-ads-invite.md} (100%) diff --git a/.changeset/odd-ads-invite.md b/.changeset/search-odd-ads-invite.md similarity index 100% rename from .changeset/odd-ads-invite.md rename to .changeset/search-odd-ads-invite.md From 24c24f384a327632f92767406ac6b8eb7aae46d6 Mon Sep 17 00:00:00 2001 From: Brenda Sukh <brendasukh@gmail.com> Date: Mon, 26 Apr 2021 14:14:22 -0400 Subject: [PATCH 159/262] Add stability index for cost insights Signed-off-by: Brenda Sukh <brendasukh@gmail.com> --- docs/overview/stability-index.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/overview/stability-index.md b/docs/overview/stability-index.md index 4172e4d1b7..6882f3d6c2 100644 --- a/docs/overview/stability-index.md +++ b/docs/overview/stability-index.md @@ -153,6 +153,13 @@ re-exported from @backstage/core, and this package should not be used directly. Stability: See @backstage/core +### `cost-insights` [GitHub](https://github.com/backstage/backstage/tree/master/plugins/cost-insights) + +A frontend plugin that allows users to visualize, understand and optimize your +team's cloud costs. + +Stability: `1` + ### `create-app` [GitHub](https://github.com/backstage/backstage/tree/master/packages/create-app/) The CLI used to scaffold new Backstage projects. @@ -359,7 +366,7 @@ https://github.com/backstage/backstage/issues/2771. ### `tech-radar` [GitHub](https://github.com/backstage/backstage/tree/master/plugins/tech-radar/) -Visualize the your company's official guidelines of different areas of software +Visualize your company's official guidelines of different areas of software development. Stability: `0` From f639a09f835f8c1e0485a6a936a7115dadb6152f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 17:40:43 +0200 Subject: [PATCH 160/262] root: add api-extractor dependency and friends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gustaf Räntilä <g.rantila@gmail.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- package.json | 6 ++ yarn.lock | 162 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 159 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index d87b98fbdb..b946019c0a 100644 --- a/package.json +++ b/package.json @@ -39,10 +39,16 @@ "**/@roadiehq/**/@backstage/core": "*", "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*", + "**/@microsoft/api-extractor/typescript": "^4.0.3", "graphql-language-service-interface": "2.8.2", "graphql-language-service-parser": "1.9.0" }, "version": "1.0.0", + "dependencies": { + "@microsoft/api-extractor": "7.13.2-pr1916.0", + "@microsoft/api-documenter": "^7.12.16", + "@microsoft/api-extractor-model": "^7.12.5" + }, "devDependencies": { "@changesets/cli": "^2.14.0", "@octokit/openapi-types": "^2.2.0", diff --git a/yarn.lock b/yarn.lock index f2c2bee93c..98c3af5d2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3820,11 +3820,54 @@ dependencies: "@types/whatwg-streams" "^0.0.7" +"@microsoft/api-documenter@^7.12.16": + version "7.12.21" + resolved "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.12.21.tgz#cdafcd4575d42e55eb8ca338a3a5fb868f9d5872" + integrity sha512-XZQKnMppgkTHeGh92fQ7kidT2Bxr3o775Mo9gP21+kTQs3LnvukHmSnFwBTHTXpvOq1wnkbT430dRvxdayWECQ== + dependencies: + "@microsoft/api-extractor-model" "7.12.5" + "@microsoft/tsdoc" "0.12.24" + "@rushstack/node-core-library" "3.36.2" + "@rushstack/ts-command-line" "4.7.10" + colors "~1.2.1" + js-yaml "~3.13.1" + resolve "~1.17.0" + +"@microsoft/api-extractor-model@7.12.5", "@microsoft/api-extractor-model@^7.12.5", "@microsoft/api-extractor-model@workspace:*": + version "7.12.5" + resolved "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.12.5.tgz#28d2804865ceba9cd89ab4f05cff99d16fa6c9b8" + integrity sha512-oeHZW83JWjIVoCDvdwI5nsZGPxThbq4gZTLAYNeJGZE/mKEO0iayMPGmI3EllJBjwQsFvNVU+O/HGULhB2to/g== + dependencies: + "@microsoft/tsdoc" "0.12.24" + "@rushstack/node-core-library" "3.36.2" + +"@microsoft/api-extractor@7.13.2-pr1916.0": + version "7.13.2-pr1916.0" + resolved "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.13.2-pr1916.0.tgz#2e10cb928ea81b56cd5f63264da11f1f9b9310a5" + integrity sha512-0/HajL+NUixuNGMfFZbHmKJn5VEqiF45q2FXhu8UrggutdJ+9M6wZ++fejUHfxlC/WhQVrVVRtf4xvVM3oIW+A== + dependencies: + "@microsoft/api-extractor-model" "workspace:*" + "@microsoft/tsdoc" "0.12.24" + "@rushstack/node-core-library" "workspace:*" + "@rushstack/rig-package" "workspace:*" + "@rushstack/ts-command-line" "workspace:*" + colors "~1.2.1" + lodash "~4.17.15" + resolve "~1.17.0" + semver "~7.3.0" + source-map "~0.6.1" + typescript "~4.1.3" + "@microsoft/microsoft-graph-types@^1.25.0": version "1.25.0" resolved "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-1.25.0.tgz#1f543ebc029a115dd1d48a1ae99d7ddd5ee9af57" integrity sha512-RsuA+ROaU3voWzG9TVBkRKxmLatteRGduFDi5p0k3FUHho49rm9SvrA7DUyYbSXLy2xXRx9AnjKM9klYBeKEiQ== +"@microsoft/tsdoc@0.12.24": + version "0.12.24" + resolved "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.12.24.tgz#30728e34ebc90351dd3aff4e18d038eed2c3e098" + integrity sha512-Mfmij13RUTmHEMi9vRUhMXD7rnGR2VvxeNYtaGtaJ4redwwjT4UXYJ+nzmVJF7hhd4pn/Fx5sncDKxMVFJSWPg== + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -4368,6 +4411,39 @@ estree-walker "^2.0.1" picomatch "^2.2.2" +"@rushstack/node-core-library@3.36.2", "@rushstack/node-core-library@workspace:*": + version "3.36.2" + resolved "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.36.2.tgz#ba00d313577f9b06d5aafaa29da0d94e594874c0" + integrity sha512-5J8xSY/PuCKR+yfxS497l0PP43kBUeD86S4eS3RzrmMle04J4522MWal8mk1T1EIDpYpgi8qScannU9oVxoStA== + dependencies: + "@types/node" "10.17.13" + colors "~1.2.1" + fs-extra "~7.0.1" + import-lazy "~4.0.0" + jju "~1.4.0" + resolve "~1.17.0" + semver "~7.3.0" + timsort "~0.3.0" + z-schema "~3.18.3" + +"@rushstack/rig-package@workspace:*": + version "0.2.12" + resolved "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.2.12.tgz#c434d62b28e0418a040938226f8913971d0424c7" + integrity sha512-nbePcvF8hQwv0ql9aeQxcaMPK/h1OLAC00W7fWCRWIvD2MchZOE8jumIIr66HGrfG2X1sw++m/ZYI4D+BM5ovQ== + dependencies: + resolve "~1.17.0" + strip-json-comments "~3.1.1" + +"@rushstack/ts-command-line@4.7.10", "@rushstack/ts-command-line@workspace:*": + version "4.7.10" + resolved "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.7.10.tgz#a2ec6efb1945b79b496671ce90eb1be4f1397d31" + integrity sha512-8t042g8eerypNOEcdpxwRA3uCmz0duMo21rG4Z2mdz7JxJeylDmzjlU3wDdef2t3P1Z61JCdZB6fbm1Mh0zi7w== + dependencies: + "@types/argparse" "1.0.38" + argparse "~1.0.9" + colors "~1.2.1" + string-argv "~0.3.1" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -5578,6 +5654,11 @@ dependencies: "@types/glob" "*" +"@types/argparse@1.0.38": + version "1.0.38" + resolved "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" + integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== + "@types/aria-query@^4.2.0": version "4.2.0" resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" @@ -6317,6 +6398,11 @@ resolved "https://registry.npmjs.org/@types/node/-/node-14.14.32.tgz#90c5c4a8d72bbbfe53033f122341343249183448" integrity sha512-/Ctrftx/zp4m8JOujM5ZhwzlWLx22nbQJiVqz8/zE15gOeEW+uly3FSX4fGFpcfEvFzXcMCJwq9lGVWgyARXhg== +"@types/node@10.17.13": + version "10.17.13" + resolved "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c" + integrity sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg== + "@types/node@^10.1.0", "@types/node@^10.12.0": version "10.17.35" resolved "https://registry.npmjs.org/@types/node/-/node-10.17.35.tgz#58058f29b870e6ae57b20e4f6e928f02b7129f56" @@ -7813,7 +7899,7 @@ arg@^4.1.0: resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== -argparse@^1.0.10, argparse@^1.0.7: +argparse@^1.0.10, argparse@^1.0.7, argparse@~1.0.9: version "1.0.10" resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -9903,6 +9989,11 @@ colors@^1.1.2, colors@^1.2.1: resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +colors@~1.2.1: + version "1.2.5" + resolved "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz#89c7ad9a374bc030df8013241f68136ed8835afc" + integrity sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg== + colorspace@1.1.x: version "1.1.2" resolved "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" @@ -9951,7 +10042,7 @@ commander@2.3.0: resolved "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" integrity sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM= -commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@~2.20.3: +commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.7.1, commander@~2.20.3: version "2.20.3" resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -13552,7 +13643,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^7.0.1: +fs-extra@^7.0.1, fs-extra@~7.0.1: version "7.0.1" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -15200,6 +15291,11 @@ import-lazy@^2.1.0: resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= +import-lazy@~4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== + import-local@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -16602,6 +16698,11 @@ jest@^26.0.1: import-local "^3.0.2" jest-cli "^26.6.3" +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= + jmespath@0.15.0: version "0.15.0" resolved "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" @@ -16682,6 +16783,14 @@ js-yaml@^4.0.0: dependencies: argparse "^2.0.1" +js-yaml@~3.13.1: + version "3.13.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -17672,7 +17781,7 @@ lodash.flattendeep@^4.0.0: resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash.get@^4: +lodash.get@^4, lodash.get@^4.0.0: version "4.4.2" resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= @@ -17687,6 +17796,11 @@ lodash.isboolean@^3.0.3: resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= +lodash.isequal@^4.0.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + lodash.isinteger@^4.0.4: version "4.0.4" resolved "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" @@ -17772,7 +17886,7 @@ lodash@4.17.15: resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@4.x, lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.20, lodash@~4.17.4: +lodash@4.x, lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.15, lodash@~4.17.20, lodash@~4.17.4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -22990,6 +23104,13 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17 is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@~1.17.0: + version "1.17.0" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -23420,6 +23541,13 @@ semver@~5.3.0: resolved "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= +semver@~7.3.0: + version "7.3.5" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + send@0.17.1: version "0.17.1" resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -24300,7 +24428,7 @@ strict-uri-encode@^2.0.0: resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= -string-argv@0.3.1: +string-argv@0.3.1, string-argv@~0.3.1: version "0.3.1" resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== @@ -24526,7 +24654,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -25130,7 +25258,7 @@ timers-ext@^0.1.7: es5-ext "~0.10.46" next-tick "1" -timsort@^0.3.0: +timsort@^0.3.0, timsort@~0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= @@ -25632,7 +25760,7 @@ typescript-json-schema@^0.49.0: typescript "^4.1.3" yargs "^16.2.0" -typescript@^4.0.3, typescript@^4.1.3: +typescript@^4.0.3, typescript@^4.1.3, typescript@~4.1.3: version "4.2.3" resolved "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3" integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw== @@ -26198,6 +26326,11 @@ validate.io-number@^1.0.3: resolved "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz#f63ffeda248bf28a67a8d48e0e3b461a1665baf8" integrity sha1-9j/+2iSL8opnqNSODjtGGhZluvg= +validator@^8.0.0: + version "8.2.0" + resolved "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz#3c1237290e37092355344fef78c231249dab77b9" + integrity sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -27112,6 +27245,17 @@ yup@^0.29.3: synchronous-promise "^2.0.13" toposort "^2.0.2" +z-schema@~3.18.3: + version "3.18.4" + resolved "https://registry.npmjs.org/z-schema/-/z-schema-3.18.4.tgz#ea8132b279533ee60be2485a02f7e3e42541a9a2" + integrity sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw== + dependencies: + lodash.get "^4.0.0" + lodash.isequal "^4.0.0" + validator "^8.0.0" + optionalDependencies: + commander "^2.7.1" + zen-observable-ts@^0.8.21: version "0.8.21" resolved "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d" From 482256023b82bdb07afb48e900cf082c12d7a081 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 17:57:18 +0200 Subject: [PATCH 161/262] scripts: add api-extractor script that generates API reports and documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gustaf Räntilä <g.rantila@gmail.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- package.json | 2 + scripts/api-extractor.ts | 264 +++++++++++++++++++++++++++++++++++++++ scripts/tsconfig.json | 6 + 3 files changed, 272 insertions(+) create mode 100644 scripts/api-extractor.ts create mode 100644 scripts/tsconfig.json diff --git a/package.json b/package.json index b946019c0a..f1faad5de7 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "start": "yarn workspace example-app start", "start-backend": "yarn workspace example-backend start", "build": "lerna run build", + "build:api-reports": "tsc && ts-node -T -P scripts/tsconfig.json scripts/api-extractor.ts", + "build:api-docs": "yarn build:api-reports --docs", "tsc": "tsc", "tsc:full": "tsc --skipLibCheck false --incremental false", "clean": "backstage-cli clean && lerna run clean", diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts new file mode 100644 index 0000000000..1cab49750f --- /dev/null +++ b/scripts/api-extractor.ts @@ -0,0 +1,264 @@ +/* + * Copyright 2021 Spotify AB + * + * 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. + */ + +/* eslint-disable import/no-extraneous-dependencies */ + +// eslint-disable-next-line no-restricted-imports +import { resolve as resolvePath, join as joinPath, dirname } from 'path'; +import fs from 'fs-extra'; +import { + Extractor, + ExtractorConfig, + CompilerState, + ExtractorLogLevel, +} from '@microsoft/api-extractor'; +import { ApiPackage, ApiModel } from '@microsoft/api-extractor-model'; +import { MarkdownDocumenter } from '@microsoft/api-documenter/lib/documenters/MarkdownDocumenter'; + +const tmpDir = resolvePath(__dirname, '../node_modules/.cache/api-extractor'); + +/** + * Yup + */ +const { + PackageJsonLookup, +} = require('@rushstack/node-core-library/lib/PackageJsonLookup'); + +const old = PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor; +PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor = function tryGetPackageJsonFilePathForPatch( + path: string, +) { + if ( + path.includes('@material-ui') && + !dirname(path).endsWith('@material-ui') + ) { + return undefined; + } + return old.call(this, path); +}; + +const DOCUMENTED_PACKAGES = [ + 'packages/backend-common', + 'packages/catalog-client', + 'packages/catalog-model', + 'packages/cli-common', + 'packages/config', + 'packages/config-loader', + // 'packages/core', + // 'packages/core-api', + 'packages/dev-utils', + 'packages/errors', + 'packages/integration', + 'packages/integration-react', + 'packages/search-common', + 'packages/techdocs-common', + 'packages/test-utils', + 'packages/test-utils-core', + 'packages/theme', +]; + +interface ApiExtractionOptions { + packageDirs: string[]; + outputDir: string; + isLocalBuild: boolean; +} +async function runApiExtraction({ + packageDirs, + outputDir, + isLocalBuild, +}: ApiExtractionOptions) { + await fs.remove(outputDir); + + const entryPoints = packageDirs.map(packageDir => { + return resolvePath(__dirname, `../dist-types/${packageDir}/src/index.d.ts`); + }); + + let compilerState: CompilerState | undefined = undefined; + + for (const packageDir of packageDirs) { + console.log(`## Processing ${packageDir}`); + const projectFolder = resolvePath(__dirname, '..', packageDir); + const packagePath = resolvePath(__dirname, `../${packageDir}/package.json`); + + const extractorConfig = ExtractorConfig.prepare({ + configObject: { + mainEntryPointFilePath: resolvePath( + __dirname, + '../dist-types/packages/<unscopedPackageName>/src/index.d.ts', + ), + bundledPackages: [], + + compiler: { + tsconfigFilePath: resolvePath(__dirname, '../tsconfig.json'), + }, + + apiReport: { + enabled: true, + reportFileName: 'api-report.md', + reportFolder: projectFolder, + reportTempFolder: resolvePath(outputDir, '<unscopedPackageName>'), + }, + + docModel: { + enabled: true, + apiJsonFilePath: resolvePath( + outputDir, + '<unscopedPackageName>.api.json', + ), + }, + + dtsRollup: { + enabled: false, + }, + + tsdocMetadata: { + enabled: false, + }, + + messages: { + compilerMessageReporting: { + default: { + logLevel: 'warning' as ExtractorLogLevel.Warning, + addToApiReportFile: true, + }, + }, + extractorMessageReporting: { + default: { + logLevel: 'warning' as ExtractorLogLevel.Warning, + addToApiReportFile: true, + }, + }, + tsdocMessageReporting: { + default: { + logLevel: 'warning' as ExtractorLogLevel.Warning, + addToApiReportFile: true, + }, + }, + }, + + newlineKind: 'lf', + + projectFolder, + }, + configObjectFullPath: projectFolder, + packageJsonFullPath: packagePath, + }); + + if (!compilerState) { + compilerState = CompilerState.create(extractorConfig, { + additionalEntryPoints: entryPoints, + }); + } + + // Message verbosity can't be configured, so just skip the check instead + (Extractor as any)._checkCompilerCompatibility = () => {}; + + // Invoke API Extractor + const extractorResult = Extractor.invoke(extractorConfig, { + localBuild: isLocalBuild, + showVerboseMessages: false, + showDiagnostics: false, + compilerState, + }); + + if (!extractorResult.succeeded) { + throw new Error( + `API Extractor completed with ${extractorResult.errorCount} errors` + + ` and ${extractorResult.warningCount} warnings`, + ); + } + } +} + +function isComponentMember(member: any) { + // React components are annotated with @components, and we want to skip those + return Boolean(member.docComment.match(/\n\s*\**\s*@component/m)); +} + +async function buildDocs({ + inputDir, + outputDir, +}: { + inputDir: string; + outputDir: string; +}) { + const parseFile = async (filename: string): Promise<any> => { + console.log(`Reading ${filename}`); + return fs.readJson(resolvePath(inputDir, filename)); + }; + + const filenames = await fs.readdir(inputDir); + const serializedPackages = await Promise.all( + filenames + .filter(filename => filename.match(/\.api\.json$/i)) + .map(parseFile), + ); + + const newModel = new ApiModel(); + for (const serialized of serializedPackages) { + serialized.members[0].members = serialized.members[0].members.filter( + member => !isComponentMember(member), + ); + + const pkg = ApiPackage.deserialize( + serialized, + serialized.metadata, + ) as ApiPackage; + newModel.addMember(pkg); + } + + await fs.remove(outputDir); + await fs.ensureDir(outputDir); + + const documenter = new MarkdownDocumenter({ + apiModel: newModel, + documenterConfig: { + outputTarget: 'markdown', + newlineKind: '\n', + // De ba dålig kod + configFilePath: '', + configFile: {}, + } as any, + outputFolder: outputDir, + }); + + documenter.generateFiles(); +} + +async function main() { + const isCiBuild = process.argv.includes('--ci'); + const isDocsBuild = process.argv.includes('--docs'); + + console.log('# Generating package API reports'); + await runApiExtraction({ + packageDirs: DOCUMENTED_PACKAGES, + outputDir: tmpDir, + isLocalBuild: !isCiBuild, + }); + + if (isDocsBuild) { + console.log('# Generating package documentation'); + await buildDocs({ + inputDir: tmpDir, + outputDir: resolvePath(__dirname, '..', 'docs/reference'), + }); + } +} + +main().catch(error => { + console.error(error.stack || String(error)); + process.exit(1); +}); diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json new file mode 100644 index 0000000000..c8d842173c --- /dev/null +++ b/scripts/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "module": "CommonJS" + } +} From 26dee60729efac52a53500086f5c0c4649d747e7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 18:13:00 +0200 Subject: [PATCH 162/262] scripts/api-extractor: better feedback for api-report mismatches Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- scripts/api-extractor.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 1cab49750f..e232170e9d 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -171,6 +171,28 @@ async function runApiExtraction({ localBuild: isLocalBuild, showVerboseMessages: false, showDiagnostics: false, + messageCallback(message) { + if ( + message.text.includes( + 'You have changed the public API signature for this project.', + ) + ) { + console.log(''); + console.log( + '*************************************************************************************', + ); + console.log( + '* You have uncommitted changes to the public API of a package. *', + ); + console.log( + '* To solve this, run `yarn build:api-reports` and commit all api-report.md changes. *', + ); + console.log( + '*************************************************************************************', + ); + console.log(''); + } + }, compilerState, }); From fecf70ae1aa2747e81a5c28ef3dcf8728505ee32 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 18:23:23 +0200 Subject: [PATCH 163/262] workflows: validate api reports in CI Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .github/workflows/ci.yml | 3 +++ package.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2337a70e2c..0a6d0f8589 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,6 +85,9 @@ jobs: - name: type checking and declarations run: yarn tsc:full + - name: check api reports + run: yarn build:api-reports:only --ci + - name: build changed packages if: ${{ steps.yarn-lock.outcome == 'success' }} run: yarn lerna -- run build --since origin/master --include-dependencies diff --git a/package.json b/package.json index f1faad5de7..b0f79031de 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "start": "yarn workspace example-app start", "start-backend": "yarn workspace example-backend start", "build": "lerna run build", - "build:api-reports": "tsc && ts-node -T -P scripts/tsconfig.json scripts/api-extractor.ts", + "build:api-reports": "tsc && yarn build:api-reports:only", + "build:api-reports:only": "ts-node -T -P scripts/tsconfig.json scripts/api-extractor.ts", "build:api-docs": "yarn build:api-reports --docs", "tsc": "tsc", "tsc:full": "tsc --skipLibCheck false --incremental false", From a904d8ba5e82d0d8e60eba9b438f7970596e673d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 18:39:21 +0200 Subject: [PATCH 164/262] packages: add api-reports for all included packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gustaf Räntilä <g.rantila@gmail.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .prettierignore | 1 + packages/backend-common/api-report.md | 469 +++++++++++++ packages/catalog-client/api-report.md | 105 +++ packages/catalog-model/api-report.md | 811 +++++++++++++++++++++++ packages/cli-common/api-report.md | 35 + packages/config-loader/api-report.md | 72 ++ packages/config/api-report.md | 112 ++++ packages/dev-utils/api-report.md | 39 ++ packages/errors/api-report.md | 125 ++++ packages/integration-react/api-report.md | 32 + packages/integration/api-report.md | 414 ++++++++++++ packages/search-common/api-report.md | 70 ++ packages/techdocs-common/api-report.md | 259 ++++++++ packages/test-utils-core/api-report.md | 113 ++++ packages/test-utils/api-report.md | 109 +++ packages/theme/api-report.md | 130 ++++ 16 files changed, 2896 insertions(+) create mode 100644 packages/backend-common/api-report.md create mode 100644 packages/catalog-client/api-report.md create mode 100644 packages/catalog-model/api-report.md create mode 100644 packages/cli-common/api-report.md create mode 100644 packages/config-loader/api-report.md create mode 100644 packages/config/api-report.md create mode 100644 packages/dev-utils/api-report.md create mode 100644 packages/errors/api-report.md create mode 100644 packages/integration-react/api-report.md create mode 100644 packages/integration/api-report.md create mode 100644 packages/search-common/api-report.md create mode 100644 packages/techdocs-common/api-report.md create mode 100644 packages/test-utils-core/api-report.md create mode 100644 packages/test-utils/api-report.md create mode 100644 packages/theme/api-report.md diff --git a/.prettierignore b/.prettierignore index c4e675a5d7..e60d54a466 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,6 +4,7 @@ microsite coverage *.hbs templates +api-report.md plugins/scaffolder-backend/sample-templates .vscode dist-types diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md new file mode 100644 index 0000000000..bdef061eda --- /dev/null +++ b/packages/backend-common/api-report.md @@ -0,0 +1,469 @@ +## API Report File for "@backstage/backend-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { AzureIntegration } from '@backstage/integration'; +import { BitbucketIntegration } from '@backstage/integration'; +import { Config } from '@backstage/config'; +import { ConfigReader } from '@backstage/config'; +import cors from 'cors'; +import Docker from 'dockerode'; +import { ErrorRequestHandler } from 'express'; +import express from 'express'; +import { Format } from 'logform'; +import { GithubCredentialsProvider } from '@backstage/integration'; +import { GitHubIntegration } from '@backstage/integration'; +import { GitLabIntegration } from '@backstage/integration'; +import * as http from 'http'; +import { Knex } from 'knex'; +import { Logger } from 'winston'; +import { MergeResult } from 'isomorphic-git'; +import { PushResult } from 'isomorphic-git'; +import { Readable } from 'stream'; +import { ReadCommitResult } from 'isomorphic-git'; +import { RequestHandler } from 'express'; +import { Router } from 'express'; +import { Server } from 'http'; +import * as winston from 'winston'; +import { Writable } from 'stream'; + +// Warning: (ae-missing-release-tag) "AzureUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class AzureUrlReader implements UrlReader { + constructor(integration: AzureIntegration, deps: { + treeResponseFactory: ReadTreeResponseFactory; + }); + // Warning: (ae-forgotten-export) The symbol "ReaderFactory" needs to be exported by the entry point index.d.ts + // + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise<Buffer>; + // Warning: (ae-forgotten-export) The symbol "ReadTreeOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>; + // Warning: (ae-forgotten-export) The symbol "SearchOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + search(url: string, options?: SearchOptions): Promise<SearchResponse>; + // (undocumented) + toString(): string; +} + +// Warning: (ae-missing-release-tag) "BitbucketUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class BitbucketUrlReader implements UrlReader { + constructor(integration: BitbucketIntegration, deps: { + treeResponseFactory: ReadTreeResponseFactory; + }); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise<Buffer>; + // (undocumented) + readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>; + // (undocumented) + search(url: string, options?: SearchOptions): Promise<SearchResponse>; + // (undocumented) + toString(): string; +} + +// Warning: (ae-missing-release-tag) "coloredFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const coloredFormat: Format; + +// Warning: (ae-missing-release-tag) "createDatabase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated +export const createDatabase: typeof createDatabaseClient; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "createDatabaseClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function createDatabaseClient(dbConfig: Config, overrides?: Partial<Knex.Config>): Knex<any, unknown[]>; + +// Warning: (ae-missing-release-tag) "createRootLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createRootLogger(options?: winston.LoggerOptions, env?: NodeJS.ProcessEnv): winston.Logger; + +// Warning: (ae-forgotten-export) The symbol "ServiceBuilderImpl" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "createServiceBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function createServiceBuilder(_module: NodeModule): ServiceBuilderImpl; + +// Warning: (ae-forgotten-export) The symbol "StatusCheckRouterOptions" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "createStatusCheckRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createStatusCheckRouter(options: StatusCheckRouterOptions): Promise<express.Router>; + +// Warning: (ae-missing-release-tag) "ensureDatabaseExists" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function ensureDatabaseExists(dbConfig: Config, ...databases: Array<string>): Promise<void>; + +// Warning: (ae-missing-release-tag) "errorHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function errorHandler(options?: ErrorHandlerOptions): ErrorRequestHandler; + +// Warning: (ae-missing-release-tag) "ErrorHandlerOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ErrorHandlerOptions = { + showStackTraces?: boolean; + logger?: Logger; + logClientErrors?: boolean; +}; + +// Warning: (ae-missing-release-tag) "getRootLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getRootLogger(): winston.Logger; + +// Warning: (ae-missing-release-tag) "getVoidLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getVoidLogger(): winston.Logger; + +// Warning: (ae-missing-release-tag) "Git" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Git { + // (undocumented) + add({ dir, filepath, }: { + dir: string; + filepath: string; + }): Promise<void>; + // (undocumented) + addRemote({ dir, url, remote, }: { + dir: string; + remote: string; + url: string; + }): Promise<void>; + // (undocumented) + clone({ url, dir, ref, }: { + url: string; + dir: string; + ref?: string; + }): Promise<void>; + // (undocumented) + commit({ dir, message, author, committer, }: { + dir: string; + message: string; + author: { + name: string; + email: string; + }; + committer: { + name: string; + email: string; + }; + }): Promise<string>; + // (undocumented) + currentBranch({ dir, fullName, }: { + dir: string; + fullName?: boolean; + }): Promise<string | undefined>; + // (undocumented) + fetch({ dir, remote, }: { + dir: string; + remote?: string; + }): Promise<void>; + // (undocumented) + static fromAuth: ({ username, password, logger, }: { + username?: string | undefined; + password?: string | undefined; + logger?: Logger | undefined; + }) => Git; + // (undocumented) + init({ dir }: { + dir: string; + }): Promise<void>; + // (undocumented) + merge({ dir, theirs, ours, author, committer, }: { + dir: string; + theirs: string; + ours?: string; + author: { + name: string; + email: string; + }; + committer: { + name: string; + email: string; + }; + }): Promise<MergeResult>; + // (undocumented) + push({ dir, remote }: { + dir: string; + remote: string; + }): Promise<PushResult>; + // (undocumented) + readCommit({ dir, sha, }: { + dir: string; + sha: string; + }): Promise<ReadCommitResult>; + // (undocumented) + resolveRef({ dir, ref, }: { + dir: string; + ref: string; + }): Promise<string>; +} + +// Warning: (ae-missing-release-tag) "GithubUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class GithubUrlReader implements UrlReader { + constructor(integration: GitHubIntegration, deps: { + treeResponseFactory: ReadTreeResponseFactory; + credentialsProvider: GithubCredentialsProvider; + }); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise<Buffer>; + // (undocumented) + readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>; + // (undocumented) + search(url: string, options?: SearchOptions): Promise<SearchResponse>; + // (undocumented) + toString(): string; +} + +// Warning: (ae-missing-release-tag) "GitlabUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class GitlabUrlReader implements UrlReader { + constructor(integration: GitLabIntegration, deps: { + treeResponseFactory: ReadTreeResponseFactory; + }); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise<Buffer>; + // (undocumented) + readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>; + // (undocumented) + search(url: string, options?: SearchOptions): Promise<SearchResponse>; + // (undocumented) + toString(): string; +} + +// Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "loadBackendConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function loadBackendConfig(options: Options): Promise<Config>; + +// Warning: (ae-missing-release-tag) "notFoundHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function notFoundHandler(): RequestHandler; + +// Warning: (ae-missing-release-tag) "PluginDatabaseManager" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface PluginDatabaseManager { + getClient(): Promise<Knex>; +} + +// Warning: (ae-missing-release-tag) "PluginEndpointDiscovery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PluginEndpointDiscovery = { + getBaseUrl(pluginId: string): Promise<string>; + getExternalBaseUrl(pluginId: string): Promise<string>; +}; + +// Warning: (ae-missing-release-tag) "ReadTreeResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ReadTreeResponse = { + files(): Promise<ReadTreeResponseFile[]>; + archive(): Promise<NodeJS.ReadableStream>; + dir(options?: ReadTreeResponseDirOptions): Promise<string>; + etag: string; +}; + +// Warning: (ae-missing-release-tag) "ReadTreeResponseFile" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ReadTreeResponseFile = { + path: string; + content(): Promise<Buffer>; +}; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "requestLoggingHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function requestLoggingHandler(logger?: Logger): RequestHandler; + +// Warning: (ae-missing-release-tag) "resolvePackagePath" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function resolvePackagePath(name: string, ...paths: string[]): string; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (ae-forgotten-export) The symbol "RunDockerContainerOptions" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "runDockerContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const runDockerContainer: ({ imageName, args, logStream, dockerClient, mountDirs, workingDir, envVars, createOptions, }: RunDockerContainerOptions) => Promise<{ + error: any; + statusCode: any; +}>; + +// Warning: (ae-missing-release-tag) "SearchResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type SearchResponse = { + files: SearchResponseFile[]; + etag: string; +}; + +// Warning: (ae-missing-release-tag) "SearchResponseFile" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type SearchResponseFile = { + url: string; + content(): Promise<Buffer>; +}; + +// Warning: (ae-missing-release-tag) "ServiceBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ServiceBuilder = { + loadConfig(config: ConfigReader): ServiceBuilder; + setPort(port: number): ServiceBuilder; + setHost(host: string): ServiceBuilder; + setLogger(logger: Logger): ServiceBuilder; + enableCors(options: cors.CorsOptions): ServiceBuilder; + setHttpsSettings(settings: HttpsSettings): ServiceBuilder; + addRouter(root: string, router: Router | RequestHandler): ServiceBuilder; + start(): Promise<Server>; +}; + +// Warning: (ae-missing-release-tag) "setRootLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function setRootLogger(newLogger: winston.Logger): void; + +// Warning: (ae-missing-release-tag) "SingleConnectionDatabaseManager" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class SingleConnectionDatabaseManager { + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + forPlugin(pluginId: string): PluginDatabaseManager; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + static fromConfig(config: Config): SingleConnectionDatabaseManager; + } + +// Warning: (ae-missing-release-tag) "SingleHostDiscovery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class SingleHostDiscovery implements PluginEndpointDiscovery { + static fromConfig(config: Config, options?: { + basePath?: string; + }): SingleHostDiscovery; + // (undocumented) + getBaseUrl(pluginId: string): Promise<string>; + // (undocumented) + getExternalBaseUrl(pluginId: string): Promise<string>; + } + +// Warning: (ae-missing-release-tag) "StatusCheck" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type StatusCheck = () => Promise<any>; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "statusCheckHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function statusCheckHandler(options?: StatusCheckHandlerOptions): Promise<RequestHandler>; + +// Warning: (ae-missing-release-tag) "StatusCheckHandlerOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface StatusCheckHandlerOptions { + statusCheck?: StatusCheck; +} + +// Warning: (ae-missing-release-tag) "UrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type UrlReader = { + read(url: string): Promise<Buffer>; + readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>; + search(url: string, options?: SearchOptions): Promise<SearchResponse>; +}; + +// Warning: (ae-missing-release-tag) "UrlReaders" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class UrlReaders { + // Warning: (ae-forgotten-export) The symbol "CreateOptions" needs to be exported by the entry point index.d.ts + static create({ logger, config, factories }: CreateOptions): UrlReader; + static default({ logger, config, factories }: CreateOptions): UrlReader; +} + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "useHotCleanup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function useHotCleanup(_module: NodeModule, cancelEffect: () => void): void; + +// Warning: (tsdoc-undefined-tag) The TSDoc tag "@warning" is not defined in this configuration +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "useHotMemoize" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function useHotMemoize<T>(_module: NodeModule, valueFactory: () => T): T; + + +// Warnings were encountered during analysis: +// +// src/middleware/errorHandler.ts:47:24 - (tsdoc-malformed-html-name) Invalid HTML element: A space is not allowed here +// src/reading/AzureUrlReader.ts:53:30 - (ae-forgotten-export) The symbol "ReadTreeResponseFactory" needs to be exported by the entry point index.d.ts +// src/reading/types.ts:87:3 - (ae-forgotten-export) The symbol "ReadTreeResponseDirOptions" needs to be exported by the entry point index.d.ts +// src/service/types.ts:28:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/service/types.ts:39:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/service/types.ts:48:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/service/types.ts:57:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/service/types.ts:67:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/service/types.ts:76:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/service/types.ts:78:3 - (ae-forgotten-export) The symbol "HttpsSettings" needs to be exported by the entry point index.d.ts +// src/service/types.ts:83:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/service/types.ts:84:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md new file mode 100644 index 0000000000..fe12d3a62c --- /dev/null +++ b/packages/catalog-client/api-report.md @@ -0,0 +1,105 @@ +## API Report File for "@backstage/catalog-client" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { Entity } from '@backstage/catalog-model'; +import { EntityName } from '@backstage/catalog-model'; +import { Location as Location_2 } from '@backstage/catalog-model'; + +// Warning: (ae-missing-release-tag) "AddLocationRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AddLocationRequest = { + type?: string; + target: string; + dryRun?: boolean; + presence?: 'optional' | 'required'; +}; + +// Warning: (ae-missing-release-tag) "AddLocationResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AddLocationResponse = { + location: Location_2; + entities: Entity[]; +}; + +// Warning: (ae-missing-release-tag) "CatalogApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface CatalogApi { + // (undocumented) + addLocation(location: AddLocationRequest, options?: CatalogRequestOptions): Promise<AddLocationResponse>; + // Warning: (ae-forgotten-export) The symbol "CatalogRequestOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getEntities(request?: CatalogEntitiesRequest, options?: CatalogRequestOptions): Promise<CatalogListResponse<Entity>>; + // (undocumented) + getEntityByName(name: EntityName, options?: CatalogRequestOptions): Promise<Entity | undefined>; + // (undocumented) + getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + // (undocumented) + getLocationById(id: String, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + // (undocumented) + getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + // (undocumented) + removeEntityByUid(uid: string, options?: CatalogRequestOptions): Promise<void>; + // (undocumented) + removeLocationById(id: string, options?: CatalogRequestOptions): Promise<void>; +} + +// Warning: (ae-missing-release-tag) "CatalogClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class CatalogClient implements CatalogApi { + constructor(options: { + discoveryApi: DiscoveryApi; + }); + // (undocumented) + addLocation({ type, target, dryRun, presence }: AddLocationRequest, options?: CatalogRequestOptions): Promise<AddLocationResponse>; + // (undocumented) + getEntities(request?: CatalogEntitiesRequest, options?: CatalogRequestOptions): Promise<CatalogListResponse<Entity>>; + // (undocumented) + getEntityByName(compoundName: EntityName, options?: CatalogRequestOptions): Promise<Entity | undefined>; + // (undocumented) + getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + // (undocumented) + getLocationById(id: String, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + // (undocumented) + getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + // (undocumented) + removeEntityByUid(uid: string, options?: CatalogRequestOptions): Promise<void>; + // (undocumented) + removeLocationById(id: string, options?: CatalogRequestOptions): Promise<void>; + } + +// Warning: (ae-missing-release-tag) "CatalogEntitiesRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type CatalogEntitiesRequest = { + filter?: Record<string, string | string[]> | undefined; + fields?: string[] | undefined; +}; + +// Warning: (ae-missing-release-tag) "CatalogListResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type CatalogListResponse<T> = { + items: T[]; +}; + + +// Warnings were encountered during analysis: +// +// src/CatalogClient.ts:40:26 - (ae-forgotten-export) The symbol "DiscoveryApi" needs to be exported by the entry point index.d.ts +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md new file mode 100644 index 0000000000..b3e3303589 --- /dev/null +++ b/packages/catalog-model/api-report.md @@ -0,0 +1,811 @@ +## API Report File for "@backstage/catalog-model" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { JsonObject } from '@backstage/config'; +import { JSONSchema7 } from 'json-schema'; +import { JsonValue } from '@backstage/config'; +import * as yup from 'yup'; + +// Warning: (ae-missing-release-tag) "analyzeLocationSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const analyzeLocationSchema: yup.ObjectSchema<{ + location: LocationSpec; +}, object>; + +// Warning: (ae-missing-release-tag) "ApiEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface ApiEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND; + // (undocumented) + spec: { + type: string; + lifecycle: string; + owner: string; + definition: string; + system?: string; + }; +} + +export { ApiEntityV1alpha1 as ApiEntity } + +export { ApiEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "apiEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const apiEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "CommonValidatorFunctions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class CommonValidatorFunctions { + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + static isJsonSafe(value: unknown): boolean; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool + static isValidDnsLabel(value: unknown): boolean; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool + static isValidDnsSubdomain(value: unknown): boolean; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + static isValidPrefixAndOrSuffix(value: unknown, separator: string, isValidPrefix: (value: string) => boolean, isValidSuffix: (value: string) => boolean): boolean; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + static isValidString(value: unknown): boolean; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + static isValidUrl(value: unknown): boolean; +} + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-forgotten-export) The symbol "EntityRefContext" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "compareEntityToRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function compareEntityToRef(entity: Entity, ref: EntityRef | EntityName, context?: EntityRefContext): boolean; + +// Warning: (ae-missing-release-tag) "ComponentEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface ComponentEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_2[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_2; + // (undocumented) + spec: { + type: string; + lifecycle: string; + owner: string; + subcomponentOf?: string; + providesApis?: string[]; + consumesApis?: string[]; + system?: string; + }; +} + +export { ComponentEntityV1alpha1 as ComponentEntity } + +export { ComponentEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "componentEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const componentEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "DefaultNamespaceEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class DefaultNamespaceEntityPolicy implements EntityPolicy { + constructor(namespace?: string); + // (undocumented) + enforce(entity: Entity): Promise<Entity>; + } + +// Warning: (ae-missing-release-tag) "DomainEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface DomainEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_3[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_3; + // (undocumented) + spec: { + owner: string; + }; +} + +export { DomainEntityV1alpha1 as DomainEntity } + +export { DomainEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "domainEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const domainEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "EDIT_URL_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const EDIT_URL_ANNOTATION = "backstage.io/edit-url"; + +// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool +// Warning: (ae-missing-release-tag) "Entity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type Entity = { + apiVersion: string; + kind: string; + metadata: EntityMeta; + spec?: JsonObject; + relations?: EntityRelation[]; +}; + +// Warning: (ae-missing-release-tag) "ENTITY_DEFAULT_NAMESPACE" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const ENTITY_DEFAULT_NAMESPACE = "default"; + +// Warning: (ae-missing-release-tag) "ENTITY_META_GENERATED_FIELDS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const ENTITY_META_GENERATED_FIELDS: readonly ["uid", "etag", "generation"]; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "entityHasChanges" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function entityHasChanges(previous: Entity, next: Entity): boolean; + +// Warning: (ae-missing-release-tag) "EntityLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EntityLink = { + url: string; + title?: string; + icon?: string; +}; + +// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool +// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool +// Warning: (ae-missing-release-tag) "EntityMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EntityMeta = JsonObject & { + uid?: string; + etag?: string; + generation?: number; + name: string; + namespace?: string; + description?: string; + labels?: Record<string, string>; + annotations?: Record<string, string>; + tags?: string[]; + links?: EntityLink[]; +}; + +// Warning: (ae-missing-release-tag) "EntityName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EntityName = { + kind: string; + namespace: string; + name: string; +}; + +// Warning: (ae-missing-release-tag) "EntityPolicies" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const EntityPolicies: { + allOf(policies: EntityPolicy[]): AllEntityPolicies; + oneOf(policies: EntityPolicy[]): AnyEntityPolicy; +}; + +// Warning: (ae-missing-release-tag) "EntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EntityPolicy = { + enforce(entity: Entity): Promise<Entity | undefined>; +}; + +// Warning: (ae-missing-release-tag) "EntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EntityRef = string | { + kind?: string; + namespace?: string; + name: string; +}; + +// Warning: (ae-missing-release-tag) "EntityRelation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EntityRelation = { + type: string; + target: EntityName; +}; + +// Warning: (ae-missing-release-tag) "EntityRelationSpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EntityRelationSpec = { + source: EntityName; + type: string; + target: EntityName; +}; + +// Warning: (ae-missing-release-tag) "FieldFormatEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class FieldFormatEntityPolicy implements EntityPolicy { + constructor(validators?: Validators); + // (undocumented) + enforce(entity: Entity): Promise<Entity>; + } + +// Warning: (ae-missing-release-tag) "generateEntityEtag" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function generateEntityEtag(): string; + +// Warning: (ae-missing-release-tag) "generateEntityUid" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function generateEntityUid(): string; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "generateUpdatedEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function generateUpdatedEntity(previous: Entity, next: Entity): Entity; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getEntityName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getEntityName(entity: Entity): EntityName; + +// Warning: (ae-missing-release-tag) "GroupEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface GroupEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_4[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_4; + // (undocumented) + spec: { + type: string; + profile?: { + displayName?: string; + email?: string; + picture?: string; + }; + parent?: string; + children: string[]; + members?: string[]; + }; +} + +export { GroupEntityV1alpha1 as GroupEntity } + +export { GroupEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "groupEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const groupEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "JSONSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type JSONSchema = JSONSchema7 & { + [key in string]?: JsonValue; +}; + +// Warning: (ae-missing-release-tag) "KindValidator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type KindValidator = { + check(entity: Entity): Promise<boolean>; +}; + +// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool +// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool +// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool +// Warning: (ae-missing-release-tag) "KubernetesValidatorFunctions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class KubernetesValidatorFunctions { + // (undocumented) + static isValidAnnotationKey(value: unknown): boolean; + // (undocumented) + static isValidAnnotationValue(value: unknown): boolean; + // (undocumented) + static isValidApiVersion(value: unknown): boolean; + // (undocumented) + static isValidKind(value: unknown): boolean; + // (undocumented) + static isValidLabelKey(value: unknown): boolean; + // (undocumented) + static isValidLabelValue(value: unknown): boolean; + // (undocumented) + static isValidNamespace(value: unknown): boolean; + // (undocumented) + static isValidObjectName(value: unknown): boolean; +} + +// Warning: (ae-missing-release-tag) "Location" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +type Location_2 = { + id: string; +} & LocationSpec; + +export { Location_2 as Location } + +// Warning: (ae-missing-release-tag) "LOCATION_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const LOCATION_ANNOTATION = "backstage.io/managed-by-location"; + +// Warning: (ae-missing-release-tag) "LocationEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface LocationEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_5[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_5; + // (undocumented) + spec: { + type?: string; + target?: string; + targets?: string[]; + }; +} + +export { LocationEntityV1alpha1 as LocationEntity } + +export { LocationEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "locationEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const locationEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "locationSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const locationSchema: yup.ObjectSchema<Location_2, object>; + +// Warning: (ae-missing-release-tag) "LocationSpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type LocationSpec = { + type: string; + target: string; + presence?: 'optional' | 'required'; +}; + +// Warning: (ae-missing-release-tag) "locationSpecSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const locationSpecSchema: yup.ObjectSchema<LocationSpec, object>; + +// Warning: (ae-missing-release-tag) "makeValidator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function makeValidator(overrides?: Partial<Validators>): Validators; + +// Warning: (ae-missing-release-tag) "NoForeignRootFieldsEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class NoForeignRootFieldsEntityPolicy implements EntityPolicy { + constructor(knownFields?: string[]); + // (undocumented) + enforce(entity: Entity): Promise<Entity>; + } + +// Warning: (ae-missing-release-tag) "ORIGIN_LOCATION_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ORIGIN_LOCATION_ANNOTATION = "backstage.io/managed-by-origin-location"; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "parseEntityName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function parseEntityName(ref: EntityRef, context?: EntityRefContext): EntityName; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "parseEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "parseEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "parseEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function parseEntityRef(ref: EntityRef, context?: { + defaultKind: string; + defaultNamespace: string; +}): { + kind: string; + namespace: string; + name: string; +}; + +// @public (undocumented) +export function parseEntityRef(ref: EntityRef, context?: { + defaultKind: string; +}): { + kind: string; + namespace?: string; + name: string; +}; + +// @public (undocumented) +export function parseEntityRef(ref: EntityRef, context?: { + defaultNamespace: string; +}): { + kind?: string; + namespace: string; + name: string; +}; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (ae-missing-release-tag) "parseLocationReference" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function parseLocationReference(ref: string): { + type: string; + target: string; +}; + +// Warning: (ae-missing-release-tag) "RELATION_API_CONSUMED_BY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_API_CONSUMED_BY = "apiConsumedBy"; + +// Warning: (ae-missing-release-tag) "RELATION_API_PROVIDED_BY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_API_PROVIDED_BY = "apiProvidedBy"; + +// Warning: (ae-missing-release-tag) "RELATION_CHILD_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_CHILD_OF = "childOf"; + +// Warning: (ae-missing-release-tag) "RELATION_CONSUMES_API" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const RELATION_CONSUMES_API = "consumesApi"; + +// Warning: (ae-missing-release-tag) "RELATION_DEPENDENCY_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_DEPENDENCY_OF = "dependencyOf"; + +// Warning: (ae-missing-release-tag) "RELATION_DEPENDS_ON" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const RELATION_DEPENDS_ON = "dependsOn"; + +// Warning: (ae-missing-release-tag) "RELATION_HAS_MEMBER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_HAS_MEMBER = "hasMember"; + +// Warning: (ae-missing-release-tag) "RELATION_HAS_PART" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_HAS_PART = "hasPart"; + +// Warning: (ae-missing-release-tag) "RELATION_MEMBER_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const RELATION_MEMBER_OF = "memberOf"; + +// Warning: (ae-missing-release-tag) "RELATION_OWNED_BY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const RELATION_OWNED_BY = "ownedBy"; + +// Warning: (ae-missing-release-tag) "RELATION_OWNER_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_OWNER_OF = "ownerOf"; + +// Warning: (ae-missing-release-tag) "RELATION_PARENT_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const RELATION_PARENT_OF = "parentOf"; + +// Warning: (ae-missing-release-tag) "RELATION_PART_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const RELATION_PART_OF = "partOf"; + +// Warning: (ae-missing-release-tag) "RELATION_PROVIDES_API" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const RELATION_PROVIDES_API = "providesApi"; + +// Warning: (ae-missing-release-tag) "ResourceEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface ResourceEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_6[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_6; + // (undocumented) + spec: { + type: string; + owner: string; + system?: string; + }; +} + +export { ResourceEntityV1alpha1 as ResourceEntity } + +export { ResourceEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "resourceEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const resourceEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "schemaValidator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated (undocumented) +export function schemaValidator(kind: string, apiVersion: readonly string[], schema: yup.Schema<any>): KindValidator; + +// Warning: (ae-missing-release-tag) "SchemaValidEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class SchemaValidEntityPolicy implements EntityPolicy { + // (undocumented) + enforce(entity: Entity): Promise<Entity>; + } + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "serializeEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated +export function serializeEntityRef(ref: Entity | { + kind?: string; + namespace?: string; + name: string; +}): EntityRef; + +// Warning: (ae-missing-release-tag) "SOURCE_LOCATION_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const SOURCE_LOCATION_ANNOTATION = "backstage.io/source-location"; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "stringifyEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function stringifyEntityRef(ref: Entity | { + kind: string; + namespace?: string; + name: string; +}): string; + +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "stringifyLocationReference" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function stringifyLocationReference(ref: { + type: string; + target: string; +}): string; + +// Warning: (ae-missing-release-tag) "SystemEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface SystemEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_7[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_7; + // (undocumented) + spec: { + owner: string; + domain?: string; + }; +} + +export { SystemEntityV1alpha1 as SystemEntity } + +export { SystemEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "systemEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const systemEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "TemplateEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface TemplateEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_8[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_8; + // (undocumented) + spec: { + type: string; + templater: string; + path?: string; + schema: JSONSchema; + }; +} + +export { TemplateEntityV1alpha1 as TemplateEntity } + +export { TemplateEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "templateEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const templateEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "TemplateEntityV1beta2" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface TemplateEntityV1beta2 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_9[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_9; + // (undocumented) + metadata: EntityMeta & { + title?: string; + }; + // (undocumented) + spec: { + type: string; + parameters?: JsonObject | JsonObject[]; + steps: Array<{ + id?: string; + name?: string; + action: string; + parameters?: JsonObject; + }>; + output?: { + [name: string]: string; + }; + }; +} + +// Warning: (ae-missing-release-tag) "templateEntityV1beta2Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const templateEntityV1beta2Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "UserEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface UserEntityV1alpha1 extends Entity { + // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + apiVersion: typeof API_VERSION_10[number]; + // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kind: typeof KIND_10; + // (undocumented) + spec: { + profile?: { + displayName?: string; + email?: string; + picture?: string; + }; + memberOf: string[]; + }; +} + +export { UserEntityV1alpha1 as UserEntity } + +export { UserEntityV1alpha1 } + +// Warning: (ae-missing-release-tag) "userEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const userEntityV1alpha1Validator: KindValidator; + +// Warning: (ae-missing-release-tag) "Validators" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type Validators = { + isValidApiVersion(value: unknown): boolean; + isValidKind(value: unknown): boolean; + isValidEntityName(value: unknown): boolean; + isValidNamespace(value: unknown): boolean; + isValidLabelKey(value: unknown): boolean; + isValidLabelValue(value: unknown): boolean; + isValidAnnotationKey(value: unknown): boolean; + isValidAnnotationValue(value: unknown): boolean; + isValidTag(value: unknown): boolean; +}; + +// Warning: (ae-missing-release-tag) "VIEW_URL_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const VIEW_URL_ANNOTATION = "backstage.io/view-url"; + + +// Warnings were encountered during analysis: +// +// src/EntityPolicies.ts:55:28 - (ae-forgotten-export) The symbol "AllEntityPolicies" needs to be exported by the entry point index.d.ts +// src/EntityPolicies.ts:57:3 - (ae-forgotten-export) The symbol "AnyEntityPolicy" needs to be exported by the entry point index.d.ts +// src/entity/policies/types.ts:27:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/kinds/types.ts:26:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/cli-common/api-report.md b/packages/cli-common/api-report.md new file mode 100644 index 0000000000..81d494e4ef --- /dev/null +++ b/packages/cli-common/api-report.md @@ -0,0 +1,35 @@ +## API Report File for "@backstage/cli-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// Warning: (ae-missing-release-tag) "findPaths" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function findPaths(searchDir: string): Paths; + +// Warning: (ae-missing-release-tag) "Paths" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type Paths = { + ownDir: string; + ownRoot: string; + targetDir: string; + targetRoot: string; + resolveOwn: ResolveFunc; + resolveOwnRoot: ResolveFunc; + resolveTarget: ResolveFunc; + resolveTargetRoot: ResolveFunc; +}; + +// Warnings were encountered during analysis: +// +// src/paths.ts:38:3 - (ae-forgotten-export) The symbol "ResolveFunc" needs to be exported by the entry point index.d.ts +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/config-loader/api-report.md b/packages/config-loader/api-report.md new file mode 100644 index 0000000000..0c011aea65 --- /dev/null +++ b/packages/config-loader/api-report.md @@ -0,0 +1,72 @@ +## API Report File for "@backstage/config-loader" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { AppConfig } from '@backstage/config'; +import { JsonObject } from '@backstage/config'; +import { JSONSchema7 } from 'json-schema'; + +// Warning: (ae-missing-release-tag) "ConfigSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ConfigSchema = { + process(appConfigs: AppConfig[], options?: ConfigProcessingOptions): AppConfig[]; + serialize(): JsonObject; +}; + +// Warning: (ae-forgotten-export) The symbol "CONFIG_VISIBILITIES" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ConfigVisibility" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ConfigVisibility = typeof CONFIG_VISIBILITIES[number]; + +// Warning: (ae-missing-release-tag) "loadConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function loadConfig(options: LoadConfigOptions): Promise<AppConfig[]>; + +// Warning: (ae-missing-release-tag) "LoadConfigOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type LoadConfigOptions = { + configRoot: string; + configPaths: string[]; + env?: string; + experimentalEnvFunc?: EnvFunc; +}; + +// Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "loadConfigSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function loadConfigSchema(options: Options): Promise<ConfigSchema>; + +// Warning: (ae-missing-release-tag) "mergeConfigSchemas" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function mergeConfigSchemas(schemas: JSONSchema7[]): JSONSchema7; + +// Warning: (ae-missing-release-tag) "readEnvConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readEnvConfig(env: { + [name: string]: string | undefined; +}): AppConfig[]; + + +// Warnings were encountered during analysis: +// +// src/lib/schema/types.ts:105:3 - (ae-forgotten-export) The symbol "ConfigProcessingOptions" needs to be exported by the entry point index.d.ts +// src/loader.ts:42:6 - (tsdoc-unsupported-tag) The TSDoc tag "@experimental" is not supported by this tool +// src/loader.ts:44:3 - (ae-forgotten-export) The symbol "EnvFunc" needs to be exported by the entry point index.d.ts +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/config/api-report.md b/packages/config/api-report.md new file mode 100644 index 0000000000..8ff881a34b --- /dev/null +++ b/packages/config/api-report.md @@ -0,0 +1,112 @@ +## API Report File for "@backstage/config" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// Warning: (ae-missing-release-tag) "AppConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AppConfig = { + context: string; + data: JsonObject; +}; + +// Warning: (ae-missing-release-tag) "Config" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type Config = { + has(key: string): boolean; + keys(): string[]; + get<T = JsonValue>(key?: string): T; + getOptional<T = JsonValue>(key?: string): T | undefined; + getConfig(key: string): Config; + getOptionalConfig(key: string): Config | undefined; + getConfigArray(key: string): Config[]; + getOptionalConfigArray(key: string): Config[] | undefined; + getNumber(key: string): number; + getOptionalNumber(key: string): number | undefined; + getBoolean(key: string): boolean; + getOptionalBoolean(key: string): boolean | undefined; + getString(key: string): string; + getOptionalString(key: string): string | undefined; + getStringArray(key: string): string[]; + getOptionalStringArray(key: string): string[] | undefined; +}; + +// Warning: (ae-missing-release-tag) "ConfigReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ConfigReader implements Config { + constructor(data: JsonObject | undefined, context?: string, fallback?: ConfigReader | undefined, prefix?: string); + // (undocumented) + static fromConfigs(configs: AppConfig[]): ConfigReader; + // (undocumented) + get<T = JsonValue>(key?: string): T; + // (undocumented) + getBoolean(key: string): boolean; + // (undocumented) + getConfig(key: string): ConfigReader; + // (undocumented) + getConfigArray(key: string): ConfigReader[]; + // (undocumented) + getNumber(key: string): number; + // (undocumented) + getOptional<T = JsonValue>(key?: string): T | undefined; + // (undocumented) + getOptionalBoolean(key: string): boolean | undefined; + // (undocumented) + getOptionalConfig(key: string): ConfigReader | undefined; + // (undocumented) + getOptionalConfigArray(key: string): ConfigReader[] | undefined; + // (undocumented) + getOptionalNumber(key: string): number | undefined; + // (undocumented) + getOptionalString(key: string): string | undefined; + // (undocumented) + getOptionalStringArray(key: string): string[] | undefined; + // (undocumented) + getString(key: string): string; + // (undocumented) + getStringArray(key: string): string[]; + // (undocumented) + has(key: string): boolean; + // (undocumented) + keys(): string[]; + } + +// Warning: (ae-missing-release-tag) "JsonArray" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface JsonArray extends Array<JsonValue> { +} + +// Warning: (ae-missing-release-tag) "JsonObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type JsonObject = { + [key in string]?: JsonValue; +}; + +// Warning: (ae-missing-release-tag) "JsonPrimitive" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type JsonPrimitive = number | string | boolean | null; + +// Warning: (ae-missing-release-tag) "JsonValue" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type JsonValue = JsonObject | JsonArray | JsonPrimitive; + + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/dev-utils/api-report.md b/packages/dev-utils/api-report.md new file mode 100644 index 0000000000..41c793e189 --- /dev/null +++ b/packages/dev-utils/api-report.md @@ -0,0 +1,39 @@ +## API Report File for "@backstage/dev-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ApiFactory } from '@backstage/core'; +import { ComponentType } from 'react'; +import { createPlugin } from '@backstage/core'; +import { Entity } from '@backstage/catalog-model'; +import { GridProps } from '@material-ui/core'; +import { IconComponent } from '@backstage/core'; +import { ReactNode } from 'react'; + +// Warning: (ae-forgotten-export) The symbol "DevAppBuilder" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "createDevApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function createDevApp(): DevAppBuilder; + +// Warning: (ae-missing-release-tag) "EntityGridItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const EntityGridItem: ({ entity, classes, ...rest }: Omit<GridProps<"div", {}>, "container" | "item"> & { + entity: Entity; +}) => JSX.Element; + + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/errors/api-report.md b/packages/errors/api-report.md new file mode 100644 index 0000000000..2a4b482463 --- /dev/null +++ b/packages/errors/api-report.md @@ -0,0 +1,125 @@ +## API Report File for "@backstage/errors" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { JsonObject } from '@backstage/config'; + +// Warning: (ae-missing-release-tag) "AuthenticationError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class AuthenticationError extends CustomErrorBase { +} + +// Warning: (ae-missing-release-tag) "ConflictError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class ConflictError extends CustomErrorBase { +} + +// Warning: (ae-missing-release-tag) "CustomErrorBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class CustomErrorBase extends Error { + constructor(message?: string, cause?: Error); + // (undocumented) + readonly cause?: Error; +} + +// Warning: (ae-missing-release-tag) "deserializeError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function deserializeError<T extends Error = Error>(data: SerializedError): T; + +// Warning: (ae-missing-release-tag) "ErrorResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ErrorResponse = { + error: SerializedError; + request?: { + method: string; + url: string; + }; + response: { + statusCode: number; + }; +}; + +// Warning: (ae-missing-release-tag) "InputError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class InputError extends CustomErrorBase { +} + +// Warning: (ae-missing-release-tag) "NotAllowedError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class NotAllowedError extends CustomErrorBase { +} + +// Warning: (ae-missing-release-tag) "NotFoundError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class NotFoundError extends CustomErrorBase { +} + +// Warning: (ae-missing-release-tag) "NotModifiedError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class NotModifiedError extends CustomErrorBase { +} + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "parseErrorResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function parseErrorResponse(response: Response): Promise<ErrorResponse>; + +// Warning: (ae-missing-release-tag) "ResponseError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class ResponseError extends Error { + constructor(props: { + message: string; + response: Response; + data: ErrorResponse; + cause: Error; + }); + readonly cause: Error; + readonly data: ErrorResponse; + static fromResponse(response: Response): Promise<ResponseError>; + readonly response: Response; +} + +// Warning: (ae-missing-release-tag) "SerializedError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type SerializedError = JsonObject & { + name: string; + message: string; + stack?: string; + code?: string; +}; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// Warning: (ae-missing-release-tag) "serializeError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function serializeError(error: Error, options?: { + includeStack?: boolean; +}): SerializedError; + + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/integration-react/api-report.md b/packages/integration-react/api-report.md new file mode 100644 index 0000000000..aa12687415 --- /dev/null +++ b/packages/integration-react/api-report.md @@ -0,0 +1,32 @@ +## API Report File for "@backstage/integration-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ApiRef } from '@backstage/core'; +import { Config } from '@backstage/config'; +import { ScmIntegrationRegistry } from '@backstage/integration'; + +// Warning: (ae-missing-release-tag) "ScmIntegrationsApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ScmIntegrationsApi { + // (undocumented) + static fromConfig(config: Config): ScmIntegrationRegistry; +} + +// Warning: (ae-missing-release-tag) "scmIntegrationsApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const scmIntegrationsApiRef: ApiRef<ScmIntegrationRegistry>; + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md new file mode 100644 index 0000000000..8782abaf1a --- /dev/null +++ b/packages/integration/api-report.md @@ -0,0 +1,414 @@ +## API Report File for "@backstage/integration" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { Config } from '@backstage/config'; + +// Warning: (ae-missing-release-tag) "AzureIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class AzureIntegration implements ScmIntegration { + constructor(integrationConfig: AzureIntegrationConfig); + // (undocumented) + get config(): AzureIntegrationConfig; + // Warning: (ae-forgotten-export) The symbol "ScmIntegrationsFactory" needs to be exported by the entry point index.d.ts + // + // (undocumented) + static factory: ScmIntegrationsFactory<AzureIntegration>; + // (undocumented) + resolveEditUrl(url: string): string; + // (undocumented) + resolveUrl(options: { + url: string; + base: string; + lineNumber?: number; + }): string; + // (undocumented) + get title(): string; + // (undocumented) + get type(): string; +} + +// Warning: (ae-missing-release-tag) "AzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type AzureIntegrationConfig = { + host: string; + token?: string; +}; + +// Warning: (ae-missing-release-tag) "BitbucketIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class BitbucketIntegration implements ScmIntegration { + constructor(integrationConfig: BitbucketIntegrationConfig); + // (undocumented) + get config(): BitbucketIntegrationConfig; + // (undocumented) + static factory: ScmIntegrationsFactory<BitbucketIntegration>; + // (undocumented) + resolveEditUrl(url: string): string; + // (undocumented) + resolveUrl(options: { + url: string; + base: string; + lineNumber?: number; + }): string; + // (undocumented) + get title(): string; + // (undocumented) + get type(): string; +} + +// Warning: (ae-missing-release-tag) "BitbucketIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type BitbucketIntegrationConfig = { + host: string; + apiBaseUrl?: string; + token?: string; + username?: string; + appPassword?: string; +}; + +// Warning: (ae-missing-release-tag) "defaultScmResolveUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function defaultScmResolveUrl(options: { + url: string; + base: string; + lineNumber?: number; +}): string; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getAzureCommitsUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getAzureCommitsUrl(url: string): string; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getAzureDownloadUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getAzureDownloadUrl(url: string): string; + +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getAzureFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getAzureFileFetchUrl(url: string): string; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getAzureRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getAzureRequestOptions(config: AzureIntegrationConfig, additionalHeaders?: Record<string, string>): RequestInit; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getBitbucketDefaultBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getBitbucketDefaultBranch(url: string, config: BitbucketIntegrationConfig): Promise<string>; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getBitbucketDownloadUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getBitbucketDownloadUrl(url: string, config: BitbucketIntegrationConfig): Promise<string>; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getBitbucketFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getBitbucketFileFetchUrl(url: string, config: BitbucketIntegrationConfig): string; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getBitbucketRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getBitbucketRequestOptions(config: BitbucketIntegrationConfig): RequestInit; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getGitHubFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getGitHubFileFetchUrl(url: string, config: GitHubIntegrationConfig): string; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getGitHubRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getGitHubRequestOptions(config: GitHubIntegrationConfig): RequestInit; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getGitLabFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getGitLabFileFetchUrl(url: string, config: GitLabIntegrationConfig): Promise<string>; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "getGitLabRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function getGitLabRequestOptions(config: GitLabIntegrationConfig): RequestInit; + +// Warning: (ae-missing-release-tag) "GithubCredentialsProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class GithubCredentialsProvider { + // (undocumented) + static create(config: GitHubIntegrationConfig): GithubCredentialsProvider; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag + // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag + // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" + // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" + // Warning: (tsdoc-undefined-tag) The TSDoc tag "@type" is not defined in this configuration + // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag + // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag + // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" + // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" + // Warning: (ae-forgotten-export) The symbol "GithubCredentials" needs to be exported by the entry point index.d.ts + getCredentials(opts: { + url: string; + }): Promise<GithubCredentials>; + } + +// Warning: (ae-missing-release-tag) "GitHubIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class GitHubIntegration implements ScmIntegration { + constructor(integrationConfig: GitHubIntegrationConfig); + // (undocumented) + get config(): GitHubIntegrationConfig; + // (undocumented) + static factory: ScmIntegrationsFactory<GitHubIntegration>; + // (undocumented) + resolveEditUrl(url: string): string; + // (undocumented) + resolveUrl(options: { + url: string; + base: string; + lineNumber?: number; + }): string; + // (undocumented) + get title(): string; + // (undocumented) + get type(): string; +} + +// Warning: (ae-missing-release-tag) "GitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type GitHubIntegrationConfig = { + host: string; + apiBaseUrl?: string; + rawBaseUrl?: string; + token?: string; + apps?: GithubAppConfig[]; +}; + +// Warning: (ae-missing-release-tag) "GitLabIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class GitLabIntegration implements ScmIntegration { + constructor(integrationConfig: GitLabIntegrationConfig); + // (undocumented) + get config(): GitLabIntegrationConfig; + // (undocumented) + static factory: ScmIntegrationsFactory<GitLabIntegration>; + // (undocumented) + resolveEditUrl(url: string): string; + // (undocumented) + resolveUrl(options: { + url: string; + base: string; + lineNumber?: number; + }): string; + // (undocumented) + get title(): string; + // (undocumented) + get type(): string; +} + +// Warning: (ae-missing-release-tag) "GitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type GitLabIntegrationConfig = { + host: string; + apiBaseUrl: string; + token?: string; + baseUrl: string; +}; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readAzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readAzureIntegrationConfig(config: Config): AzureIntegrationConfig; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readAzureIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readAzureIntegrationConfigs(configs: Config[]): AzureIntegrationConfig[]; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readBitbucketIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readBitbucketIntegrationConfig(config: Config): BitbucketIntegrationConfig; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readBitbucketIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readBitbucketIntegrationConfigs(configs: Config[]): BitbucketIntegrationConfig[]; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readGitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readGitHubIntegrationConfig(config: Config): GitHubIntegrationConfig; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readGitHubIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readGitHubIntegrationConfigs(configs: Config[]): GitHubIntegrationConfig[]; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readGitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readGitLabIntegrationConfig(config: Config): GitLabIntegrationConfig; + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "readGitLabIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function readGitLabIntegrationConfigs(configs: Config[]): GitLabIntegrationConfig[]; + +// Warning: (ae-missing-release-tag) "ScmIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ScmIntegration { + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + resolveEditUrl(url: string): string; + // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters + // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters + // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters + resolveUrl(options: { + url: string; + base: string; + lineNumber?: number; + }): string; + title: string; + type: string; +} + +// Warning: (ae-missing-release-tag) "ScmIntegrationRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ScmIntegrationRegistry extends ScmIntegrationsGroup<ScmIntegration> { + // (undocumented) + azure: ScmIntegrationsGroup<AzureIntegration>; + // (undocumented) + bitbucket: ScmIntegrationsGroup<BitbucketIntegration>; + // (undocumented) + github: ScmIntegrationsGroup<GitHubIntegration>; + // (undocumented) + gitlab: ScmIntegrationsGroup<GitLabIntegration>; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + resolveEditUrl(url: string): string; + // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters + // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters + // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters + resolveUrl(options: { + url: string; + base: string; + lineNumber?: number; + }): string; +} + +// Warning: (ae-missing-release-tag) "ScmIntegrations" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ScmIntegrations implements ScmIntegrationRegistry { + // Warning: (ae-forgotten-export) The symbol "IntegrationsByType" needs to be exported by the entry point index.d.ts + constructor(integrationsByType: IntegrationsByType); + // (undocumented) + get azure(): ScmIntegrationsGroup<AzureIntegration>; + // (undocumented) + get bitbucket(): ScmIntegrationsGroup<BitbucketIntegration>; + // (undocumented) + byHost(host: string): ScmIntegration | undefined; + // (undocumented) + byUrl(url: string | URL): ScmIntegration | undefined; + // (undocumented) + static fromConfig(config: Config): ScmIntegrations; + // (undocumented) + get github(): ScmIntegrationsGroup<GitHubIntegration>; + // (undocumented) + get gitlab(): ScmIntegrationsGroup<GitLabIntegration>; + // (undocumented) + list(): ScmIntegration[]; + // (undocumented) + resolveEditUrl(url: string): string; + // (undocumented) + resolveUrl(options: { + url: string; + base: string; + lineNumber?: number; + }): string; +} + +// Warning: (ae-missing-release-tag) "ScmIntegrationsGroup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ScmIntegrationsGroup<T extends ScmIntegration> { + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + byHost(host: string): T | undefined; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + byUrl(url: string | URL): T | undefined; + list(): T[]; +} + + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. +// src/github/config.ts:67:3 - (ae-forgotten-export) The symbol "GithubAppConfig" needs to be exported by the entry point index.d.ts +// src/gitlab/config.ts:51:66 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// src/gitlab/config.ts:51:61 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/search-common/api-report.md b/packages/search-common/api-report.md new file mode 100644 index 0000000000..3911059177 --- /dev/null +++ b/packages/search-common/api-report.md @@ -0,0 +1,70 @@ +## API Report File for "@backstage/search-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { JsonObject } from '@backstage/config'; + +// Warning: (ae-missing-release-tag) "DocumentCollator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface DocumentCollator { + // (undocumented) + execute(): Promise<IndexableDocument[]>; +} + +// Warning: (ae-missing-release-tag) "DocumentDecorator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface DocumentDecorator { + // (undocumented) + execute(documents: IndexableDocument[]): Promise<IndexableDocument[]>; +} + +// Warning: (ae-missing-release-tag) "IndexableDocument" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface IndexableDocument { + location: string; + text: string; + title: string; +} + +// Warning: (ae-missing-release-tag) "SearchQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface SearchQuery { + // (undocumented) + filters?: JsonObject; + // (undocumented) + pageCursor: string; + // (undocumented) + term: string; +} + +// Warning: (ae-missing-release-tag) "SearchResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface SearchResult { + // (undocumented) + document: IndexableDocument; +} + +// Warning: (ae-missing-release-tag) "SearchResultSet" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface SearchResultSet { + // (undocumented) + results: SearchResult[]; +} + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md new file mode 100644 index 0000000000..df1bea443c --- /dev/null +++ b/packages/techdocs-common/api-report.md @@ -0,0 +1,259 @@ +## API Report File for "@backstage/techdocs-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { AzureIntegrationConfig } from '@backstage/integration'; +import { Config } from '@backstage/config'; +import Docker from 'dockerode'; +import { Entity } from '@backstage/catalog-model'; +import { EntityName } from '@backstage/catalog-model'; +import express from 'express'; +import { GitHubIntegrationConfig } from '@backstage/integration'; +import { GitLabIntegrationConfig } from '@backstage/integration'; +import { Logger } from 'winston'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { UrlReader } from '@backstage/backend-common'; +import { Writable } from 'stream'; + +// Warning: (ae-missing-release-tag) "checkoutGitRepository" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger) => Promise<string>; + +// Warning: (ae-missing-release-tag) "CommonGitPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class CommonGitPreparer implements PreparerBase { + constructor(config: Config, logger: Logger); + // Warning: (ae-forgotten-export) The symbol "PreparerResponse" needs to be exported by the entry point index.d.ts + // + // (undocumented) + prepare(entity: Entity, options?: { + etag?: string; + }): Promise<PreparerResponse>; +} + +// Warning: (ae-missing-release-tag) "DirectoryPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class DirectoryPreparer implements PreparerBase { + constructor(config: Config, logger: Logger, reader: UrlReader); + // (undocumented) + prepare(entity: Entity): Promise<PreparerResponse>; + } + +// Warning: (ae-missing-release-tag) "GeneratorBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type GeneratorBase = { + run(opts: GeneratorRunOptions): Promise<void>; +}; + +// Warning: (ae-missing-release-tag) "GeneratorBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type GeneratorBuilder = { + register(protocol: SupportedGeneratorKey, generator: GeneratorBase): void; + get(entity: Entity): GeneratorBase; +}; + +// Warning: (ae-missing-release-tag) "Generators" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Generators implements GeneratorBuilder { + // (undocumented) + static fromConfig(config: Config, { logger }: { + logger: Logger; + }): Promise<GeneratorBuilder>; + // (undocumented) + get(entity: Entity): GeneratorBase; + // (undocumented) + register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase): void; +} + +// Warning: (ae-missing-release-tag) "getAzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getAzureIntegrationConfig: (config: Config, host: string) => AzureIntegrationConfig; + +// Warning: (ae-missing-release-tag) "getDefaultBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getDefaultBranch: (repositoryUrl: string, config: Config) => Promise<string>; + +// Warning: (ae-missing-release-tag) "getDocFilesFromRepository" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getDocFilesFromRepository: (reader: UrlReader, entity: Entity, opts?: { + etag?: string | undefined; + logger?: Logger | undefined; +} | undefined) => Promise<PreparerResponse>; + +// Warning: (ae-missing-release-tag) "getGitHost" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getGitHost(url: string): string; + +// Warning: (ae-missing-release-tag) "getGitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getGitHubIntegrationConfig: (config: Config, host: string) => GitHubIntegrationConfig; + +// Warning: (ae-missing-release-tag) "getGitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getGitLabIntegrationConfig: (config: Config, host: string) => GitLabIntegrationConfig; + +// Warning: (ae-missing-release-tag) "getGitRepositoryTempFolder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getGitRepositoryTempFolder: (repositoryUrl: string, config: Config) => Promise<string>; + +// Warning: (ae-missing-release-tag) "getGitRepoType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getGitRepoType(url: string): string; + +// Warning: (ae-missing-release-tag) "getLastCommitTimestamp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger) => Promise<number>; + +// Warning: (ae-missing-release-tag) "getLocationForEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getLocationForEntity: (entity: Entity) => ParsedLocationAnnotation; + +// Warning: (ae-missing-release-tag) "getTokenForGitRepo" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const getTokenForGitRepo: (repositoryUrl: string, config: Config) => Promise<string | undefined>; + +// Warning: (ae-missing-release-tag) "ParsedLocationAnnotation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ParsedLocationAnnotation = { + type: RemoteProtocol; + target: string; +}; + +// Warning: (ae-missing-release-tag) "parseReferenceAnnotation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const parseReferenceAnnotation: (annotationName: string, entity: Entity) => ParsedLocationAnnotation; + +// Warning: (ae-missing-release-tag) "PreparerBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PreparerBase = { + prepare(entity: Entity, options?: { + logger?: Logger; + etag?: string; + }): Promise<PreparerResponse>; +}; + +// Warning: (ae-missing-release-tag) "PreparerBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PreparerBuilder = { + register(protocol: RemoteProtocol, preparer: PreparerBase): void; + get(entity: Entity): PreparerBase; +}; + +// Warning: (ae-missing-release-tag) "Preparers" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Preparers implements PreparerBuilder { + // Warning: (ae-forgotten-export) The symbol "factoryOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + static fromConfig(config: Config, { logger, reader }: factoryOptions): Promise<PreparerBuilder>; + // (undocumented) + get(entity: Entity): PreparerBase; + // (undocumented) + register(protocol: RemoteProtocol, preparer: PreparerBase): void; +} + +// Warning: (ae-missing-release-tag) "Publisher" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class Publisher { + // Warning: (ae-forgotten-export) The symbol "factoryOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + static fromConfig(config: Config, { logger, discovery }: factoryOptions_2): Promise<PublisherBase>; +} + +// Warning: (ae-missing-release-tag) "PublisherBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface PublisherBase { + docsRouter(): express.Handler; + fetchTechDocsMetadata(entityName: EntityName): Promise<TechDocsMetadata>; + hasDocsBeenGenerated(entityName: Entity): Promise<boolean>; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (ae-forgotten-export) The symbol "PublishRequest" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "PublishResponse" needs to be exported by the entry point index.d.ts + publish(request: PublishRequest): Promise<PublishResponse>; +} + +// Warning: (ae-missing-release-tag) "PublisherType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PublisherType = 'local' | 'googleGcs' | 'awsS3' | 'azureBlobStorage' | 'openStackSwift'; + +// Warning: (ae-missing-release-tag) "RemoteProtocol" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type RemoteProtocol = 'url' | 'dir' | 'github' | 'gitlab' | 'file' | 'azure/api'; + +// Warning: (ae-missing-release-tag) "TechdocsGenerator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class TechdocsGenerator implements GeneratorBase { + constructor(logger: Logger, config: Config); + // (undocumented) + run({ inputDir, outputDir, dockerClient, parsedLocationAnnotation, etag, }: GeneratorRunOptions): Promise<void>; +} + +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "TechDocsMetadata" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type TechDocsMetadata = { + site_name: string; + site_description: string; + etag: string; +}; + +// Warning: (ae-missing-release-tag) "UrlPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class UrlPreparer implements PreparerBase { + constructor(reader: UrlReader, logger: Logger); + // (undocumented) + prepare(entity: Entity, options?: { + etag?: string; + }): Promise<PreparerResponse>; + } + + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. +// src/stages/generate/types.ts:42:3 - (ae-forgotten-export) The symbol "GeneratorRunOptions" needs to be exported by the entry point index.d.ts +// src/stages/generate/types.ts:54:3 - (ae-forgotten-export) The symbol "SupportedGeneratorKey" needs to be exported by the entry point index.d.ts +// src/stages/prepare/types.ts:35:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// src/stages/prepare/types.ts:36:6 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters +// src/stages/prepare/types.ts:38:31 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag +// src/stages/prepare/types.ts:38:14 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/test-utils-core/api-report.md b/packages/test-utils-core/api-report.md new file mode 100644 index 0000000000..a462be7aca --- /dev/null +++ b/packages/test-utils-core/api-report.md @@ -0,0 +1,113 @@ +## API Report File for "@backstage/test-utils-core" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ReactElement } from 'react'; +import { RenderResult } from '@testing-library/react'; + +// Warning: (ae-missing-release-tag) "AsyncLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AsyncLogCollector = () => Promise<void>; + +// Warning: (ae-missing-release-tag) "CollectedLogs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type CollectedLogs<T extends LogFuncs> = { + [key in T]: string[]; +}; + +// Warning: (ae-missing-release-tag) "Keyboard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Keyboard { + constructor(target: any, { debug }?: { + debug?: boolean | undefined; + }); + // (undocumented) + click(): Promise<void>; + // (undocumented) + debug: boolean; + // (undocumented) + document: any; + // (undocumented) + enter(value: any): Promise<void>; + // (undocumented) + escape(): Promise<void>; + // (undocumented) + get focused(): any; + // (undocumented) + static fromReadableInput(input: any): any; + // (undocumented) + _log(message: any, ...args: any[]): void; + // (undocumented) + _pretty(element: any): string; + // (undocumented) + send(chars: any): Promise<void>; + // (undocumented) + _sendKey(key: any, charCode: any, action: any): Promise<void>; + // (undocumented) + tab(): Promise<void>; + // (undocumented) + static toReadableInput(chars: any): any; + // (undocumented) + toString(): string; + // (undocumented) + static type(target: any, input: any): Promise<void>; + // (undocumented) + type(input: any): Promise<void>; + // (undocumented) + static typeDebug(target: any, input: any): Promise<void>; +} + +// Warning: (ae-missing-release-tag) "LogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type LogCollector = AsyncLogCollector | SyncLogCollector; + +// Warning: (ae-missing-release-tag) "LogFuncs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type LogFuncs = 'log' | 'warn' | 'error'; + +// Warning: (ae-missing-release-tag) "renderWithEffects" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function renderWithEffects(nodes: ReactElement): Promise<RenderResult>; + +// Warning: (ae-missing-release-tag) "SyncLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SyncLogCollector = () => void; + +// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function withLogCollector(callback: AsyncLogCollector): Promise<CollectedLogs<LogFuncs>>; + +// @public (undocumented) +export function withLogCollector(callback: SyncLogCollector): CollectedLogs<LogFuncs>; + +// @public (undocumented) +export function withLogCollector<T extends LogFuncs>(logsToCollect: T[], callback: AsyncLogCollector): Promise<CollectedLogs<T>>; + +// @public (undocumented) +export function withLogCollector<T extends LogFuncs>(logsToCollect: T[], callback: SyncLogCollector): CollectedLogs<T>; + + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md new file mode 100644 index 0000000000..9e72a070f7 --- /dev/null +++ b/packages/test-utils/api-report.md @@ -0,0 +1,109 @@ +## API Report File for "@backstage/test-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ComponentType } from 'react'; +import { ErrorApi } from '@backstage/core-api'; +import { ErrorContext } from '@backstage/core-api'; +import { ExternalRouteRef } from '@backstage/core-api'; +import { Observable } from '@backstage/core-api'; +import { ReactElement } from 'react'; +import { ReactNode } from 'react'; +import { RenderResult } from '@testing-library/react'; +import { RouteRef } from '@backstage/core-api'; +import { StorageApi } from '@backstage/core-api'; +import { StorageValueChange } from '@backstage/core-api'; + +// Warning: (ae-forgotten-export) The symbol "Breakpoint" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "mockBreakpoint" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function mockBreakpoint(initialBreakpoint?: Breakpoint): { + set(breakpoint: Breakpoint): void; + remove(): void; +}; + +// Warning: (ae-missing-release-tag) "MockErrorApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class MockErrorApi implements ErrorApi { + // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts + constructor(options?: Options); + // (undocumented) + error$(): Observable<{ + error: Error; + context?: ErrorContext; + }>; + // Warning: (ae-forgotten-export) The symbol "ErrorWithContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getErrors(): ErrorWithContext[]; + // (undocumented) + post(error: Error, context?: ErrorContext): void; + // (undocumented) + waitForError(pattern: RegExp, timeoutMs?: number): Promise<ErrorWithContext>; +} + +// Warning: (ae-missing-release-tag) "MockStorageApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class MockStorageApi implements StorageApi { + // (undocumented) + static create(data?: MockStorageBucket): MockStorageApi; + // (undocumented) + forBucket(name: string): StorageApi; + // (undocumented) + get<T>(key: string): T | undefined; + // (undocumented) + observe$<T>(key: string): Observable<StorageValueChange<T>>; + // (undocumented) + remove(key: string): Promise<void>; + // (undocumented) + set<T>(key: string, data: T): Promise<void>; + } + +// Warning: (ae-missing-release-tag) "MockStorageBucket" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MockStorageBucket = { + [key: string]: any; +}; + +// Warning: (ae-missing-release-tag) "msw" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const msw: { + setupDefaultHandlers: (worker: { + listen: (t: any) => void; + close: () => void; + resetHandlers: () => void; + }) => void; +}; + +// Warning: (ae-forgotten-export) The symbol "TestAppOptions" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "renderInTestApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function renderInTestApp(Component: ComponentType | ReactNode, options?: TestAppOptions): Promise<RenderResult>; + +// Warning: (ae-missing-release-tag) "wrapInTestApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function wrapInTestApp(Component: ComponentType | ReactNode, options?: TestAppOptions): ReactElement; + + +export * from "@backstage/test-utils-core"; + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md new file mode 100644 index 0000000000..87656beb2c --- /dev/null +++ b/packages/theme/api-report.md @@ -0,0 +1,130 @@ +## API Report File for "@backstage/theme" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { Overrides } from '@material-ui/core/styles/overrides'; +import { Palette } from '@material-ui/core/styles/createPalette'; +import { PaletteOptions } from '@material-ui/core/styles/createPalette'; +import { Theme } from '@material-ui/core'; +import { ThemeOptions } from '@material-ui/core'; + +// Warning: (ae-forgotten-export) The symbol "PaletteAdditions" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "BackstagePalette" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BackstagePalette = Palette & PaletteAdditions; + +// Warning: (ae-missing-release-tag) "BackstagePaletteOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BackstagePaletteOptions = PaletteOptions & PaletteAdditions; + +// Warning: (ae-missing-release-tag) "BackstageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface BackstageTheme extends Theme { + // (undocumented) + getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; + // (undocumented) + page: PageTheme; + // (undocumented) + palette: BackstagePalette; +} + +// Warning: (ae-missing-release-tag) "BackstageThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface BackstageThemeOptions extends ThemeOptions { + // (undocumented) + getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; + // (undocumented) + page: PageTheme; + // (undocumented) + palette: BackstagePaletteOptions; +} + +// Warning: (ae-missing-release-tag) "colorVariants" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const colorVariants: Record<string, string[]>; + +// Warning: (ae-missing-release-tag) "createTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createTheme(options: SimpleThemeOptions): BackstageTheme; + +// Warning: (ae-missing-release-tag) "createThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createThemeOptions(options: SimpleThemeOptions): BackstageThemeOptions; + +// Warning: (ae-missing-release-tag) "createThemeOverrides" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createThemeOverrides(theme: BackstageTheme): Overrides; + +// Warning: (ae-missing-release-tag) "darkTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const darkTheme: BackstageTheme; + +// Warning: (ae-missing-release-tag) "genPageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function genPageTheme(colors: string[], shape: string): PageTheme; + +// Warning: (ae-missing-release-tag) "lightTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const lightTheme: BackstageTheme; + +// Warning: (ae-missing-release-tag) "PageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PageTheme = { + colors: string[]; + shape: string; + backgroundImage: string; +}; + +// Warning: (ae-missing-release-tag) "pageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const pageTheme: Record<string, PageTheme>; + +// Warning: (ae-missing-release-tag) "PageThemeSelector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PageThemeSelector = { + themeId: string; +}; + +// Warning: (ae-missing-release-tag) "shapes" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const shapes: Record<string, string>; + +// Warning: (ae-missing-release-tag) "SimpleThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type SimpleThemeOptions = { + palette: BackstagePaletteOptions; + defaultPageTheme: string; + pageTheme?: Record<string, PageTheme>; + fontFamily?: string; +}; + + +// Warnings were encountered during analysis: +// +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. +// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. + +// (No @packageDocumentation comment for this package) + +``` From d3c54f9663a890bc9cadad2db7d071e2d8c461ac Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 19:23:00 +0200 Subject: [PATCH 165/262] scripts/api-extractor: log instructions after run is complete to avoid race Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- scripts/api-extractor.ts | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index e232170e9d..6eca3b0de3 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -166,6 +166,8 @@ async function runApiExtraction({ // Message verbosity can't be configured, so just skip the check instead (Extractor as any)._checkCompilerCompatibility = () => {}; + let shouldLogInstructions = false; + // Invoke API Extractor const extractorResult = Extractor.invoke(extractorConfig, { localBuild: isLocalBuild, @@ -177,26 +179,29 @@ async function runApiExtraction({ 'You have changed the public API signature for this project.', ) ) { - console.log(''); - console.log( - '*************************************************************************************', - ); - console.log( - '* You have uncommitted changes to the public API of a package. *', - ); - console.log( - '* To solve this, run `yarn build:api-reports` and commit all api-report.md changes. *', - ); - console.log( - '*************************************************************************************', - ); - console.log(''); + shouldLogInstructions = true; } }, compilerState, }); if (!extractorResult.succeeded) { + if (shouldLogInstructions) { + console.log(''); + console.log( + '*************************************************************************************', + ); + console.log( + '* You have uncommitted changes to the public API of a package. *', + ); + console.log( + '* To solve this, run `yarn build:api-reports` and commit all api-report.md changes. *', + ); + console.log( + '*************************************************************************************', + ); + console.log(''); + } throw new Error( `API Extractor completed with ${extractorResult.errorCount} errors` + ` and ${extractorResult.warningCount} warnings`, From 0eda63fe9da28397288d7d52be4d8dfd0e98591b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 20:12:52 +0200 Subject: [PATCH 166/262] scripts/api-extractor: disable inline compilation warnings Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- packages/backend-common/api-report.md | 5 --- packages/catalog-client/api-report.md | 5 --- packages/catalog-model/api-report.md | 5 --- packages/cli-common/api-report.md | 24 ++++++------- packages/config-loader/api-report.md | 5 --- packages/config/api-report.md | 8 ----- packages/dev-utils/api-report.md | 8 ----- packages/errors/api-report.md | 8 ----- packages/integration-react/api-report.md | 13 +++---- packages/integration/api-report.md | 5 --- packages/search-common/api-report.md | 43 +++++++++++------------- packages/techdocs-common/api-report.md | 5 --- packages/test-utils-core/api-report.md | 8 ----- packages/test-utils/api-report.md | 8 ----- packages/theme/api-report.md | 8 ----- scripts/api-extractor.ts | 3 +- 16 files changed, 36 insertions(+), 125 deletions(-) diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index bdef061eda..79a7ca1a5c 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -458,11 +458,6 @@ export function useHotMemoize<T>(_module: NodeModule, valueFactory: () => T): T; // src/service/types.ts:78:3 - (ae-forgotten-export) The symbol "HttpsSettings" needs to be exported by the entry point index.d.ts // src/service/types.ts:83:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // src/service/types.ts:84:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // (No @packageDocumentation comment for this package) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index fe12d3a62c..467cf752af 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -94,11 +94,6 @@ export type CatalogListResponse<T> = { // Warnings were encountered during analysis: // // src/CatalogClient.ts:40:26 - (ae-forgotten-export) The symbol "DiscoveryApi" needs to be exported by the entry point index.d.ts -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // (No @packageDocumentation comment for this package) diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index b3e3303589..7aa98e52c7 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -800,11 +800,6 @@ export const VIEW_URL_ANNOTATION = "backstage.io/view-url"; // src/EntityPolicies.ts:57:3 - (ae-forgotten-export) The symbol "AnyEntityPolicy" needs to be exported by the entry point index.d.ts // src/entity/policies/types.ts:27:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // src/kinds/types.ts:26:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // (No @packageDocumentation comment for this package) diff --git a/packages/cli-common/api-report.md b/packages/cli-common/api-report.md index 81d494e4ef..f4df3562b8 100644 --- a/packages/cli-common/api-report.md +++ b/packages/cli-common/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts + // Warning: (ae-missing-release-tag) "findPaths" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @@ -12,24 +13,21 @@ export function findPaths(searchDir: string): Paths; // // @public (undocumented) export type Paths = { - ownDir: string; - ownRoot: string; - targetDir: string; - targetRoot: string; - resolveOwn: ResolveFunc; - resolveOwnRoot: ResolveFunc; - resolveTarget: ResolveFunc; - resolveTargetRoot: ResolveFunc; + ownDir: string; + ownRoot: string; + targetDir: string; + targetRoot: string; + resolveOwn: ResolveFunc; + resolveOwnRoot: ResolveFunc; + resolveTarget: ResolveFunc; + resolveTargetRoot: ResolveFunc; }; + // Warnings were encountered during analysis: // // src/paths.ts:38:3 - (ae-forgotten-export) The symbol "ResolveFunc" needs to be exported by the entry point index.d.ts -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // (No @packageDocumentation comment for this package) + ``` diff --git a/packages/config-loader/api-report.md b/packages/config-loader/api-report.md index 0c011aea65..ffa599df2b 100644 --- a/packages/config-loader/api-report.md +++ b/packages/config-loader/api-report.md @@ -61,11 +61,6 @@ export function readEnvConfig(env: { // src/lib/schema/types.ts:105:3 - (ae-forgotten-export) The symbol "ConfigProcessingOptions" needs to be exported by the entry point index.d.ts // src/loader.ts:42:6 - (tsdoc-unsupported-tag) The TSDoc tag "@experimental" is not supported by this tool // src/loader.ts:44:3 - (ae-forgotten-export) The symbol "EnvFunc" needs to be exported by the entry point index.d.ts -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // (No @packageDocumentation comment for this package) diff --git a/packages/config/api-report.md b/packages/config/api-report.md index 8ff881a34b..4e0da777ec 100644 --- a/packages/config/api-report.md +++ b/packages/config/api-report.md @@ -99,14 +99,6 @@ export type JsonPrimitive = number | string | boolean | null; export type JsonValue = JsonObject | JsonArray | JsonPrimitive; -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/dev-utils/api-report.md b/packages/dev-utils/api-report.md index 41c793e189..841f9c19b2 100644 --- a/packages/dev-utils/api-report.md +++ b/packages/dev-utils/api-report.md @@ -26,14 +26,6 @@ export const EntityGridItem: ({ entity, classes, ...rest }: Omit<GridProps<"div" }) => JSX.Element; -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/errors/api-report.md b/packages/errors/api-report.md index 2a4b482463..18861fdc84 100644 --- a/packages/errors/api-report.md +++ b/packages/errors/api-report.md @@ -112,14 +112,6 @@ export function serializeError(error: Error, options?: { }): SerializedError; -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/integration-react/api-report.md b/packages/integration-react/api-report.md index aa12687415..8dcc02a443 100644 --- a/packages/integration-react/api-report.md +++ b/packages/integration-react/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts + import { ApiRef } from '@backstage/core'; import { Config } from '@backstage/config'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -11,8 +12,8 @@ import { ScmIntegrationRegistry } from '@backstage/integration'; // // @public (undocumented) export class ScmIntegrationsApi { - // (undocumented) - static fromConfig(config: Config): ScmIntegrationRegistry; + // (undocumented) + static fromConfig(config: Config): ScmIntegrationRegistry; } // Warning: (ae-missing-release-tag) "scmIntegrationsApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -20,13 +21,7 @@ export class ScmIntegrationsApi { // @public (undocumented) export const scmIntegrationsApiRef: ApiRef<ScmIntegrationRegistry>; -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // (No @packageDocumentation comment for this package) + ``` diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md index 8782abaf1a..6d85bf4a51 100644 --- a/packages/integration/api-report.md +++ b/packages/integration/api-report.md @@ -400,11 +400,6 @@ export interface ScmIntegrationsGroup<T extends ScmIntegration> { // Warnings were encountered during analysis: // -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // src/github/config.ts:67:3 - (ae-forgotten-export) The symbol "GithubAppConfig" needs to be exported by the entry point index.d.ts // src/gitlab/config.ts:51:66 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag // src/gitlab/config.ts:51:61 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" diff --git a/packages/search-common/api-report.md b/packages/search-common/api-report.md index 3911059177..ed53275017 100644 --- a/packages/search-common/api-report.md +++ b/packages/search-common/api-report.md @@ -3,68 +3,63 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts + import { JsonObject } from '@backstage/config'; // Warning: (ae-missing-release-tag) "DocumentCollator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public export interface DocumentCollator { - // (undocumented) - execute(): Promise<IndexableDocument[]>; + // (undocumented) + execute(): Promise<IndexableDocument[]>; } // Warning: (ae-missing-release-tag) "DocumentDecorator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public export interface DocumentDecorator { - // (undocumented) - execute(documents: IndexableDocument[]): Promise<IndexableDocument[]>; + // (undocumented) + execute(documents: IndexableDocument[]): Promise<IndexableDocument[]>; } // Warning: (ae-missing-release-tag) "IndexableDocument" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public export interface IndexableDocument { - location: string; - text: string; - title: string; + location: string; + text: string; + title: string; } // Warning: (ae-missing-release-tag) "SearchQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export interface SearchQuery { - // (undocumented) - filters?: JsonObject; - // (undocumented) - pageCursor: string; - // (undocumented) - term: string; + // (undocumented) + filters?: JsonObject; + // (undocumented) + pageCursor: string; + // (undocumented) + term: string; } // Warning: (ae-missing-release-tag) "SearchResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export interface SearchResult { - // (undocumented) - document: IndexableDocument; + // (undocumented) + document: IndexableDocument; } // Warning: (ae-missing-release-tag) "SearchResultSet" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export interface SearchResultSet { - // (undocumented) - results: SearchResult[]; + // (undocumented) + results: SearchResult[]; } -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // (No @packageDocumentation comment for this package) + ``` diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md index df1bea443c..aa6c9da2f8 100644 --- a/packages/techdocs-common/api-report.md +++ b/packages/techdocs-common/api-report.md @@ -242,11 +242,6 @@ export class UrlPreparer implements PreparerBase { // Warnings were encountered during analysis: // -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. // src/stages/generate/types.ts:42:3 - (ae-forgotten-export) The symbol "GeneratorRunOptions" needs to be exported by the entry point index.d.ts // src/stages/generate/types.ts:54:3 - (ae-forgotten-export) The symbol "SupportedGeneratorKey" needs to be exported by the entry point index.d.ts // src/stages/prepare/types.ts:35:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen diff --git a/packages/test-utils-core/api-report.md b/packages/test-utils-core/api-report.md index a462be7aca..bda058ad23 100644 --- a/packages/test-utils-core/api-report.md +++ b/packages/test-utils-core/api-report.md @@ -100,14 +100,6 @@ export function withLogCollector<T extends LogFuncs>(logsToCollect: T[], callbac export function withLogCollector<T extends LogFuncs>(logsToCollect: T[], callback: SyncLogCollector): CollectedLogs<T>; -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index 9e72a070f7..f62b1e6dec 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -96,14 +96,6 @@ export function wrapInTestApp(Component: ComponentType | ReactNode, options?: Te export * from "@backstage/test-utils-core"; -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index 87656beb2c..adfbcee346 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -117,14 +117,6 @@ export type SimpleThemeOptions = { }; -// Warnings were encountered during analysis: -// -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:18:31 - (TS2307) Cannot find module './assets/missingAnnotation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:19:27 - (TS2307) Cannot find module './assets/noInformation.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:20:29 - (TS2307) Cannot find module './assets/createComponent.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/components/EmptyState/EmptyStateImage.tsx:21:21 - (TS2307) Cannot find module './assets/noBuild.svg' or its corresponding type declarations. -// /Users/patriko/dev/backstage/packages/core/src/layout/ErrorPage/MicDrop.tsx:19:27 - (TS2307) Cannot find module './mic-drop.svg' or its corresponding type declarations. - // (No @packageDocumentation comment for this package) ``` diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 6eca3b0de3..6095b1f15f 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -132,7 +132,8 @@ async function runApiExtraction({ compilerMessageReporting: { default: { logLevel: 'warning' as ExtractorLogLevel.Warning, - addToApiReportFile: true, + // These contain absolute file paths, so can't be included in the report + // addToApiReportFile: true, }, }, extractorMessageReporting: { From 6768b397bd644ae5e9d5ec35e0ee4c82bb64c79a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 7 Apr 2021 22:41:35 +0200 Subject: [PATCH 167/262] scripts/api-extractor: silence compiler warnings Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- scripts/api-extractor.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 6095b1f15f..2391832f3e 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -131,7 +131,8 @@ async function runApiExtraction({ messages: { compilerMessageReporting: { default: { - logLevel: 'warning' as ExtractorLogLevel.Warning, + // Silence compiler warnings, as these will prevent the CI build to work + logLevel: 'none' as ExtractorLogLevel.None, // These contain absolute file paths, so can't be included in the report // addToApiReportFile: true, }, From c04a465330dbc35543b224aa4562265c59a287a4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 14 Apr 2021 18:40:04 +0200 Subject: [PATCH 168/262] scripts/api-extractor: figure out the conflicting file in CI and print the contents Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- scripts/api-extractor.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 2391832f3e..4135c52701 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -17,7 +17,11 @@ /* eslint-disable import/no-extraneous-dependencies */ // eslint-disable-next-line no-restricted-imports -import { resolve as resolvePath, join as joinPath, dirname } from 'path'; +import { + resolve as resolvePath, + relative as relativePath, + dirname, +} from 'path'; import fs from 'fs-extra'; import { Extractor, @@ -169,6 +173,7 @@ async function runApiExtraction({ (Extractor as any)._checkCompilerCompatibility = () => {}; let shouldLogInstructions = false; + let conflictingFile: undefined | string = undefined; // Invoke API Extractor const extractorResult = Extractor.invoke(extractorConfig, { @@ -182,6 +187,12 @@ async function runApiExtraction({ ) ) { shouldLogInstructions = true; + const match = message.text.match( + /Please copy the file "(.*)" to "api-report\.md"/, + ); + if (match) { + conflictingFile = match[1]; + } } }, compilerState, @@ -203,7 +214,23 @@ async function runApiExtraction({ '*************************************************************************************', ); console.log(''); + + if (conflictingFile) { + console.log(''); + console.log( + `The conflicting file is ${relativePath( + tmpDir, + conflictingFile, + )}, with the following content:`, + ); + console.log(''); + + const content = await fs.readFile(conflictingFile, 'utf8'); + console.log(content); + console.log(''); + } } + throw new Error( `API Extractor completed with ${extractorResult.errorCount} errors` + ` and ${extractorResult.warningCount} warnings`, From 658de01647c9fbd3e206ccc3d6c9673b8c9e90ba Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 14 Apr 2021 20:00:37 +0200 Subject: [PATCH 169/262] scripts/api-extractor: disable all inline warnings Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- packages/backend-common/api-report.md | 123 ----------- packages/catalog-client/api-report.md | 22 +- packages/catalog-model/api-report.md | 251 +---------------------- packages/cli-common/api-report.md | 8 - packages/config-loader/api-report.md | 22 -- packages/config/api-report.md | 14 -- packages/dev-utils/api-report.md | 5 - packages/errors/api-report.md | 29 --- packages/integration-react/api-report.md | 4 - packages/integration/api-report.md | 148 +------------ packages/search-common/api-report.md | 12 -- packages/techdocs-common/api-report.md | 77 ------- packages/test-utils-core/api-report.md | 19 -- packages/test-utils/api-report.md | 19 -- packages/theme/api-report.md | 33 --- scripts/api-extractor.ts | 10 +- 16 files changed, 24 insertions(+), 772 deletions(-) diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 79a7ca1a5c..58b9aa36d9 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -29,33 +29,23 @@ import { Server } from 'http'; import * as winston from 'winston'; import { Writable } from 'stream'; -// Warning: (ae-missing-release-tag) "AzureUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class AzureUrlReader implements UrlReader { constructor(integration: AzureIntegration, deps: { treeResponseFactory: ReadTreeResponseFactory; }); - // Warning: (ae-forgotten-export) The symbol "ReaderFactory" needs to be exported by the entry point index.d.ts - // // (undocumented) static factory: ReaderFactory; // (undocumented) read(url: string): Promise<Buffer>; - // Warning: (ae-forgotten-export) The symbol "ReadTreeOptions" needs to be exported by the entry point index.d.ts - // // (undocumented) readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>; - // Warning: (ae-forgotten-export) The symbol "SearchOptions" needs to be exported by the entry point index.d.ts - // // (undocumented) search(url: string, options?: SearchOptions): Promise<SearchResponse>; // (undocumented) toString(): string; } -// Warning: (ae-missing-release-tag) "BitbucketUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class BitbucketUrlReader implements UrlReader { constructor(integration: BitbucketIntegration, deps: { @@ -73,52 +63,30 @@ export class BitbucketUrlReader implements UrlReader { toString(): string; } -// Warning: (ae-missing-release-tag) "coloredFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const coloredFormat: Format; -// Warning: (ae-missing-release-tag) "createDatabase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated export const createDatabase: typeof createDatabaseClient; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "createDatabaseClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function createDatabaseClient(dbConfig: Config, overrides?: Partial<Knex.Config>): Knex<any, unknown[]>; -// Warning: (ae-missing-release-tag) "createRootLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createRootLogger(options?: winston.LoggerOptions, env?: NodeJS.ProcessEnv): winston.Logger; -// Warning: (ae-forgotten-export) The symbol "ServiceBuilderImpl" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "createServiceBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function createServiceBuilder(_module: NodeModule): ServiceBuilderImpl; -// Warning: (ae-forgotten-export) The symbol "StatusCheckRouterOptions" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "createStatusCheckRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createStatusCheckRouter(options: StatusCheckRouterOptions): Promise<express.Router>; -// Warning: (ae-missing-release-tag) "ensureDatabaseExists" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function ensureDatabaseExists(dbConfig: Config, ...databases: Array<string>): Promise<void>; -// Warning: (ae-missing-release-tag) "errorHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function errorHandler(options?: ErrorHandlerOptions): ErrorRequestHandler; -// Warning: (ae-missing-release-tag) "ErrorHandlerOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ErrorHandlerOptions = { showStackTraces?: boolean; @@ -126,18 +94,12 @@ export type ErrorHandlerOptions = { logClientErrors?: boolean; }; -// Warning: (ae-missing-release-tag) "getRootLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function getRootLogger(): winston.Logger; -// Warning: (ae-missing-release-tag) "getVoidLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getVoidLogger(): winston.Logger; -// Warning: (ae-missing-release-tag) "Git" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class Git { // (undocumented) @@ -221,8 +183,6 @@ export class Git { }): Promise<string>; } -// Warning: (ae-missing-release-tag) "GithubUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class GithubUrlReader implements UrlReader { constructor(integration: GitHubIntegration, deps: { @@ -241,8 +201,6 @@ export class GithubUrlReader implements UrlReader { toString(): string; } -// Warning: (ae-missing-release-tag) "GitlabUrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class GitlabUrlReader implements UrlReader { constructor(integration: GitLabIntegration, deps: { @@ -260,34 +218,23 @@ export class GitlabUrlReader implements UrlReader { toString(): string; } -// Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "loadBackendConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function loadBackendConfig(options: Options): Promise<Config>; -// Warning: (ae-missing-release-tag) "notFoundHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function notFoundHandler(): RequestHandler; -// Warning: (ae-missing-release-tag) "PluginDatabaseManager" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface PluginDatabaseManager { getClient(): Promise<Knex>; } -// Warning: (ae-missing-release-tag) "PluginEndpointDiscovery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type PluginEndpointDiscovery = { getBaseUrl(pluginId: string): Promise<string>; getExternalBaseUrl(pluginId: string): Promise<string>; }; -// Warning: (ae-missing-release-tag) "ReadTreeResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ReadTreeResponse = { files(): Promise<ReadTreeResponseFile[]>; @@ -296,62 +243,36 @@ export type ReadTreeResponse = { etag: string; }; -// Warning: (ae-missing-release-tag) "ReadTreeResponseFile" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type ReadTreeResponseFile = { path: string; content(): Promise<Buffer>; }; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "requestLoggingHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function requestLoggingHandler(logger?: Logger): RequestHandler; -// Warning: (ae-missing-release-tag) "resolvePackagePath" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function resolvePackagePath(name: string, ...paths: string[]): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (ae-forgotten-export) The symbol "RunDockerContainerOptions" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "runDockerContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const runDockerContainer: ({ imageName, args, logStream, dockerClient, mountDirs, workingDir, envVars, createOptions, }: RunDockerContainerOptions) => Promise<{ error: any; statusCode: any; }>; -// Warning: (ae-missing-release-tag) "SearchResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type SearchResponse = { files: SearchResponseFile[]; etag: string; }; -// Warning: (ae-missing-release-tag) "SearchResponseFile" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type SearchResponseFile = { url: string; content(): Promise<Buffer>; }; -// Warning: (ae-missing-release-tag) "ServiceBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ServiceBuilder = { loadConfig(config: ConfigReader): ServiceBuilder; @@ -364,23 +285,15 @@ export type ServiceBuilder = { start(): Promise<Server>; }; -// Warning: (ae-missing-release-tag) "setRootLogger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function setRootLogger(newLogger: winston.Logger): void; -// Warning: (ae-missing-release-tag) "SingleConnectionDatabaseManager" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class SingleConnectionDatabaseManager { - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen forPlugin(pluginId: string): PluginDatabaseManager; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen static fromConfig(config: Config): SingleConnectionDatabaseManager; } -// Warning: (ae-missing-release-tag) "SingleHostDiscovery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class SingleHostDiscovery implements PluginEndpointDiscovery { static fromConfig(config: Config, options?: { @@ -392,26 +305,17 @@ export class SingleHostDiscovery implements PluginEndpointDiscovery { getExternalBaseUrl(pluginId: string): Promise<string>; } -// Warning: (ae-missing-release-tag) "StatusCheck" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type StatusCheck = () => Promise<any>; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "statusCheckHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function statusCheckHandler(options?: StatusCheckHandlerOptions): Promise<RequestHandler>; -// Warning: (ae-missing-release-tag) "StatusCheckHandlerOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface StatusCheckHandlerOptions { statusCheck?: StatusCheck; } -// Warning: (ae-missing-release-tag) "UrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type UrlReader = { read(url: string): Promise<Buffer>; @@ -419,46 +323,19 @@ export type UrlReader = { search(url: string, options?: SearchOptions): Promise<SearchResponse>; }; -// Warning: (ae-missing-release-tag) "UrlReaders" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class UrlReaders { - // Warning: (ae-forgotten-export) The symbol "CreateOptions" needs to be exported by the entry point index.d.ts static create({ logger, config, factories }: CreateOptions): UrlReader; static default({ logger, config, factories }: CreateOptions): UrlReader; } -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "useHotCleanup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function useHotCleanup(_module: NodeModule, cancelEffect: () => void): void; -// Warning: (tsdoc-undefined-tag) The TSDoc tag "@warning" is not defined in this configuration -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "useHotMemoize" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function useHotMemoize<T>(_module: NodeModule, valueFactory: () => T): T; -// Warnings were encountered during analysis: -// -// src/middleware/errorHandler.ts:47:24 - (tsdoc-malformed-html-name) Invalid HTML element: A space is not allowed here -// src/reading/AzureUrlReader.ts:53:30 - (ae-forgotten-export) The symbol "ReadTreeResponseFactory" needs to be exported by the entry point index.d.ts -// src/reading/types.ts:87:3 - (ae-forgotten-export) The symbol "ReadTreeResponseDirOptions" needs to be exported by the entry point index.d.ts -// src/service/types.ts:28:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/service/types.ts:39:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/service/types.ts:48:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/service/types.ts:57:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/service/types.ts:67:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/service/types.ts:76:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/service/types.ts:78:3 - (ae-forgotten-export) The symbol "HttpsSettings" needs to be exported by the entry point index.d.ts -// src/service/types.ts:83:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/service/types.ts:84:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index 467cf752af..a17a6cdc10 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -8,8 +8,6 @@ import { Entity } from '@backstage/catalog-model'; import { EntityName } from '@backstage/catalog-model'; import { Location as Location_2 } from '@backstage/catalog-model'; -// Warning: (ae-missing-release-tag) "AddLocationRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type AddLocationRequest = { type?: string; @@ -18,22 +16,16 @@ export type AddLocationRequest = { presence?: 'optional' | 'required'; }; -// Warning: (ae-missing-release-tag) "AddLocationResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type AddLocationResponse = { location: Location_2; entities: Entity[]; }; -// Warning: (ae-missing-release-tag) "CatalogApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface CatalogApi { // (undocumented) addLocation(location: AddLocationRequest, options?: CatalogRequestOptions): Promise<AddLocationResponse>; - // Warning: (ae-forgotten-export) The symbol "CatalogRequestOptions" needs to be exported by the entry point index.d.ts - // // (undocumented) getEntities(request?: CatalogEntitiesRequest, options?: CatalogRequestOptions): Promise<CatalogListResponse<Entity>>; // (undocumented) @@ -41,7 +33,7 @@ export interface CatalogApi { // (undocumented) getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; // (undocumented) - getLocationById(id: String, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + getLocationById(id: string, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; // (undocumented) getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; // (undocumented) @@ -50,8 +42,6 @@ export interface CatalogApi { removeLocationById(id: string, options?: CatalogRequestOptions): Promise<void>; } -// Warning: (ae-missing-release-tag) "CatalogClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class CatalogClient implements CatalogApi { constructor(options: { @@ -66,7 +56,7 @@ export class CatalogClient implements CatalogApi { // (undocumented) getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; // (undocumented) - getLocationById(id: String, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; + getLocationById(id: string, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; // (undocumented) getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location_2 | undefined>; // (undocumented) @@ -75,26 +65,18 @@ export class CatalogClient implements CatalogApi { removeLocationById(id: string, options?: CatalogRequestOptions): Promise<void>; } -// Warning: (ae-missing-release-tag) "CatalogEntitiesRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type CatalogEntitiesRequest = { filter?: Record<string, string | string[]> | undefined; fields?: string[] | undefined; }; -// Warning: (ae-missing-release-tag) "CatalogListResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type CatalogListResponse<T> = { items: T[]; }; -// Warnings were encountered during analysis: -// -// src/CatalogClient.ts:40:26 - (ae-forgotten-export) The symbol "DiscoveryApi" needs to be exported by the entry point index.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index 7aa98e52c7..c37c86b01f 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -9,23 +9,15 @@ import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/config'; import * as yup from 'yup'; -// Warning: (ae-missing-release-tag) "analyzeLocationSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const analyzeLocationSchema: yup.ObjectSchema<{ location: LocationSpec; }, object>; -// Warning: (ae-missing-release-tag) "ApiEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface ApiEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND; // (undocumented) @@ -42,53 +34,26 @@ export { ApiEntityV1alpha1 as ApiEntity } export { ApiEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "apiEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const apiEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "CommonValidatorFunctions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class CommonValidatorFunctions { - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen static isJsonSafe(value: unknown): boolean; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool static isValidDnsLabel(value: unknown): boolean; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool static isValidDnsSubdomain(value: unknown): boolean; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen static isValidPrefixAndOrSuffix(value: unknown, separator: string, isValidPrefix: (value: string) => boolean, isValidSuffix: (value: string) => boolean): boolean; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen static isValidString(value: unknown): boolean; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen static isValidUrl(value: unknown): boolean; } -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-forgotten-export) The symbol "EntityRefContext" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "compareEntityToRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function compareEntityToRef(entity: Entity, ref: EntityRef | EntityName, context?: EntityRefContext): boolean; -// Warning: (ae-missing-release-tag) "ComponentEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface ComponentEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_2[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_2; // (undocumented) @@ -99,6 +64,7 @@ interface ComponentEntityV1alpha1 extends Entity { subcomponentOf?: string; providesApis?: string[]; consumesApis?: string[]; + dependsOn?: string[]; system?: string; }; } @@ -107,13 +73,9 @@ export { ComponentEntityV1alpha1 as ComponentEntity } export { ComponentEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "componentEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const componentEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "DefaultNamespaceEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class DefaultNamespaceEntityPolicy implements EntityPolicy { constructor(namespace?: string); @@ -121,16 +83,10 @@ export class DefaultNamespaceEntityPolicy implements EntityPolicy { enforce(entity: Entity): Promise<Entity>; } -// Warning: (ae-missing-release-tag) "DomainEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface DomainEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_3[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_3; // (undocumented) @@ -143,19 +99,12 @@ export { DomainEntityV1alpha1 as DomainEntity } export { DomainEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "domainEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const domainEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "EDIT_URL_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const EDIT_URL_ANNOTATION = "backstage.io/edit-url"; -// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool -// Warning: (ae-missing-release-tag) "Entity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type Entity = { apiVersion: string; @@ -165,25 +114,15 @@ export type Entity = { relations?: EntityRelation[]; }; -// Warning: (ae-missing-release-tag) "ENTITY_DEFAULT_NAMESPACE" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const ENTITY_DEFAULT_NAMESPACE = "default"; -// Warning: (ae-missing-release-tag) "ENTITY_META_GENERATED_FIELDS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const ENTITY_META_GENERATED_FIELDS: readonly ["uid", "etag", "generation"]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "entityHasChanges" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function entityHasChanges(previous: Entity, next: Entity): boolean; -// Warning: (ae-missing-release-tag) "EntityLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type EntityLink = { url: string; @@ -191,10 +130,6 @@ export type EntityLink = { icon?: string; }; -// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool -// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool -// Warning: (ae-missing-release-tag) "EntityMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type EntityMeta = JsonObject & { uid?: string; @@ -209,8 +144,6 @@ export type EntityMeta = JsonObject & { links?: EntityLink[]; }; -// Warning: (ae-missing-release-tag) "EntityName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type EntityName = { kind: string; @@ -218,23 +151,17 @@ export type EntityName = { name: string; }; -// Warning: (ae-missing-release-tag) "EntityPolicies" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const EntityPolicies: { allOf(policies: EntityPolicy[]): AllEntityPolicies; oneOf(policies: EntityPolicy[]): AnyEntityPolicy; }; -// Warning: (ae-missing-release-tag) "EntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type EntityPolicy = { enforce(entity: Entity): Promise<Entity | undefined>; }; -// Warning: (ae-missing-release-tag) "EntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type EntityRef = string | { kind?: string; @@ -242,16 +169,12 @@ export type EntityRef = string | { name: string; }; -// Warning: (ae-missing-release-tag) "EntityRelation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type EntityRelation = { type: string; target: EntityName; }; -// Warning: (ae-missing-release-tag) "EntityRelationSpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type EntityRelationSpec = { source: EntityName; @@ -259,8 +182,6 @@ export type EntityRelationSpec = { target: EntityName; }; -// Warning: (ae-missing-release-tag) "FieldFormatEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class FieldFormatEntityPolicy implements EntityPolicy { constructor(validators?: Validators); @@ -268,39 +189,28 @@ export class FieldFormatEntityPolicy implements EntityPolicy { enforce(entity: Entity): Promise<Entity>; } -// Warning: (ae-missing-release-tag) "generateEntityEtag" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function generateEntityEtag(): string; -// Warning: (ae-missing-release-tag) "generateEntityUid" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function generateEntityUid(): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "generateUpdatedEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function generateUpdatedEntity(previous: Entity, next: Entity): Entity; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getEntityName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getEntityName(entity: Entity): EntityName; -// Warning: (ae-missing-release-tag) "GroupEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public +export function getEntitySourceLocation(entity: Entity): { + type: string; + target: string; +}; + // @public (undocumented) interface GroupEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_4[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_4; // (undocumented) @@ -321,30 +231,19 @@ export { GroupEntityV1alpha1 as GroupEntity } export { GroupEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "groupEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const groupEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "JSONSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type JSONSchema = JSONSchema7 & { [key in string]?: JsonValue; }; -// Warning: (ae-missing-release-tag) "KindValidator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type KindValidator = { check(entity: Entity): Promise<boolean>; }; -// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool -// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool -// Warning: (tsdoc-unsupported-tag) The TSDoc tag "@see" is not supported by this tool -// Warning: (ae-missing-release-tag) "KubernetesValidatorFunctions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class KubernetesValidatorFunctions { // (undocumented) @@ -365,8 +264,6 @@ export class KubernetesValidatorFunctions { static isValidObjectName(value: unknown): boolean; } -// Warning: (ae-missing-release-tag) "Location" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) type Location_2 = { id: string; @@ -374,21 +271,13 @@ type Location_2 = { export { Location_2 as Location } -// Warning: (ae-missing-release-tag) "LOCATION_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const LOCATION_ANNOTATION = "backstage.io/managed-by-location"; -// Warning: (ae-missing-release-tag) "LocationEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface LocationEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_5[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_5; // (undocumented) @@ -403,18 +292,12 @@ export { LocationEntityV1alpha1 as LocationEntity } export { LocationEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "locationEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const locationEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "locationSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const locationSchema: yup.ObjectSchema<Location_2, object>; -// Warning: (ae-missing-release-tag) "LocationSpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type LocationSpec = { type: string; @@ -422,18 +305,12 @@ export type LocationSpec = { presence?: 'optional' | 'required'; }; -// Warning: (ae-missing-release-tag) "locationSpecSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const locationSpecSchema: yup.ObjectSchema<LocationSpec, object>; -// Warning: (ae-missing-release-tag) "makeValidator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function makeValidator(overrides?: Partial<Validators>): Validators; -// Warning: (ae-missing-release-tag) "NoForeignRootFieldsEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class NoForeignRootFieldsEntityPolicy implements EntityPolicy { constructor(knownFields?: string[]); @@ -441,24 +318,12 @@ export class NoForeignRootFieldsEntityPolicy implements EntityPolicy { enforce(entity: Entity): Promise<Entity>; } -// Warning: (ae-missing-release-tag) "ORIGIN_LOCATION_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const ORIGIN_LOCATION_ANNOTATION = "backstage.io/managed-by-origin-location"; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "parseEntityName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function parseEntityName(ref: EntityRef, context?: EntityRefContext): EntityName; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "parseEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// Warning: (ae-missing-release-tag) "parseEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// Warning: (ae-missing-release-tag) "parseEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function parseEntityRef(ref: EntityRef, context?: { defaultKind: string; @@ -487,103 +352,65 @@ export function parseEntityRef(ref: EntityRef, context?: { name: string; }; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (ae-missing-release-tag) "parseLocationReference" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function parseLocationReference(ref: string): { type: string; target: string; }; -// Warning: (ae-missing-release-tag) "RELATION_API_CONSUMED_BY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_API_CONSUMED_BY = "apiConsumedBy"; -// Warning: (ae-missing-release-tag) "RELATION_API_PROVIDED_BY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_API_PROVIDED_BY = "apiProvidedBy"; -// Warning: (ae-missing-release-tag) "RELATION_CHILD_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_CHILD_OF = "childOf"; -// Warning: (ae-missing-release-tag) "RELATION_CONSUMES_API" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const RELATION_CONSUMES_API = "consumesApi"; -// Warning: (ae-missing-release-tag) "RELATION_DEPENDENCY_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_DEPENDENCY_OF = "dependencyOf"; -// Warning: (ae-missing-release-tag) "RELATION_DEPENDS_ON" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const RELATION_DEPENDS_ON = "dependsOn"; -// Warning: (ae-missing-release-tag) "RELATION_HAS_MEMBER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_HAS_MEMBER = "hasMember"; -// Warning: (ae-missing-release-tag) "RELATION_HAS_PART" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_HAS_PART = "hasPart"; -// Warning: (ae-missing-release-tag) "RELATION_MEMBER_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const RELATION_MEMBER_OF = "memberOf"; -// Warning: (ae-missing-release-tag) "RELATION_OWNED_BY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const RELATION_OWNED_BY = "ownedBy"; -// Warning: (ae-missing-release-tag) "RELATION_OWNER_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_OWNER_OF = "ownerOf"; -// Warning: (ae-missing-release-tag) "RELATION_PARENT_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const RELATION_PARENT_OF = "parentOf"; -// Warning: (ae-missing-release-tag) "RELATION_PART_OF" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const RELATION_PART_OF = "partOf"; -// Warning: (ae-missing-release-tag) "RELATION_PROVIDES_API" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const RELATION_PROVIDES_API = "providesApi"; -// Warning: (ae-missing-release-tag) "ResourceEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface ResourceEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_6[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_6; // (undocumented) spec: { type: string; owner: string; + dependsOn?: string[]; system?: string; }; } @@ -592,27 +419,18 @@ export { ResourceEntityV1alpha1 as ResourceEntity } export { ResourceEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "resourceEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const resourceEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "schemaValidator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated (undocumented) export function schemaValidator(kind: string, apiVersion: readonly string[], schema: yup.Schema<any>): KindValidator; -// Warning: (ae-missing-release-tag) "SchemaValidEntityPolicy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class SchemaValidEntityPolicy implements EntityPolicy { // (undocumented) enforce(entity: Entity): Promise<Entity>; } -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "serializeEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated export function serializeEntityRef(ref: Entity | { kind?: string; @@ -620,14 +438,9 @@ export function serializeEntityRef(ref: Entity | { name: string; }): EntityRef; -// Warning: (ae-missing-release-tag) "SOURCE_LOCATION_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const SOURCE_LOCATION_ANNOTATION = "backstage.io/source-location"; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "stringifyEntityRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function stringifyEntityRef(ref: Entity | { kind: string; @@ -635,27 +448,16 @@ export function stringifyEntityRef(ref: Entity | { name: string; }): string; -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "stringifyLocationReference" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function stringifyLocationReference(ref: { type: string; target: string; }): string; -// Warning: (ae-missing-release-tag) "SystemEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface SystemEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_7[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_7; // (undocumented) @@ -669,21 +471,13 @@ export { SystemEntityV1alpha1 as SystemEntity } export { SystemEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "systemEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const systemEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "TemplateEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface TemplateEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_8[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_8; // (undocumented) @@ -699,21 +493,13 @@ export { TemplateEntityV1alpha1 as TemplateEntity } export { TemplateEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "templateEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const templateEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "TemplateEntityV1beta2" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface TemplateEntityV1beta2 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_9[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_9; // (undocumented) @@ -736,21 +522,13 @@ export interface TemplateEntityV1beta2 extends Entity { }; } -// Warning: (ae-missing-release-tag) "templateEntityV1beta2Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const templateEntityV1beta2Validator: KindValidator; -// Warning: (ae-missing-release-tag) "UserEntityV1alpha1" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface UserEntityV1alpha1 extends Entity { - // Warning: (ae-forgotten-export) The symbol "API_VERSION" needs to be exported by the entry point index.d.ts - // // (undocumented) apiVersion: typeof API_VERSION_10[number]; - // Warning: (ae-forgotten-export) The symbol "KIND" needs to be exported by the entry point index.d.ts - // // (undocumented) kind: typeof KIND_10; // (undocumented) @@ -768,13 +546,9 @@ export { UserEntityV1alpha1 as UserEntity } export { UserEntityV1alpha1 } -// Warning: (ae-missing-release-tag) "userEntityV1alpha1Validator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const userEntityV1alpha1Validator: KindValidator; -// Warning: (ae-missing-release-tag) "Validators" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type Validators = { isValidApiVersion(value: unknown): boolean; @@ -788,19 +562,10 @@ export type Validators = { isValidTag(value: unknown): boolean; }; -// Warning: (ae-missing-release-tag) "VIEW_URL_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const VIEW_URL_ANNOTATION = "backstage.io/view-url"; -// Warnings were encountered during analysis: -// -// src/EntityPolicies.ts:55:28 - (ae-forgotten-export) The symbol "AllEntityPolicies" needs to be exported by the entry point index.d.ts -// src/EntityPolicies.ts:57:3 - (ae-forgotten-export) The symbol "AnyEntityPolicy" needs to be exported by the entry point index.d.ts -// src/entity/policies/types.ts:27:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/kinds/types.ts:26:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/cli-common/api-report.md b/packages/cli-common/api-report.md index f4df3562b8..bcdc023c22 100644 --- a/packages/cli-common/api-report.md +++ b/packages/cli-common/api-report.md @@ -4,13 +4,9 @@ ```ts -// Warning: (ae-missing-release-tag) "findPaths" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function findPaths(searchDir: string): Paths; -// Warning: (ae-missing-release-tag) "Paths" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type Paths = { ownDir: string; @@ -24,10 +20,6 @@ export type Paths = { }; -// Warnings were encountered during analysis: -// -// src/paths.ts:38:3 - (ae-forgotten-export) The symbol "ResolveFunc" needs to be exported by the entry point index.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/config-loader/api-report.md b/packages/config-loader/api-report.md index ffa599df2b..a09311b786 100644 --- a/packages/config-loader/api-report.md +++ b/packages/config-loader/api-report.md @@ -8,27 +8,18 @@ import { AppConfig } from '@backstage/config'; import { JsonObject } from '@backstage/config'; import { JSONSchema7 } from 'json-schema'; -// Warning: (ae-missing-release-tag) "ConfigSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type ConfigSchema = { process(appConfigs: AppConfig[], options?: ConfigProcessingOptions): AppConfig[]; serialize(): JsonObject; }; -// Warning: (ae-forgotten-export) The symbol "CONFIG_VISIBILITIES" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "ConfigVisibility" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type ConfigVisibility = typeof CONFIG_VISIBILITIES[number]; -// Warning: (ae-missing-release-tag) "loadConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function loadConfig(options: LoadConfigOptions): Promise<AppConfig[]>; -// Warning: (ae-missing-release-tag) "LoadConfigOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type LoadConfigOptions = { configRoot: string; @@ -37,31 +28,18 @@ export type LoadConfigOptions = { experimentalEnvFunc?: EnvFunc; }; -// Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "loadConfigSchema" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function loadConfigSchema(options: Options): Promise<ConfigSchema>; -// Warning: (ae-missing-release-tag) "mergeConfigSchemas" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function mergeConfigSchemas(schemas: JSONSchema7[]): JSONSchema7; -// Warning: (ae-missing-release-tag) "readEnvConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readEnvConfig(env: { [name: string]: string | undefined; }): AppConfig[]; -// Warnings were encountered during analysis: -// -// src/lib/schema/types.ts:105:3 - (ae-forgotten-export) The symbol "ConfigProcessingOptions" needs to be exported by the entry point index.d.ts -// src/loader.ts:42:6 - (tsdoc-unsupported-tag) The TSDoc tag "@experimental" is not supported by this tool -// src/loader.ts:44:3 - (ae-forgotten-export) The symbol "EnvFunc" needs to be exported by the entry point index.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/config/api-report.md b/packages/config/api-report.md index 4e0da777ec..be250778ec 100644 --- a/packages/config/api-report.md +++ b/packages/config/api-report.md @@ -4,16 +4,12 @@ ```ts -// Warning: (ae-missing-release-tag) "AppConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type AppConfig = { context: string; data: JsonObject; }; -// Warning: (ae-missing-release-tag) "Config" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type Config = { has(key: string): boolean; @@ -34,8 +30,6 @@ export type Config = { getOptionalStringArray(key: string): string[] | undefined; }; -// Warning: (ae-missing-release-tag) "ConfigReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class ConfigReader implements Config { constructor(data: JsonObject | undefined, context?: string, fallback?: ConfigReader | undefined, prefix?: string); @@ -75,26 +69,18 @@ export class ConfigReader implements Config { keys(): string[]; } -// Warning: (ae-missing-release-tag) "JsonArray" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface JsonArray extends Array<JsonValue> { } -// Warning: (ae-missing-release-tag) "JsonObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type JsonObject = { [key in string]?: JsonValue; }; -// Warning: (ae-missing-release-tag) "JsonPrimitive" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type JsonPrimitive = number | string | boolean | null; -// Warning: (ae-missing-release-tag) "JsonValue" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type JsonValue = JsonObject | JsonArray | JsonPrimitive; diff --git a/packages/dev-utils/api-report.md b/packages/dev-utils/api-report.md index 841f9c19b2..d3e6447cd5 100644 --- a/packages/dev-utils/api-report.md +++ b/packages/dev-utils/api-report.md @@ -12,14 +12,9 @@ import { GridProps } from '@material-ui/core'; import { IconComponent } from '@backstage/core'; import { ReactNode } from 'react'; -// Warning: (ae-forgotten-export) The symbol "DevAppBuilder" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "createDevApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function createDevApp(): DevAppBuilder; -// Warning: (ae-missing-release-tag) "EntityGridItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const EntityGridItem: ({ entity, classes, ...rest }: Omit<GridProps<"div", {}>, "container" | "item"> & { entity: Entity; diff --git a/packages/errors/api-report.md b/packages/errors/api-report.md index 18861fdc84..cb24cba80f 100644 --- a/packages/errors/api-report.md +++ b/packages/errors/api-report.md @@ -6,20 +6,14 @@ import { JsonObject } from '@backstage/config'; -// Warning: (ae-missing-release-tag) "AuthenticationError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class AuthenticationError extends CustomErrorBase { } -// Warning: (ae-missing-release-tag) "ConflictError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class ConflictError extends CustomErrorBase { } -// Warning: (ae-missing-release-tag) "CustomErrorBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class CustomErrorBase extends Error { constructor(message?: string, cause?: Error); @@ -27,13 +21,9 @@ export class CustomErrorBase extends Error { readonly cause?: Error; } -// Warning: (ae-missing-release-tag) "deserializeError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function deserializeError<T extends Error = Error>(data: SerializedError): T; -// Warning: (ae-missing-release-tag) "ErrorResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type ErrorResponse = { error: SerializedError; @@ -46,38 +36,25 @@ export type ErrorResponse = { }; }; -// Warning: (ae-missing-release-tag) "InputError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class InputError extends CustomErrorBase { } -// Warning: (ae-missing-release-tag) "NotAllowedError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class NotAllowedError extends CustomErrorBase { } -// Warning: (ae-missing-release-tag) "NotFoundError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class NotFoundError extends CustomErrorBase { } -// Warning: (ae-missing-release-tag) "NotModifiedError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class NotModifiedError extends CustomErrorBase { } -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "parseErrorResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function parseErrorResponse(response: Response): Promise<ErrorResponse>; -// Warning: (ae-missing-release-tag) "ResponseError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class ResponseError extends Error { constructor(props: { @@ -92,8 +69,6 @@ export class ResponseError extends Error { readonly response: Response; } -// Warning: (ae-missing-release-tag) "SerializedError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type SerializedError = JsonObject & { name: string; @@ -102,10 +77,6 @@ export type SerializedError = JsonObject & { code?: string; }; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// Warning: (ae-missing-release-tag) "serializeError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function serializeError(error: Error, options?: { includeStack?: boolean; diff --git a/packages/integration-react/api-report.md b/packages/integration-react/api-report.md index 8dcc02a443..7c37ab0392 100644 --- a/packages/integration-react/api-report.md +++ b/packages/integration-react/api-report.md @@ -8,16 +8,12 @@ import { ApiRef } from '@backstage/core'; import { Config } from '@backstage/config'; import { ScmIntegrationRegistry } from '@backstage/integration'; -// Warning: (ae-missing-release-tag) "ScmIntegrationsApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class ScmIntegrationsApi { // (undocumented) static fromConfig(config: Config): ScmIntegrationRegistry; } -// Warning: (ae-missing-release-tag) "scmIntegrationsApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const scmIntegrationsApiRef: ApiRef<ScmIntegrationRegistry>; diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md index 6d85bf4a51..5387eb12db 100644 --- a/packages/integration/api-report.md +++ b/packages/integration/api-report.md @@ -6,15 +6,11 @@ import { Config } from '@backstage/config'; -// Warning: (ae-missing-release-tag) "AzureIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class AzureIntegration implements ScmIntegration { constructor(integrationConfig: AzureIntegrationConfig); // (undocumented) get config(): AzureIntegrationConfig; - // Warning: (ae-forgotten-export) The symbol "ScmIntegrationsFactory" needs to be exported by the entry point index.d.ts - // // (undocumented) static factory: ScmIntegrationsFactory<AzureIntegration>; // (undocumented) @@ -31,16 +27,12 @@ export class AzureIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "AzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type AzureIntegrationConfig = { host: string; token?: string; }; -// Warning: (ae-missing-release-tag) "BitbucketIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class BitbucketIntegration implements ScmIntegration { constructor(integrationConfig: BitbucketIntegrationConfig); @@ -62,8 +54,6 @@ export class BitbucketIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "BitbucketIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type BitbucketIntegrationConfig = { host: string; @@ -73,8 +63,6 @@ export type BitbucketIntegrationConfig = { appPassword?: string; }; -// Warning: (ae-missing-release-tag) "defaultScmResolveUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function defaultScmResolveUrl(options: { url: string; @@ -82,123 +70,51 @@ export function defaultScmResolveUrl(options: { lineNumber?: number; }): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureCommitsUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureCommitsUrl(url: string): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureDownloadUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureDownloadUrl(url: string): string; -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureFileFetchUrl(url: string): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getAzureRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getAzureRequestOptions(config: AzureIntegrationConfig, additionalHeaders?: Record<string, string>): RequestInit; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketDefaultBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketDefaultBranch(url: string, config: BitbucketIntegrationConfig): Promise<string>; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketDownloadUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketDownloadUrl(url: string, config: BitbucketIntegrationConfig): Promise<string>; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketFileFetchUrl(url: string, config: BitbucketIntegrationConfig): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getBitbucketRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getBitbucketRequestOptions(config: BitbucketIntegrationConfig): RequestInit; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getGitHubFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getGitHubFileFetchUrl(url: string, config: GitHubIntegrationConfig): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getGitHubRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getGitHubRequestOptions(config: GitHubIntegrationConfig): RequestInit; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getGitLabFileFetchUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getGitLabFileFetchUrl(url: string, config: GitLabIntegrationConfig): Promise<string>; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "getGitLabRequestOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getGitLabRequestOptions(config: GitLabIntegrationConfig): RequestInit; -// Warning: (ae-missing-release-tag) "GithubCredentialsProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class GithubCredentialsProvider { // (undocumented) static create(config: GitHubIntegrationConfig): GithubCredentialsProvider; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // Warning: (tsdoc-undefined-tag) The TSDoc tag "@type" is not defined in this configuration - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // Warning: (ae-forgotten-export) The symbol "GithubCredentials" needs to be exported by the entry point index.d.ts getCredentials(opts: { url: string; }): Promise<GithubCredentials>; } -// Warning: (ae-missing-release-tag) "GitHubIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class GitHubIntegration implements ScmIntegration { constructor(integrationConfig: GitHubIntegrationConfig); @@ -220,8 +136,6 @@ export class GitHubIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "GitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type GitHubIntegrationConfig = { host: string; @@ -231,8 +145,6 @@ export type GitHubIntegrationConfig = { apps?: GithubAppConfig[]; }; -// Warning: (ae-missing-release-tag) "GitLabIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class GitLabIntegration implements ScmIntegration { constructor(integrationConfig: GitLabIntegrationConfig); @@ -254,8 +166,6 @@ export class GitLabIntegration implements ScmIntegration { get type(): string; } -// Warning: (ae-missing-release-tag) "GitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type GitLabIntegrationConfig = { host: string; @@ -264,63 +174,42 @@ export type GitLabIntegrationConfig = { baseUrl: string; }; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readAzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public +export type GoogleGcsIntegrationConfig = { + clientEmail?: string; + privateKey?: string; +}; + // @public export function readAzureIntegrationConfig(config: Config): AzureIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readAzureIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readAzureIntegrationConfigs(configs: Config[]): AzureIntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readBitbucketIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readBitbucketIntegrationConfig(config: Config): BitbucketIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readBitbucketIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readBitbucketIntegrationConfigs(configs: Config[]): BitbucketIntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitHubIntegrationConfig(config: Config): GitHubIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitHubIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitHubIntegrationConfigs(configs: Config[]): GitHubIntegrationConfig[]; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitLabIntegrationConfig(config: Config): GitLabIntegrationConfig; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "readGitLabIntegrationConfigs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function readGitLabIntegrationConfigs(configs: Config[]): GitLabIntegrationConfig[]; -// Warning: (ae-missing-release-tag) "ScmIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public +export function readGoogleGcsIntegrationConfig(config: Config): GoogleGcsIntegrationConfig; + // @public export interface ScmIntegration { - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen resolveEditUrl(url: string): string; - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters resolveUrl(options: { url: string; base: string; @@ -330,8 +219,6 @@ export interface ScmIntegration { type: string; } -// Warning: (ae-missing-release-tag) "ScmIntegrationRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface ScmIntegrationRegistry extends ScmIntegrationsGroup<ScmIntegration> { // (undocumented) @@ -342,11 +229,7 @@ export interface ScmIntegrationRegistry extends ScmIntegrationsGroup<ScmIntegrat github: ScmIntegrationsGroup<GitHubIntegration>; // (undocumented) gitlab: ScmIntegrationsGroup<GitLabIntegration>; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen resolveEditUrl(url: string): string; - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters - // Warning: (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters resolveUrl(options: { url: string; base: string; @@ -354,11 +237,8 @@ export interface ScmIntegrationRegistry extends ScmIntegrationsGroup<ScmIntegrat }): string; } -// Warning: (ae-missing-release-tag) "ScmIntegrations" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class ScmIntegrations implements ScmIntegrationRegistry { - // Warning: (ae-forgotten-export) The symbol "IntegrationsByType" needs to be exported by the entry point index.d.ts constructor(integrationsByType: IntegrationsByType); // (undocumented) get azure(): ScmIntegrationsGroup<AzureIntegration>; @@ -386,24 +266,14 @@ export class ScmIntegrations implements ScmIntegrationRegistry { }): string; } -// Warning: (ae-missing-release-tag) "ScmIntegrationsGroup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface ScmIntegrationsGroup<T extends ScmIntegration> { - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen byHost(host: string): T | undefined; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen byUrl(url: string | URL): T | undefined; list(): T[]; } -// Warnings were encountered during analysis: -// -// src/github/config.ts:67:3 - (ae-forgotten-export) The symbol "GithubAppConfig" needs to be exported by the entry point index.d.ts -// src/gitlab/config.ts:51:66 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// src/gitlab/config.ts:51:61 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/search-common/api-report.md b/packages/search-common/api-report.md index ed53275017..70522f4ee4 100644 --- a/packages/search-common/api-report.md +++ b/packages/search-common/api-report.md @@ -6,24 +6,18 @@ import { JsonObject } from '@backstage/config'; -// Warning: (ae-missing-release-tag) "DocumentCollator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface DocumentCollator { // (undocumented) execute(): Promise<IndexableDocument[]>; } -// Warning: (ae-missing-release-tag) "DocumentDecorator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface DocumentDecorator { // (undocumented) execute(documents: IndexableDocument[]): Promise<IndexableDocument[]>; } -// Warning: (ae-missing-release-tag) "IndexableDocument" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface IndexableDocument { location: string; @@ -31,8 +25,6 @@ export interface IndexableDocument { title: string; } -// Warning: (ae-missing-release-tag) "SearchQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface SearchQuery { // (undocumented) @@ -43,16 +35,12 @@ export interface SearchQuery { term: string; } -// Warning: (ae-missing-release-tag) "SearchResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface SearchResult { // (undocumented) document: IndexableDocument; } -// Warning: (ae-missing-release-tag) "SearchResultSet" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface SearchResultSet { // (undocumented) diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md index aa6c9da2f8..c26f62e981 100644 --- a/packages/techdocs-common/api-report.md +++ b/packages/techdocs-common/api-report.md @@ -17,26 +17,18 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; -// Warning: (ae-missing-release-tag) "checkoutGitRepository" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger) => Promise<string>; -// Warning: (ae-missing-release-tag) "CommonGitPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class CommonGitPreparer implements PreparerBase { constructor(config: Config, logger: Logger); - // Warning: (ae-forgotten-export) The symbol "PreparerResponse" needs to be exported by the entry point index.d.ts - // // (undocumented) prepare(entity: Entity, options?: { etag?: string; }): Promise<PreparerResponse>; } -// Warning: (ae-missing-release-tag) "DirectoryPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class DirectoryPreparer implements PreparerBase { constructor(config: Config, logger: Logger, reader: UrlReader); @@ -44,23 +36,17 @@ export class DirectoryPreparer implements PreparerBase { prepare(entity: Entity): Promise<PreparerResponse>; } -// Warning: (ae-missing-release-tag) "GeneratorBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type GeneratorBase = { run(opts: GeneratorRunOptions): Promise<void>; }; -// Warning: (ae-missing-release-tag) "GeneratorBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type GeneratorBuilder = { register(protocol: SupportedGeneratorKey, generator: GeneratorBase): void; get(entity: Entity): GeneratorBase; }; -// Warning: (ae-missing-release-tag) "Generators" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class Generators implements GeneratorBuilder { // (undocumented) @@ -73,79 +59,51 @@ export class Generators implements GeneratorBuilder { register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase): void; } -// Warning: (ae-missing-release-tag) "getAzureIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getAzureIntegrationConfig: (config: Config, host: string) => AzureIntegrationConfig; -// Warning: (ae-missing-release-tag) "getDefaultBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getDefaultBranch: (repositoryUrl: string, config: Config) => Promise<string>; -// Warning: (ae-missing-release-tag) "getDocFilesFromRepository" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getDocFilesFromRepository: (reader: UrlReader, entity: Entity, opts?: { etag?: string | undefined; logger?: Logger | undefined; } | undefined) => Promise<PreparerResponse>; -// Warning: (ae-missing-release-tag) "getGitHost" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function getGitHost(url: string): string; -// Warning: (ae-missing-release-tag) "getGitHubIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getGitHubIntegrationConfig: (config: Config, host: string) => GitHubIntegrationConfig; -// Warning: (ae-missing-release-tag) "getGitLabIntegrationConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getGitLabIntegrationConfig: (config: Config, host: string) => GitLabIntegrationConfig; -// Warning: (ae-missing-release-tag) "getGitRepositoryTempFolder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getGitRepositoryTempFolder: (repositoryUrl: string, config: Config) => Promise<string>; -// Warning: (ae-missing-release-tag) "getGitRepoType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function getGitRepoType(url: string): string; -// Warning: (ae-missing-release-tag) "getLastCommitTimestamp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger) => Promise<number>; -// Warning: (ae-missing-release-tag) "getLocationForEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getLocationForEntity: (entity: Entity) => ParsedLocationAnnotation; -// Warning: (ae-missing-release-tag) "getTokenForGitRepo" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const getTokenForGitRepo: (repositoryUrl: string, config: Config) => Promise<string | undefined>; -// Warning: (ae-missing-release-tag) "ParsedLocationAnnotation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ParsedLocationAnnotation = { type: RemoteProtocol; target: string; }; -// Warning: (ae-missing-release-tag) "parseReferenceAnnotation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const parseReferenceAnnotation: (annotationName: string, entity: Entity) => ParsedLocationAnnotation; -// Warning: (ae-missing-release-tag) "PreparerBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type PreparerBase = { prepare(entity: Entity, options?: { @@ -154,20 +112,14 @@ export type PreparerBase = { }): Promise<PreparerResponse>; }; -// Warning: (ae-missing-release-tag) "PreparerBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type PreparerBuilder = { register(protocol: RemoteProtocol, preparer: PreparerBase): void; get(entity: Entity): PreparerBase; }; -// Warning: (ae-missing-release-tag) "Preparers" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class Preparers implements PreparerBuilder { - // Warning: (ae-forgotten-export) The symbol "factoryOptions" needs to be exported by the entry point index.d.ts - // // (undocumented) static fromConfig(config: Config, { logger, reader }: factoryOptions): Promise<PreparerBuilder>; // (undocumented) @@ -176,41 +128,26 @@ export class Preparers implements PreparerBuilder { register(protocol: RemoteProtocol, preparer: PreparerBase): void; } -// Warning: (ae-missing-release-tag) "Publisher" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export class Publisher { - // Warning: (ae-forgotten-export) The symbol "factoryOptions" needs to be exported by the entry point index.d.ts - // // (undocumented) static fromConfig(config: Config, { logger, discovery }: factoryOptions_2): Promise<PublisherBase>; } -// Warning: (ae-missing-release-tag) "PublisherBase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export interface PublisherBase { docsRouter(): express.Handler; fetchTechDocsMetadata(entityName: EntityName): Promise<TechDocsMetadata>; hasDocsBeenGenerated(entityName: Entity): Promise<boolean>; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen - // Warning: (ae-forgotten-export) The symbol "PublishRequest" needs to be exported by the entry point index.d.ts - // Warning: (ae-forgotten-export) The symbol "PublishResponse" needs to be exported by the entry point index.d.ts publish(request: PublishRequest): Promise<PublishResponse>; } -// Warning: (ae-missing-release-tag) "PublisherType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type PublisherType = 'local' | 'googleGcs' | 'awsS3' | 'azureBlobStorage' | 'openStackSwift'; -// Warning: (ae-missing-release-tag) "RemoteProtocol" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type RemoteProtocol = 'url' | 'dir' | 'github' | 'gitlab' | 'file' | 'azure/api'; -// Warning: (ae-missing-release-tag) "TechdocsGenerator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class TechdocsGenerator implements GeneratorBase { constructor(logger: Logger, config: Config); @@ -218,9 +155,6 @@ export class TechdocsGenerator implements GeneratorBase { run({ inputDir, outputDir, dockerClient, parsedLocationAnnotation, etag, }: GeneratorRunOptions): Promise<void>; } -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "TechDocsMetadata" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type TechDocsMetadata = { site_name: string; @@ -228,8 +162,6 @@ export type TechDocsMetadata = { etag: string; }; -// Warning: (ae-missing-release-tag) "UrlPreparer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class UrlPreparer implements PreparerBase { constructor(reader: UrlReader, logger: Logger); @@ -240,15 +172,6 @@ export class UrlPreparer implements PreparerBase { } -// Warnings were encountered during analysis: -// -// src/stages/generate/types.ts:42:3 - (ae-forgotten-export) The symbol "GeneratorRunOptions" needs to be exported by the entry point index.d.ts -// src/stages/generate/types.ts:54:3 - (ae-forgotten-export) The symbol "SupportedGeneratorKey" needs to be exported by the entry point index.d.ts -// src/stages/prepare/types.ts:35:6 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// src/stages/prepare/types.ts:36:6 - (tsdoc-param-tag-with-invalid-name) The @param block should be followed by a valid parameter name: The identifier cannot non-word characters -// src/stages/prepare/types.ts:38:31 - (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag -// src/stages/prepare/types.ts:38:14 - (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@" - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/test-utils-core/api-report.md b/packages/test-utils-core/api-report.md index bda058ad23..4b603b8e7b 100644 --- a/packages/test-utils-core/api-report.md +++ b/packages/test-utils-core/api-report.md @@ -7,20 +7,14 @@ import { ReactElement } from 'react'; import { RenderResult } from '@testing-library/react'; -// Warning: (ae-missing-release-tag) "AsyncLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type AsyncLogCollector = () => Promise<void>; -// Warning: (ae-missing-release-tag) "CollectedLogs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type CollectedLogs<T extends LogFuncs> = { [key in T]: string[]; }; -// Warning: (ae-missing-release-tag) "Keyboard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class Keyboard { constructor(target: any, { debug }?: { @@ -62,31 +56,18 @@ export class Keyboard { static typeDebug(target: any, input: any): Promise<void>; } -// Warning: (ae-missing-release-tag) "LogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type LogCollector = AsyncLogCollector | SyncLogCollector; -// Warning: (ae-missing-release-tag) "LogFuncs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type LogFuncs = 'log' | 'warn' | 'error'; -// Warning: (ae-missing-release-tag) "renderWithEffects" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function renderWithEffects(nodes: ReactElement): Promise<RenderResult>; -// Warning: (ae-missing-release-tag) "SyncLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type SyncLogCollector = () => void; -// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// Warning: (ae-missing-release-tag) "withLogCollector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function withLogCollector(callback: AsyncLogCollector): Promise<CollectedLogs<LogFuncs>>; diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index f62b1e6dec..dcac9b64a7 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -16,28 +16,20 @@ import { RouteRef } from '@backstage/core-api'; import { StorageApi } from '@backstage/core-api'; import { StorageValueChange } from '@backstage/core-api'; -// Warning: (ae-forgotten-export) The symbol "Breakpoint" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "mockBreakpoint" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function mockBreakpoint(initialBreakpoint?: Breakpoint): { set(breakpoint: Breakpoint): void; remove(): void; }; -// Warning: (ae-missing-release-tag) "MockErrorApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class MockErrorApi implements ErrorApi { - // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts constructor(options?: Options); // (undocumented) error$(): Observable<{ error: Error; context?: ErrorContext; }>; - // Warning: (ae-forgotten-export) The symbol "ErrorWithContext" needs to be exported by the entry point index.d.ts - // // (undocumented) getErrors(): ErrorWithContext[]; // (undocumented) @@ -46,8 +38,6 @@ export class MockErrorApi implements ErrorApi { waitForError(pattern: RegExp, timeoutMs?: number): Promise<ErrorWithContext>; } -// Warning: (ae-missing-release-tag) "MockStorageApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class MockStorageApi implements StorageApi { // (undocumented) @@ -64,15 +54,11 @@ export class MockStorageApi implements StorageApi { set<T>(key: string, data: T): Promise<void>; } -// Warning: (ae-missing-release-tag) "MockStorageBucket" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type MockStorageBucket = { [key: string]: any; }; -// Warning: (ae-missing-release-tag) "msw" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const msw: { setupDefaultHandlers: (worker: { @@ -82,14 +68,9 @@ export const msw: { }) => void; }; -// Warning: (ae-forgotten-export) The symbol "TestAppOptions" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "renderInTestApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function renderInTestApp(Component: ComponentType | ReactNode, options?: TestAppOptions): Promise<RenderResult>; -// Warning: (ae-missing-release-tag) "wrapInTestApp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function wrapInTestApp(Component: ComponentType | ReactNode, options?: TestAppOptions): ReactElement; diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index adfbcee346..93d0957f5a 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -10,19 +10,12 @@ import { PaletteOptions } from '@material-ui/core/styles/createPalette'; import { Theme } from '@material-ui/core'; import { ThemeOptions } from '@material-ui/core'; -// Warning: (ae-forgotten-export) The symbol "PaletteAdditions" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "BackstagePalette" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type BackstagePalette = Palette & PaletteAdditions; -// Warning: (ae-missing-release-tag) "BackstagePaletteOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type BackstagePaletteOptions = PaletteOptions & PaletteAdditions; -// Warning: (ae-missing-release-tag) "BackstageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface BackstageTheme extends Theme { // (undocumented) @@ -33,8 +26,6 @@ export interface BackstageTheme extends Theme { palette: BackstagePalette; } -// Warning: (ae-missing-release-tag) "BackstageThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface BackstageThemeOptions extends ThemeOptions { // (undocumented) @@ -45,43 +36,27 @@ export interface BackstageThemeOptions extends ThemeOptions { palette: BackstagePaletteOptions; } -// Warning: (ae-missing-release-tag) "colorVariants" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const colorVariants: Record<string, string[]>; -// Warning: (ae-missing-release-tag) "createTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createTheme(options: SimpleThemeOptions): BackstageTheme; -// Warning: (ae-missing-release-tag) "createThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createThemeOptions(options: SimpleThemeOptions): BackstageThemeOptions; -// Warning: (ae-missing-release-tag) "createThemeOverrides" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createThemeOverrides(theme: BackstageTheme): Overrides; -// Warning: (ae-missing-release-tag) "darkTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const darkTheme: BackstageTheme; -// Warning: (ae-missing-release-tag) "genPageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function genPageTheme(colors: string[], shape: string): PageTheme; -// Warning: (ae-missing-release-tag) "lightTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const lightTheme: BackstageTheme; -// Warning: (ae-missing-release-tag) "PageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type PageTheme = { colors: string[]; @@ -89,25 +64,17 @@ export type PageTheme = { backgroundImage: string; }; -// Warning: (ae-missing-release-tag) "pageTheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const pageTheme: Record<string, PageTheme>; -// Warning: (ae-missing-release-tag) "PageThemeSelector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type PageThemeSelector = { themeId: string; }; -// Warning: (ae-missing-release-tag) "shapes" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const shapes: Record<string, string>; -// Warning: (ae-missing-release-tag) "SimpleThemeOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export type SimpleThemeOptions = { palette: BackstagePaletteOptions; diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 4135c52701..7bbf955f9a 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -133,9 +133,9 @@ async function runApiExtraction({ }, messages: { + // Silence warnings, as these will prevent the CI build to work compilerMessageReporting: { default: { - // Silence compiler warnings, as these will prevent the CI build to work logLevel: 'none' as ExtractorLogLevel.None, // These contain absolute file paths, so can't be included in the report // addToApiReportFile: true, @@ -143,14 +143,14 @@ async function runApiExtraction({ }, extractorMessageReporting: { default: { - logLevel: 'warning' as ExtractorLogLevel.Warning, - addToApiReportFile: true, + logLevel: 'none' as ExtractorLogLevel.Warning, + // addToApiReportFile: true, }, }, tsdocMessageReporting: { default: { - logLevel: 'warning' as ExtractorLogLevel.Warning, - addToApiReportFile: true, + logLevel: 'none' as ExtractorLogLevel.Warning, + // addToApiReportFile: true, }, }, }, From 70ac6d68c25d398435d0fb0f11d8f5067556598d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Thu, 22 Apr 2021 18:24:41 +0200 Subject: [PATCH 170/262] scripts/api-extractor: some more explanations Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- scripts/api-extractor.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 7bbf955f9a..7da9fac515 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -35,7 +35,13 @@ import { MarkdownDocumenter } from '@microsoft/api-documenter/lib/documenters/Ma const tmpDir = resolvePath(__dirname, '../node_modules/.cache/api-extractor'); /** - * Yup + * All of this monkey patching below is because MUI has these bare package.json file as a method + * for making TypeScript accept imports like `@material-ui/core/Button`, and improve tree-shaking + * by declaring them side effect free. + * + * The package.json lookup logic in api-extractor really doesn't like that though, as it enforces + * that the 'name' field exists in all package.json files that it discovers. This below is just + * making sure that we ignore those file package.json files instead of crashing. */ const { PackageJsonLookup, @@ -61,6 +67,7 @@ const DOCUMENTED_PACKAGES = [ 'packages/cli-common', 'packages/config', 'packages/config-loader', + // TODO(Rugvip): Enable these once `import * as ...` and `import()` PRs have landed, #1796 & #1916. // 'packages/core', // 'packages/core-api', 'packages/dev-utils', From 215b44de9c10a9b6d8f657ad42c91a15c3f41116 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Thu, 22 Apr 2021 18:29:22 +0200 Subject: [PATCH 171/262] scripts/api-extractor: fix comment Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- scripts/api-extractor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 7da9fac515..37dc4769fd 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -247,7 +247,7 @@ async function runApiExtraction({ } function isComponentMember(member: any) { - // React components are annotated with @components, and we want to skip those + // React components are annotated with @component, and we want to skip those return Boolean(member.docComment.match(/\n\s*\**\s*@component/m)); } From 9d3fb9a30aaeb8d9901ff76047a88b0eef722790 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Mon, 26 Apr 2021 20:51:12 +0200 Subject: [PATCH 172/262] scripts/api-extractor: sync API definitions Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- packages/search-common/api-report.md | 2 ++ packages/techdocs-common/api-report.md | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/search-common/api-report.md b/packages/search-common/api-report.md index 70522f4ee4..76bd937a1c 100644 --- a/packages/search-common/api-report.md +++ b/packages/search-common/api-report.md @@ -33,6 +33,8 @@ export interface SearchQuery { pageCursor: string; // (undocumented) term: string; + // (undocumented) + types?: string[]; } // @public (undocumented) diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md index c26f62e981..a53fb9e681 100644 --- a/packages/techdocs-common/api-report.md +++ b/packages/techdocs-common/api-report.md @@ -138,6 +138,7 @@ export class Publisher { export interface PublisherBase { docsRouter(): express.Handler; fetchTechDocsMetadata(entityName: EntityName): Promise<TechDocsMetadata>; + getReadiness(): Promise<ReadinessResponse>; hasDocsBeenGenerated(entityName: Entity): Promise<boolean>; publish(request: PublishRequest): Promise<PublishResponse>; } From b74e3e1efc3739304e37435a58ea3f0f16478bfe Mon Sep 17 00:00:00 2001 From: Victor Perera <v-vperera@expediagroup.com> Date: Mon, 26 Apr 2021 18:53:11 -0500 Subject: [PATCH 173/262] Enable starred templates on scaffolder Signed-off-by: Victor Perera <v-vperera@expediagroup.com> --- .../FavouriteTemplate/FavouriteTemplate.tsx | 67 +++++++++++++++++++ .../ScaffolderPage/ScaffolderPage.tsx | 1 + .../components/TemplateCard/TemplateCard.tsx | 10 ++- 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx diff --git a/plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx b/plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx new file mode 100644 index 0000000000..99f6c21a1d --- /dev/null +++ b/plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx @@ -0,0 +1,67 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 React, { ComponentProps } from 'react'; +import { useStarredEntities } from '@backstage/plugin-catalog-react'; +import { IconButton, makeStyles, Tooltip, withStyles } from '@material-ui/core'; +import StarBorder from '@material-ui/icons/StarBorder'; +import Star from '@material-ui/icons/Star'; +import { Entity } from '@backstage/catalog-model'; + +type Props = ComponentProps<typeof IconButton> & { entity: Entity }; + +const YellowStar = withStyles({ + root: { + color: '#f3ba37', + }, +})(Star); + +const useStyles = makeStyles(theme => ({ + starButton: { + position: 'absolute', + top: theme.spacing(0.5), + right: theme.spacing(0.5), + padding: '0.25rem', + }, +})); + +export const favouriteTemplateTooltip = (isStarred: boolean) => + isStarred ? 'Remove from favorites' : 'Add to favorites'; + +export const favouriteTemplateIcon = (isStarred: boolean) => + isStarred ? <YellowStar /> : <StarBorder style={{ color: 'white' }} />; + +/** + * IconButton for showing if a current entity is starred and adding/removing it from the favourite entities + * @param props MaterialUI IconButton props extended by required `entity` prop + */ +export const FavouriteTemplate = (props: Props) => { + const classes = useStyles(); + const { toggleStarredEntity, isStarredEntity } = useStarredEntities(); + const isStarred = isStarredEntity(props.entity); + return ( + <IconButton + color="inherit" + className={classes.starButton} + {...props} + onClick={() => toggleStarredEntity(props.entity)} + > + <Tooltip title={favouriteTemplateTooltip(isStarred)}> + {favouriteTemplateIcon(isStarred)} + </Tooltip> + </IconButton> + ); +}; diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 68bf588d01..00b13853ec 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -61,6 +61,7 @@ const getTemplateCardProps = ( type: template.spec.type ?? '', description: template.metadata.description ?? '-', tags: (template.metadata?.tags as string[]) ?? [], + entityTemplate: template, }; }; diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index 2ba83fdaae..2e9cfe6470 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -28,8 +28,13 @@ import { import React from 'react'; import { generatePath } from 'react-router'; import { rootRouteRef } from '../../routes'; +import { Entity } from '@backstage/catalog-model'; +import { FavouriteTemplate } from '../FavouriteTemplate/FavouriteTemplate'; const useStyles = makeStyles({ + cardHeader: { + position: 'relative', + }, title: { backgroundImage: ({ backgroundImage }: any) => backgroundImage, }, @@ -48,6 +53,7 @@ export type TemplateCardProps = { title: string; type: string; name: string; + entityTemplate: Entity; }; export const TemplateCard = ({ @@ -56,6 +62,7 @@ export const TemplateCard = ({ title, type, name, + entityTemplate, }: TemplateCardProps) => { const backstageTheme = useTheme<BackstageTheme>(); const rootLink = useRouteRef(rootRouteRef); @@ -69,7 +76,8 @@ export const TemplateCard = ({ return ( <Card> - <CardMedia> + <CardMedia className={classes.cardHeader}> + <FavouriteTemplate entity={entityTemplate} /> <ItemCardHeader title={title} subtitle={type} From f6efa71ee7c7960bbc2b1a4b7e678f36b8076091 Mon Sep 17 00:00:00 2001 From: Victor Perera <v-vperera@expediagroup.com> Date: Mon, 26 Apr 2021 19:00:57 -0500 Subject: [PATCH 174/262] Adding Changeset Signed-off-by: Victor Perera <v-vperera@expediagroup.com> --- .changeset/long-ladybugs-promise.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/long-ladybugs-promise.md diff --git a/.changeset/long-ladybugs-promise.md b/.changeset/long-ladybugs-promise.md new file mode 100644 index 0000000000..7d683650c3 --- /dev/null +++ b/.changeset/long-ladybugs-promise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Enable starred templates on Scaffolder frontend From 111d30a8cb6fb91142d267ccc2e6eeb033915b2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Apr 2021 04:20:03 +0000 Subject: [PATCH 175/262] chore(deps-dev): bump @types/express-serve-static-core Bumps [@types/express-serve-static-core](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/express-serve-static-core) from 4.17.18 to 4.17.19. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/express-serve-static-core) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index f2c2bee93c..ce39d4425e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5875,7 +5875,16 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/express-serve-static-core@*", "@types/express-serve-static-core@4.17.18", "@types/express-serve-static-core@^4.17.5": +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.5": + version "4.17.19" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.19.tgz#00acfc1632e729acac4f1530e9e16f6dd1508a1d" + integrity sha512-DJOSHzX7pCiSElWaGR8kCprwibCB/3yW6vcT8VG3P0SJjnv19gnWG/AZMfM60Xj/YJIp/YCaDHyvzsFVeniARA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express-serve-static-core@4.17.18": version "4.17.18" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz#8371e260f40e0e1ca0c116a9afcd9426fa094c40" integrity sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA== From 4c42ecca2d106c80f358655b7e0863be463049c6 Mon Sep 17 00:00:00 2001 From: Andrew Shirley <andrew@als-bi.com> Date: Mon, 19 Apr 2021 16:31:30 +0100 Subject: [PATCH 176/262] Wrap EmptyState in a Card This prevents it overflowing onto subsequent content Signed-off-by: Andrew Shirley <andrew@als-bi.com> --- .changeset/empty-lizards-doubt.md | 5 +++ .../Cards/RecentWorkflowRunsCard.tsx | 43 ++++++++++++------- 2 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 .changeset/empty-lizards-doubt.md diff --git a/.changeset/empty-lizards-doubt.md b/.changeset/empty-lizards-doubt.md new file mode 100644 index 0000000000..cfe1e128fc --- /dev/null +++ b/.changeset/empty-lizards-doubt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-actions': patch +--- + +Wrap EmptyState in Card diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx index 1126c2a2a0..a3605abb7e 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx @@ -25,7 +25,14 @@ import { } from '@backstage/core'; import { readGitHubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; -import { Button, Link } from '@material-ui/core'; +import { + Button, + Card, + CardContent, + CardHeader, + Divider, + Link, +} from '@material-ui/core'; import React, { useEffect } from 'react'; import { generatePath, Link as RouterLink } from 'react-router-dom'; import { GITHUB_ACTIONS_ANNOTATION } from '../useProjectName'; @@ -75,20 +82,26 @@ export const RecentWorkflowRunsCard = ({ const githubHost = hostname || 'github.com'; return !runs.length ? ( - <EmptyState - missing="data" - title="No Workflow Data" - description="This component has GitHub Actions enabled, but no data was found. Have you created any Workflows? Click the button below to create a new Workflow." - action={ - <Button - variant="contained" - color="primary" - href={`https://${githubHost}/${owner}/${repo}/actions/new`} - > - Create new Workflow - </Button> - } - /> + <Card> + <CardHeader title="Recent Workflow Runs" /> + <Divider /> + <CardContent> + <EmptyState + missing="data" + title="No Workflow Data" + description="This component has GitHub Actions enabled, but no data was found. Have you created any Workflows? Click the button below to create a new Workflow." + action={ + <Button + variant="contained" + color="primary" + href={`https://${githubHost}/${owner}/${repo}/actions/new`} + > + Create new Workflow + </Button> + } + /> + </CardContent> + </Card> ) : ( <InfoCard title="Recent Workflow Runs" From 50701f32cb87d6582135c21b9f0a04dcb3650e97 Mon Sep 17 00:00:00 2001 From: Andrew Shirley <andrew@als-bi.com> Date: Mon, 26 Apr 2021 17:31:43 +0100 Subject: [PATCH 177/262] Use InfoCard not Card Signed-off-by: Andrew Shirley <andrew@als-bi.com> --- .../Cards/RecentWorkflowRunsCard.tsx | 45 +++++++------------ 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx index a3605abb7e..97428088fc 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx @@ -25,14 +25,7 @@ import { } from '@backstage/core'; import { readGitHubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; -import { - Button, - Card, - CardContent, - CardHeader, - Divider, - Link, -} from '@material-ui/core'; +import { Button, Link } from '@material-ui/core'; import React, { useEffect } from 'react'; import { generatePath, Link as RouterLink } from 'react-router-dom'; import { GITHUB_ACTIONS_ANNOTATION } from '../useProjectName'; @@ -82,26 +75,22 @@ export const RecentWorkflowRunsCard = ({ const githubHost = hostname || 'github.com'; return !runs.length ? ( - <Card> - <CardHeader title="Recent Workflow Runs" /> - <Divider /> - <CardContent> - <EmptyState - missing="data" - title="No Workflow Data" - description="This component has GitHub Actions enabled, but no data was found. Have you created any Workflows? Click the button below to create a new Workflow." - action={ - <Button - variant="contained" - color="primary" - href={`https://${githubHost}/${owner}/${repo}/actions/new`} - > - Create new Workflow - </Button> - } - /> - </CardContent> - </Card> + <InfoCard title="Recent Workflow Runs" variant={variant}> + <EmptyState + missing="data" + title="No Workflow Data" + description="This component has GitHub Actions enabled, but no data was found. Have you created any Workflows? Click the button below to create a new Workflow." + action={ + <Button + variant="contained" + color="primary" + href={`https://${githubHost}/${owner}/${repo}/actions/new`} + > + Create new Workflow + </Button> + } + /> + </InfoCard> ) : ( <InfoCard title="Recent Workflow Runs" From 16a4ffb871f1643cd1f1eef964488f2b318da046 Mon Sep 17 00:00:00 2001 From: Andrew Shirley <andrew@als-bi.com> Date: Mon, 26 Apr 2021 18:04:06 +0100 Subject: [PATCH 178/262] Eliminate EmptyState usage Signed-off-by: Andrew Shirley <andrew@als-bi.com> --- .../Cards/RecentWorkflowRunsCard.tsx | 89 +++++++++---------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx index 97428088fc..f0366e5590 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx @@ -16,21 +16,21 @@ import { Entity } from '@backstage/catalog-model'; import { configApiRef, - EmptyState, errorApiRef, InfoCard, InfoCardVariants, + Link, Table, useApi, } from '@backstage/core'; import { readGitHubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; -import { Button, Link } from '@material-ui/core'; import React, { useEffect } from 'react'; import { generatePath, Link as RouterLink } from 'react-router-dom'; import { GITHUB_ACTIONS_ANNOTATION } from '../useProjectName'; import { useWorkflowRuns } from '../useWorkflowRuns'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; +import { Typography } from '@material-ui/core'; const firstLine = (message: string): string => message.split('\n')[0]; @@ -74,56 +74,53 @@ export const RecentWorkflowRunsCard = ({ const githubHost = hostname || 'github.com'; - return !runs.length ? ( - <InfoCard title="Recent Workflow Runs" variant={variant}> - <EmptyState - missing="data" - title="No Workflow Data" - description="This component has GitHub Actions enabled, but no data was found. Have you created any Workflows? Click the button below to create a new Workflow." - action={ - <Button - variant="contained" - color="primary" - href={`https://${githubHost}/${owner}/${repo}/actions/new`} - > - Create new Workflow - </Button> - } - /> - </InfoCard> - ) : ( + return ( <InfoCard title="Recent Workflow Runs" subheader={branch ? `Branch: ${branch}` : 'All Branches'} noPadding variant={variant} > - <Table - isLoading={loading} - options={{ - search: false, - paging: false, - padding: dense ? 'dense' : 'default', - toolbar: false, - }} - columns={[ - { - title: 'Commit Message', - field: 'message', - render: data => ( - <Link - component={RouterLink} - to={generatePath('./ci-cd/:id', { id: data.id! })} - > - {firstLine(data.message)} - </Link> - ), - }, - { title: 'Branch', field: 'source.branchName' }, - { title: 'Status', field: 'status', render: WorkflowRunStatus }, - ]} - data={runs} - /> + {!runs.length ? ( + <div style={{ textAlign: 'center' }}> + <Typography variant="body1"> + This component has GitHub Actions enabled, but no workflows were + found. + </Typography> + <Typography variant="body2"> + <Link to={`https://${githubHost}/${owner}/${repo}/actions/new`}> + Create a new workflow + </Link> + </Typography> + </div> + ) : ( + <Table + isLoading={loading} + options={{ + search: false, + paging: false, + padding: dense ? 'dense' : 'default', + toolbar: false, + }} + columns={[ + { + title: 'Commit Message', + field: 'message', + render: data => ( + <Link + component={RouterLink} + to={generatePath('./ci-cd/:id', { id: data.id! })} + > + {firstLine(data.message)} + </Link> + ), + }, + { title: 'Branch', field: 'source.branchName' }, + { title: 'Status', field: 'status', render: WorkflowRunStatus }, + ]} + data={runs} + /> + )} </InfoCard> ); }; From 266e46d3c3a4f73f5c27f50c4275be254b4ed9e9 Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Tue, 27 Apr 2021 11:07:08 +0200 Subject: [PATCH 179/262] switch from map to forEach Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- plugins/search-backend-node/src/IndexBuilder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/search-backend-node/src/IndexBuilder.ts b/plugins/search-backend-node/src/IndexBuilder.ts index 768dee5b67..71d374e704 100644 --- a/plugins/search-backend-node/src/IndexBuilder.ts +++ b/plugins/search-backend-node/src/IndexBuilder.ts @@ -98,7 +98,7 @@ export class IndexBuilder { async build(): Promise<{ scheduler: Scheduler }> { const scheduler = new Scheduler({ logger: this.logger }); - Object.keys(this.collators).map(type => { + Object.keys(this.collators).forEach(type => { scheduler.addToSchedule(async () => { // Collate, Decorate, Index. const decorators: DocumentDecorator[] = ( From 4906a4c2210c38e1364bf69c882ab90df2fc7f3c Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Tue, 27 Apr 2021 11:07:55 +0200 Subject: [PATCH 180/262] rename test file to be more specific to IndexBuilder Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- .../src/{index.test.ts => IndexBuilder.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/search-backend-node/src/{index.test.ts => IndexBuilder.test.ts} (100%) diff --git a/plugins/search-backend-node/src/index.test.ts b/plugins/search-backend-node/src/IndexBuilder.test.ts similarity index 100% rename from plugins/search-backend-node/src/index.test.ts rename to plugins/search-backend-node/src/IndexBuilder.test.ts From 6c46febf6326a8a119529e2b37f2029178fa7a3e Mon Sep 17 00:00:00 2001 From: Emma Indal <emma.indahl@gmail.com> Date: Tue, 27 Apr 2021 11:08:37 +0200 Subject: [PATCH 181/262] Add tests for Scheduler Signed-off-by: Emma Indal <emma.indahl@gmail.com> --- .../search-backend-node/src/Scheduler.test.ts | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 plugins/search-backend-node/src/Scheduler.test.ts diff --git a/plugins/search-backend-node/src/Scheduler.test.ts b/plugins/search-backend-node/src/Scheduler.test.ts new file mode 100644 index 0000000000..43fdb7ea92 --- /dev/null +++ b/plugins/search-backend-node/src/Scheduler.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger } from '@backstage/backend-common'; +import { Scheduler } from './index'; + +describe('Scheduler', () => { + let testScheduler: Scheduler; + + beforeEach(() => { + const logger = getVoidLogger(); + testScheduler = new Scheduler({ + logger, + }); + }); + + describe('addToSchedule', () => { + it('should not add a task and interval to schedule, if already started', async () => { + jest.useFakeTimers(); + const mockTask1 = jest.fn(); + const mockTask2 = jest.fn(); + + // Add a task and interval to schedule + testScheduler.addToSchedule(mockTask1, 2); + + // Starts scheduling process + testScheduler.start(); + + // Throws Error if task and interval is added to a already started schedule + expect(() => testScheduler.addToSchedule(mockTask2, 2)).toThrowError(); + + jest.runOnlyPendingTimers(); + expect(mockTask1).toHaveBeenCalled(); + expect(mockTask2).not.toHaveBeenCalled(); + }); + + it('should be possible to add a task and interval to schedule, if already started, but stopped in between', async () => { + jest.useFakeTimers(); + const mockTask1 = jest.fn(); + const mockTask2 = jest.fn(); + + // Add a task and interval to schedule + testScheduler.addToSchedule(mockTask1, 2); + + // Starts scheduling process + testScheduler.start(); + + // Stop scheduling process + testScheduler.stop(); + + // Should't throw error, as it is stopped. + expect(() => + testScheduler.addToSchedule(mockTask2, 4), + ).not.toThrowError(); + + // Starts scheduling process + testScheduler.start(); + + jest.runOnlyPendingTimers(); + expect(mockTask1).toHaveBeenCalled(); + expect(mockTask2).toHaveBeenCalled(); + }); + }); +}); From 1a142ae8a42fb018e9c746f853e3d5c460dc544d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Mon, 26 Apr 2021 21:36:50 +0200 Subject: [PATCH 182/262] catalog: switch out time-based greeting for plain title Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/witty-lies-shave.md | 5 +++++ .../src/components/CatalogPage/CatalogLayout.tsx | 13 ++++--------- .../src}/utils/locales/goodAfternoon.locales.json | 0 .../src}/utils/locales/goodEvening.locales.json | 0 .../src}/utils/locales/goodMorning.locales.json | 0 .../CatalogPage => welcome/src}/utils/timeUtil.js | 0 .../src}/utils/timeUtil.test.js | 0 7 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 .changeset/witty-lies-shave.md rename plugins/{catalog/src/components/CatalogPage => welcome/src}/utils/locales/goodAfternoon.locales.json (100%) rename plugins/{catalog/src/components/CatalogPage => welcome/src}/utils/locales/goodEvening.locales.json (100%) rename plugins/{catalog/src/components/CatalogPage => welcome/src}/utils/locales/goodMorning.locales.json (100%) rename plugins/{catalog/src/components/CatalogPage => welcome/src}/utils/timeUtil.js (100%) rename plugins/{catalog/src/components/CatalogPage => welcome/src}/utils/timeUtil.test.js (100%) diff --git a/.changeset/witty-lies-shave.md b/.changeset/witty-lies-shave.md new file mode 100644 index 0000000000..4c0aeef80a --- /dev/null +++ b/.changeset/witty-lies-shave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Switch out the time-based personal greeting for a plain title on the catalog index page. diff --git a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx index 298aeacfec..c038f3f08c 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx @@ -18,29 +18,24 @@ import { configApiRef, Header, HomepageTimer, - identityApiRef, Page, useApi, } from '@backstage/core'; import React from 'react'; -import { getTimeBasedGreeting } from './utils/timeUtil'; type Props = { children?: React.ReactNode; }; const CatalogLayout = ({ children }: Props) => { - const greeting = getTimeBasedGreeting(); - const profile = useApi(identityApiRef).getProfile(); - const userId = useApi(identityApiRef).getUserId(); - const orgName = useApi(configApiRef).getOptionalString('organization.name'); + const orgName = + useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; return ( <Page themeId="home"> <Header - title={`${greeting.greeting}, ${profile.displayName || userId}!`} - subtitle={`${orgName || 'Backstage'} Service Catalog`} - tooltip={greeting.language} + title={`${orgName} Catalog`} + subtitle={`Index of software components in ${orgName}`} pageTitleOverride="Home" > <HomepageTimer /> diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json b/plugins/welcome/src/utils/locales/goodAfternoon.locales.json similarity index 100% rename from plugins/catalog/src/components/CatalogPage/utils/locales/goodAfternoon.locales.json rename to plugins/welcome/src/utils/locales/goodAfternoon.locales.json diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json b/plugins/welcome/src/utils/locales/goodEvening.locales.json similarity index 100% rename from plugins/catalog/src/components/CatalogPage/utils/locales/goodEvening.locales.json rename to plugins/welcome/src/utils/locales/goodEvening.locales.json diff --git a/plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json b/plugins/welcome/src/utils/locales/goodMorning.locales.json similarity index 100% rename from plugins/catalog/src/components/CatalogPage/utils/locales/goodMorning.locales.json rename to plugins/welcome/src/utils/locales/goodMorning.locales.json diff --git a/plugins/catalog/src/components/CatalogPage/utils/timeUtil.js b/plugins/welcome/src/utils/timeUtil.js similarity index 100% rename from plugins/catalog/src/components/CatalogPage/utils/timeUtil.js rename to plugins/welcome/src/utils/timeUtil.js diff --git a/plugins/catalog/src/components/CatalogPage/utils/timeUtil.test.js b/plugins/welcome/src/utils/timeUtil.test.js similarity index 100% rename from plugins/catalog/src/components/CatalogPage/utils/timeUtil.test.js rename to plugins/welcome/src/utils/timeUtil.test.js From 8b43d5f8a231ba58be5cbbad0467834c13e23f6d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Mon, 26 Apr 2021 21:45:51 +0200 Subject: [PATCH 183/262] catalog: remove home page clocks Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/witty-lies-shave.md | 2 +- .../src/components/CatalogPage/CatalogLayout.tsx | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.changeset/witty-lies-shave.md b/.changeset/witty-lies-shave.md index 4c0aeef80a..68fd4b1137 100644 --- a/.changeset/witty-lies-shave.md +++ b/.changeset/witty-lies-shave.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog': patch --- -Switch out the time-based personal greeting for a plain title on the catalog index page. +Switch out the time-based personal greeting for a plain title on the catalog index page, and remove the clocks for different timezones. diff --git a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx index c038f3f08c..e762efdee8 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx @@ -14,13 +14,7 @@ * limitations under the License. */ -import { - configApiRef, - Header, - HomepageTimer, - Page, - useApi, -} from '@backstage/core'; +import { configApiRef, Header, Page, useApi } from '@backstage/core'; import React from 'react'; type Props = { @@ -37,9 +31,7 @@ const CatalogLayout = ({ children }: Props) => { title={`${orgName} Catalog`} subtitle={`Index of software components in ${orgName}`} pageTitleOverride="Home" - > - <HomepageTimer /> - </Header> + /> {children} </Page> ); From f2a5ed93b68927475fbb6cb57c129f113e0d9a40 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Tue, 27 Apr 2021 12:25:28 +0200 Subject: [PATCH 184/262] catalog: tweak index page subtitle Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx index e762efdee8..a57b223afe 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx @@ -29,7 +29,7 @@ const CatalogLayout = ({ children }: Props) => { <Page themeId="home"> <Header title={`${orgName} Catalog`} - subtitle={`Index of software components in ${orgName}`} + subtitle={`Catalog of software components at ${orgName}`} pageTitleOverride="Home" /> {children} From 4bfff07eaec3b7255bc56c48acd0cf8b2210def9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Tue, 27 Apr 2021 12:27:06 +0200 Subject: [PATCH 185/262] e2e-test: update to search for new catalog index page title Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- packages/e2e-test/src/commands/run.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/e2e-test/src/commands/run.ts b/packages/e2e-test/src/commands/run.ts index c055bcd21e..ebf4e6c835 100644 --- a/packages/e2e-test/src/commands/run.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -335,7 +335,7 @@ async function testAppServe(pluginName: string, appDir: string) { try { const browser = new Browser(); - await waitForPageWithText(browser, '/', 'My Company Service Catalog'); + await waitForPageWithText(browser, '/', 'My Company Catalog'); await waitForPageWithText( browser, `/${pluginName}`, From 73f3f5d78d2388576c25b462a181fb3ddf2767c7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Tue, 27 Apr 2021 12:29:53 +0200 Subject: [PATCH 186/262] create-app: update app template to check for new catalog index page title Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/little-trees-fold.md | 5 +++++ .../default-app/packages/app/cypress/integration/app.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/little-trees-fold.md diff --git a/.changeset/little-trees-fold.md b/.changeset/little-trees-fold.md new file mode 100644 index 0000000000..4963dd5aa1 --- /dev/null +++ b/.changeset/little-trees-fold.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Updates the end to end test in the app to match the new catalog index page title. To apply this change to an existing app, update `packages/app/cypress/integration/app.js` to search for `"My Company Catalog"` instead of `"My Company Service Catalog"`. diff --git a/packages/create-app/templates/default-app/packages/app/cypress/integration/app.js b/packages/create-app/templates/default-app/packages/app/cypress/integration/app.js index efcd5b8d93..43fb2e32de 100644 --- a/packages/create-app/templates/default-app/packages/app/cypress/integration/app.js +++ b/packages/create-app/templates/default-app/packages/app/cypress/integration/app.js @@ -1,6 +1,6 @@ describe('App', () => { it('should render the catalog', () => { cy.visit('/'); - cy.contains('My Company Service Catalog'); + cy.contains('My Company Catalog'); }); }); From 6c38f5e92031b5574e20d8da28ffeedd89608177 Mon Sep 17 00:00:00 2001 From: Brian Fox <brianhfox@gmail.com> Date: Tue, 27 Apr 2021 10:55:57 +0200 Subject: [PATCH 187/262] tests(proxy-backend): align tests with default backend configuration The pathPrefix is not suffixed with `/` by default as noted at https://github.com/backstage/backstage/blob/df897a6126d1641d111b015c527cc8d40c47bd06/packages/backend-common/src/discovery/types.ts#L47 and seen in the implementation at https://github.com/backstage/backstage/blob/df897a6126d1641d111b015c527cc8d40c47bd06/packages/backend-common/src/discovery/SingleHostDiscovery.ts#L81. Currently the tests work in the opposite way - the pathPrefix is suffixed by / whereas the routes are **not** prefixed by /. This commit brings the tests in line with the default configuration prior to any further work. Signed-off-by: Brian Fox <brianhfox@gmail.com> --- .../proxy-backend/src/service/router.test.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/proxy-backend/src/service/router.test.ts b/plugins/proxy-backend/src/service/router.test.ts index 6c47043602..3a0a25f164 100644 --- a/plugins/proxy-backend/src/service/router.test.ts +++ b/plugins/proxy-backend/src/service/router.test.ts @@ -60,7 +60,7 @@ describe('buildMiddleware', () => { }); it('accepts strings', async () => { - buildMiddleware('/api/', logger, 'test', 'http://mocked'); + buildMiddleware('/proxy', logger, '/test', 'http://mocked'); expect(createProxyMiddleware).toHaveBeenCalledTimes(1); @@ -74,13 +74,13 @@ describe('buildMiddleware', () => { expect(filter('', { method: 'PATCH', headers: {} })).toBe(true); expect(filter('', { method: 'DELETE', headers: {} })).toBe(true); - expect(fullConfig.pathRewrite).toEqual({ '^/api/test/': '/' }); + expect(fullConfig.pathRewrite).toEqual({ '^/proxy/test/': '/' }); expect(fullConfig.changeOrigin).toBe(true); expect(fullConfig.logProvider!(logger)).toBe(logger); }); it('limits allowedMethods', async () => { - buildMiddleware('/api/', logger, 'test', { + buildMiddleware('/proxy', logger, '/test', { target: 'http://mocked', allowedMethods: ['GET', 'DELETE'], }); @@ -97,13 +97,13 @@ describe('buildMiddleware', () => { expect(filter('', { method: 'PATCH', headers: {} })).toBe(false); expect(filter('', { method: 'DELETE', headers: {} })).toBe(true); - expect(fullConfig.pathRewrite).toEqual({ '^/api/test/': '/' }); + expect(fullConfig.pathRewrite).toEqual({ '^/proxy/test/': '/' }); expect(fullConfig.changeOrigin).toBe(true); expect(fullConfig.logProvider!(logger)).toBe(logger); }); it('permits default headers', async () => { - buildMiddleware('/api/', logger, 'test', { + buildMiddleware('/proxy', logger, '/test', { target: 'http://mocked', }); @@ -143,7 +143,7 @@ describe('buildMiddleware', () => { }); it('permits default and configured headers', async () => { - buildMiddleware('/api/', logger, 'test', { + buildMiddleware('/proxy', logger, '/test', { target: 'http://mocked', headers: { Authorization: 'my-token', @@ -176,7 +176,7 @@ describe('buildMiddleware', () => { }); it('permits configured headers', async () => { - buildMiddleware('/api/', logger, 'test', { + buildMiddleware('/proxy', logger, '/test', { target: 'http://mocked', allowedHeaders: ['authorization', 'cookie'], }); @@ -208,7 +208,7 @@ describe('buildMiddleware', () => { }); it('responds default headers', async () => { - buildMiddleware('/api/', logger, 'test', { + buildMiddleware('/proxy', logger, '/test', { target: 'http://mocked', }); @@ -251,7 +251,7 @@ describe('buildMiddleware', () => { }); it('responds configured headers', async () => { - buildMiddleware('/api/', logger, 'test', { + buildMiddleware('/proxy', logger, '/test', { target: 'http://mocked', allowedHeaders: ['set-cookie'], }); @@ -282,10 +282,10 @@ describe('buildMiddleware', () => { it('rejects malformed target URLs', async () => { expect(() => - buildMiddleware('/api/', logger, 'test', 'backstage.io'), + buildMiddleware('/proxy', logger, '/test', 'backstage.io'), ).toThrowError(/Proxy target is not a valid URL/); expect(() => - buildMiddleware('/api/', logger, 'test', { target: 'backstage.io' }), + buildMiddleware('/proxy', logger, '/test', { target: 'backstage.io' }), ).toThrowError(/Proxy target is not a valid URL/); }); }); From cdb3426e56f49dd5dffba3c35eea383a416b1bf1 Mon Sep 17 00:00:00 2001 From: Brian Fox <brianhfox@gmail.com> Date: Tue, 27 Apr 2021 12:38:31 +0200 Subject: [PATCH 188/262] fix(proxy-backend): prefix routes with `/` if not present in config This commit ensures that the default `pathRewrite` configuration for a proxy element is more resilient to the combination of whether: - `route` is prefixed with `/` - `pathPrefix` on the plugin is suffixed with `/` (which at present it will never be - see comments). Signed-off-by: Brian Fox <brianhfox@gmail.com> --- .changeset/thick-cobras-switch.md | 5 +++ docs/plugins/proxying.md | 11 ++--- .../proxy-backend/src/service/router.test.ts | 42 ++++++++++++++++++- plugins/proxy-backend/src/service/router.ts | 16 ++++++- 4 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 .changeset/thick-cobras-switch.md diff --git a/.changeset/thick-cobras-switch.md b/.changeset/thick-cobras-switch.md new file mode 100644 index 0000000000..002c724421 --- /dev/null +++ b/.changeset/thick-cobras-switch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-proxy-backend': patch +--- + +Prefix proxy routes with `/` if not present in configuration diff --git a/docs/plugins/proxying.md b/docs/plugins/proxying.md index 50c56af7a6..3e20e37cad 100644 --- a/docs/plugins/proxying.md +++ b/docs/plugins/proxying.md @@ -36,7 +36,7 @@ Example: ```yaml # in app-config.yaml proxy: - '/simple-example': http://simple.example.com:8080 + simple-example: http://simple.example.com:8080 '/larger-example/v1': target: http://larger.example.com:8080/svc.v1 headers: @@ -46,10 +46,11 @@ proxy: ``` Each key under the proxy configuration entry is a route to match, below the -prefix that the proxy plugin is mounted on. It must start with a slash. For -example, if the backend mounts the proxy plugin as `/proxy`, the above -configuration will lead to the proxy acting on backend requests to -`/api/proxy/simple-example/...` and `/api/proxy/larger-example/v1/...`. +prefix that the proxy plugin is mounted on. If it does not start with a slash, +one will be prefixed automatically. For example, if the backend mounts the proxy +plugin as `/proxy`, the above configuration will lead to the proxy acting on +backend requests to `/api/proxy/simple-example/...` and +`/api/proxy/larger-example/v1/...`. The value inside each route is either a simple URL string, or an object on the format accepted by diff --git a/plugins/proxy-backend/src/service/router.test.ts b/plugins/proxy-backend/src/service/router.test.ts index 3a0a25f164..571de96ac4 100644 --- a/plugins/proxy-backend/src/service/router.test.ts +++ b/plugins/proxy-backend/src/service/router.test.ts @@ -59,7 +59,7 @@ describe('buildMiddleware', () => { mockCreateProxyMiddleware.mockClear(); }); - it('accepts strings', async () => { + it('accepts strings prefixed by /', async () => { buildMiddleware('/proxy', logger, '/test', 'http://mocked'); expect(createProxyMiddleware).toHaveBeenCalledTimes(1); @@ -79,6 +79,46 @@ describe('buildMiddleware', () => { expect(fullConfig.logProvider!(logger)).toBe(logger); }); + it('accepts routes not prefixed with / when path is not suffixed with /', async () => { + buildMiddleware('/proxy', logger, 'test', 'http://mocked'); + + expect(createProxyMiddleware).toHaveBeenCalledTimes(1); + + const [filter, fullConfig] = mockCreateProxyMiddleware.mock.calls[0] as [ + (pathname: string, req: Partial<http.IncomingMessage>) => boolean, + ProxyMiddlewareConfig, + ]; + expect(filter('', { method: 'GET', headers: {} })).toBe(true); + expect(filter('', { method: 'POST', headers: {} })).toBe(true); + expect(filter('', { method: 'PUT', headers: {} })).toBe(true); + expect(filter('', { method: 'PATCH', headers: {} })).toBe(true); + expect(filter('', { method: 'DELETE', headers: {} })).toBe(true); + + expect(fullConfig.pathRewrite).toEqual({ '^/proxy/test/': '/' }); + expect(fullConfig.changeOrigin).toBe(true); + expect(fullConfig.logProvider!(logger)).toBe(logger); + }); + + it('accepts routes prefixed with / when path is suffixed with /', async () => { + buildMiddleware('/proxy/', logger, '/test', 'http://mocked'); + + expect(createProxyMiddleware).toHaveBeenCalledTimes(1); + + const [filter, fullConfig] = mockCreateProxyMiddleware.mock.calls[0] as [ + (pathname: string, req: Partial<http.IncomingMessage>) => boolean, + ProxyMiddlewareConfig, + ]; + expect(filter('', { method: 'GET', headers: {} })).toBe(true); + expect(filter('', { method: 'POST', headers: {} })).toBe(true); + expect(filter('', { method: 'PUT', headers: {} })).toBe(true); + expect(filter('', { method: 'PATCH', headers: {} })).toBe(true); + expect(filter('', { method: 'DELETE', headers: {} })).toBe(true); + + expect(fullConfig.pathRewrite).toEqual({ '^/proxy/test/': '/' }); + expect(fullConfig.changeOrigin).toBe(true); + expect(fullConfig.logProvider!(logger)).toBe(logger); + }); + it('limits allowedMethods', async () => { buildMiddleware('/proxy', logger, '/test', { target: 'http://mocked', diff --git a/plugins/proxy-backend/src/service/router.ts b/plugins/proxy-backend/src/service/router.ts index 5c306de966..71ed82c23b 100644 --- a/plugins/proxy-backend/src/service/router.ts +++ b/plugins/proxy-backend/src/service/router.ts @@ -77,10 +77,24 @@ export function buildMiddleware( `Proxy target is not a valid URL: ${fullConfig.target ?? ''}`, ); } + // Default is to do a path rewrite that strips out the proxy's path prefix // and the rest of the route. if (fullConfig.pathRewrite === undefined) { - const routeWithSlash = route.endsWith('/') ? route : `${route}/`; + let routeWithSlash = route.endsWith('/') ? route : `${route}/`; + + if (!pathPrefix.endsWith('/') && !routeWithSlash.startsWith('/')) { + // Need to insert a / between pathPrefix and routeWithSlash + routeWithSlash = `/${routeWithSlash}`; + } else if (pathPrefix.endsWith('/') && routeWithSlash.startsWith('/')) { + // Never expect this to happen at this point in time as + // pathPrefix is set using `getExternalBaseUrl` which "Returns the + // external HTTP base backend URL for a given plugin, + // **without a trailing slash.**". But in case this changes in future, we + // need to drop a / on either pathPrefix or routeWithSlash + routeWithSlash = routeWithSlash.substring(1); + } + fullConfig.pathRewrite = { [`^${pathPrefix}${routeWithSlash}`]: '/', }; From 8ce7d6e8f81d621c66e069c64cfe67f4e42fed3c Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 14:16:49 +0200 Subject: [PATCH 189/262] catalog-backend: Add ConfigLocationProvider tests Co-authored-by: Ben Lambert <ben@blam.sh> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/ConfigLocationProvider.test.ts | 67 +++++++++++++++++++ .../src/next/ConfigLocationProvider.ts | 14 ++-- 2 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts b/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts new file mode 100644 index 0000000000..9aaba13c48 --- /dev/null +++ b/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts @@ -0,0 +1,67 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { ConfigLocationProvider } from './ConfigLocationProvider'; +import { EntityProviderConnection } from './types'; +import { ConfigReader } from '@backstage/config'; +import { resolvePackagePath } from '@backstage/backend-common'; +import path from 'path'; + +describe('Config Location Provider', () => { + it('should apply mutation with the correct paths in the config', async () => { + const mockConfig = new ConfigReader({ + catalog: { + locations: [ + { type: 'file', target: './lols.yaml' }, + { type: 'url', target: 'https://github.com/backstage/backstage' }, + ], + }, + }); + + const mockConnection = ({ + applyMutation: jest.fn(), + } as unknown) as EntityProviderConnection; + const locationProvider = new ConfigLocationProvider(mockConfig); + + await locationProvider.connect(mockConnection); + + expect(mockConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: path.join( + resolvePackagePath('@backstage/plugin-catalog-backend'), + './lols.yaml', + ), + type: 'file', + }, + }), + ]), + }); + expect(mockConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: 'https://github.com/backstage/backstage', + type: 'url', + }, + }), + ]), + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts index 5b93fcfd98..8a65487df1 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts @@ -34,12 +34,14 @@ export class ConfigLocationProvider implements EntityProvider { const locationConfigs = this.config.getOptionalConfigArray('catalog.locations') ?? []; - const entities = locationConfigs.map(location => - locationSpecToLocationEntity({ - type: location.getString('type'), - target: path.resolve(location.getString('target')), - }), - ); + const entities = locationConfigs.map(location => { + const type = location.getString('type'); + const target = location.getString('target'); + return locationSpecToLocationEntity({ + type, + target: type === 'file' ? path.resolve(target) : target, + }); + }); await this.connection.applyMutation({ type: 'full', From 07a7806c31847c459b3aaea8bad7d76bfe952c94 Mon Sep 17 00:00:00 2001 From: Anastasia Rodionova <argali96@gmail.com> Date: Thu, 22 Apr 2021 16:20:03 +0200 Subject: [PATCH 190/262] Filter returned fields in apis explorer Signed-off-by: Anastasia Rodionova <argali96@gmail.com> --- .changeset/kind-suns-melt.md | 5 +++++ .../components/ApiExplorerPage/ApiExplorerPage.tsx | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .changeset/kind-suns-melt.md diff --git a/.changeset/kind-suns-melt.md b/.changeset/kind-suns-melt.md new file mode 100644 index 0000000000..7cbec28fea --- /dev/null +++ b/.changeset/kind-suns-melt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Added fields filtering in get API entities to avoid the requesting of unused data diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx index 83d0bfc2ba..1ed47811ef 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx @@ -34,7 +34,19 @@ export const ApiExplorerPage = () => { const createComponentLink = useRouteRef(createComponentRouteRef); const catalogApi = useApi(catalogApiRef); const { loading, error, value: catalogResponse } = useAsync(() => { - return catalogApi.getEntities({ filter: { kind: 'API' } }); + return catalogApi.getEntities({ + filter: { kind: 'API' }, + fields: [ + 'apiVersion', + 'kind', + 'metadata', + 'relations', + 'spec.lifecycle', + 'spec.owner', + 'spec.type', + 'spec.system', + ], + }); }, [catalogApi]); return ( From 74f74ccbdbb9932cbda2a88eb81a371bbb57a26f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Tue, 27 Apr 2021 17:16:16 +0200 Subject: [PATCH 191/262] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> Co-authored-by: Fredrik Adelöw <freben@gmail.com> --- docs/features/techdocs/getting-started.md | 2 +- docs/overview/architecture-overview.md | 6 +++--- plugins/api-docs/README.md | 2 +- plugins/catalog-import/README.md | 2 +- plugins/rollbar/README.md | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index 934e91bd26..223b276d68 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -29,7 +29,7 @@ yarn add @backstage/plugin-techdocs Once the package has been installed, you need to import the plugin in your app. -In `packages/app/src/App.tsx`, import TechDocsPage and add the following to +In `packages/app/src/App.tsx`, import `TechDocsPage` and add the following to `FlatRoutes`: ```tsx diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index fab5698014..44bc1293f0 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -95,10 +95,10 @@ any route we want for the page, as long as it doesn't collide with the routes that we choose for the other plugins in the app. These components that are exported from plugins are referred to as "Plugin -Extension Components", or "Extensions Components". They are regular React +Extension Components", or "Extension Components". They are regular React components, but in addition to being able to be rendered by React, they also -contain various pieces of metadata that is used to write together the entire -app. Extensions components are created using `create*Extension` methods, which +contain various pieces of metadata that is used to wire together the entire +app. Extension components are created using `create*Extension` methods, which you can read more about in the [composability documentation](../plugins/composability.md). diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index 3d44eaaa29..dac4b6ff4d 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -33,7 +33,7 @@ To link that a component provides or consumes an API, see the [`providesApis`](h yarn add @backstage/plugin-api-docs ``` -2. Add the `ApiExplorerPage` extensions to the app: +2. Add the `ApiExplorerPage` extension to the app: ```tsx // packages/app/src/App.tsx diff --git a/plugins/catalog-import/README.md b/plugins/catalog-import/README.md index 90190e4356..5e773ad288 100644 --- a/plugins/catalog-import/README.md +++ b/plugins/catalog-import/README.md @@ -23,7 +23,7 @@ Some features are not yet available for all supported Git providers. yarn add @backstage/plugin-catalog-import ``` -2. Add the `CatalogImportPage` extensions to the app: +2. Add the `CatalogImportPage` extension to the app: ```tsx // packages/app/src/App.tsx diff --git a/plugins/rollbar/README.md b/plugins/rollbar/README.md index 584bd7d6bc..3a33fe223c 100644 --- a/plugins/rollbar/README.md +++ b/plugins/rollbar/README.md @@ -30,7 +30,7 @@ const serviceEntityPage = ( ); ``` -4. Setup the `app.config.yaml` and account token environment variable +4. Setup the `app-config.yaml` and account token environment variable ```yaml # app.config.yaml From 6b580d979b4d5aed9f9b167436c8b3a448af58b0 Mon Sep 17 00:00:00 2001 From: jrusso1020 <jrusso@brex.com> Date: Tue, 27 Apr 2021 09:16:41 -0600 Subject: [PATCH 192/262] addres feedback Signed-off-by: jrusso1020 <jrusso@brex.com> --- docs/features/software-catalog/descriptor-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 2506e2e9c1..0dba11fd62 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -44,7 +44,7 @@ metadata: name: artist-web description: The place to be, for great artists labels: - backstage.io/custom: ValueStuff + example.com/custom: custom_label_value annotations: example.com/service-discovery: artistweb circleci.com/project-slug: github/example-org/artist-website From d6ead26753337e84150e4aa7dececfbd4abbd086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Fri, 23 Apr 2021 16:50:06 +0200 Subject: [PATCH 193/262] Update the Bitrise plugin README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/bitrise/README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/bitrise/README.md b/plugins/bitrise/README.md index ae3917d78a..411db3198e 100644 --- a/plugins/bitrise/README.md +++ b/plugins/bitrise/README.md @@ -8,30 +8,30 @@ Welcome to the Bitrise plugin! ## Installation ```sh +# The plugin must be added in the app package +$ cd packages/app $ yarn add @backstage/plugin-bitrise ``` -Bitrise Plugin exposes an "Entity Tab Content" component `EntityBitriseContent`. You can include it in the [`EntityPage.tsx`](https://github.com/backstage/backstage/blob/master/packages/app/src/components/catalog/EntityPage.tsx)`: +Bitrise Plugin exposes an entity tab component named `EntityBitriseContent`. You can include it in the +[`EntityPage.tsx`](https://github.com/backstage/backstage/blob/master/packages/app/src/components/catalog/EntityPage.tsx)`: ```tsx // At the top imports import { EntityBitriseContent } from '@backstage/plugin-bitrise'; -// Inside `WebsiteEntityPage` component -<EntityPageLayout.Content - path="/bitrise" - title="Bitrise" - element={ - <Grid container spacing={3}> - <Grid item xs={12}> - <EntityBitrisePage /> - </Grid> - </Grid> - } -/>; +// Farther down at the website declaration +const websiteEntityPage = ( + <EntityLayoutWrapper> + {/* Place the following section where you want the tab to appear */} + <EntityLayout.Route path="/bitrise" title="Bitrise"> + <EntityBitriseContent /> + </EntityLayout.Route> ``` -Now your plugin should be visible in the entity page, however in a state with a missing `bitrise.io/app` annotation. +Now your plugin should be visible as a tab at the top of the entity pages, +specifically for components that are of the type `website`. +However, it warns of a missing `bitrise.io/app` annotation. Add the annotation to your component [catalog-info.yaml](https://github.com/backstage/backstage/blob/master/catalog-info.yaml) as shown in the highlighted example below: From e5d4cd4dc8b4db1fa48ec059341c14c112e76c96 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Tue, 27 Apr 2021 17:30:34 +0200 Subject: [PATCH 194/262] docs: prettier Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- docs/overview/architecture-overview.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index 44bc1293f0..316f066614 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -97,9 +97,9 @@ that we choose for the other plugins in the app. These components that are exported from plugins are referred to as "Plugin Extension Components", or "Extension Components". They are regular React components, but in addition to being able to be rendered by React, they also -contain various pieces of metadata that is used to wire together the entire -app. Extension components are created using `create*Extension` methods, which -you can read more about in the +contain various pieces of metadata that is used to wire together the entire app. +Extension components are created using `create*Extension` methods, which you can +read more about in the [composability documentation](../plugins/composability.md). As of this moment, there is no config based install procedure for plugins. Some From 826bcc46b6afebaa915d5d0da0df2803d031e2a3 Mon Sep 17 00:00:00 2001 From: Victor Perera <v-vperera@expediagroup.com> Date: Tue, 27 Apr 2021 10:36:14 -0500 Subject: [PATCH 195/262] Issues/sugestions fixed Signed-off-by: Victor Perera victorcito001@hotmail.com Signed-off-by: Victor Perera <v-vperera@expediagroup.com> --- .../FavouriteTemplate/FavouriteTemplate.tsx | 15 ++++-- .../ScaffolderPage/ScaffolderPage.tsx | 18 +------ .../components/TemplateCard/TemplateCard.tsx | 50 ++++++++++++------- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx b/plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx index 99f6c21a1d..ae6057beff 100644 --- a/plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx +++ b/plugins/scaffolder/src/components/FavouriteTemplate/FavouriteTemplate.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { ComponentProps } from 'react'; +import React, { ComponentProps, useMemo } from 'react'; import { useStarredEntities } from '@backstage/plugin-catalog-react'; import { IconButton, makeStyles, Tooltip, withStyles } from '@material-ui/core'; import StarBorder from '@material-ui/icons/StarBorder'; @@ -29,6 +29,12 @@ const YellowStar = withStyles({ }, })(Star); +const WhiteBorderStar = withStyles({ + root: { + color: '#ffffff', + }, +})(StarBorder); + const useStyles = makeStyles(theme => ({ starButton: { position: 'absolute', @@ -42,7 +48,7 @@ export const favouriteTemplateTooltip = (isStarred: boolean) => isStarred ? 'Remove from favorites' : 'Add to favorites'; export const favouriteTemplateIcon = (isStarred: boolean) => - isStarred ? <YellowStar /> : <StarBorder style={{ color: 'white' }} />; + isStarred ? <YellowStar /> : <WhiteBorderStar />; /** * IconButton for showing if a current entity is starred and adding/removing it from the favourite entities @@ -51,7 +57,10 @@ export const favouriteTemplateIcon = (isStarred: boolean) => export const FavouriteTemplate = (props: Props) => { const classes = useStyles(); const { toggleStarredEntity, isStarredEntity } = useStarredEntities(); - const isStarred = isStarredEntity(props.entity); + const isStarred = useMemo(() => isStarredEntity(props.entity), [ + isStarredEntity, + props.entity, + ]); return ( <IconButton color="inherit" diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 00b13853ec..4a482402f8 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -39,7 +39,7 @@ import { ResultsFilter } from '../ResultsFilter/ResultsFilter'; import { ScaffolderFilter } from '../ScaffolderFilter'; import { ButtonGroup } from '../ScaffolderFilter/ScaffolderFilter'; import SearchToolbar from '../SearchToolbar/SearchToolbar'; -import { TemplateCard, TemplateCardProps } from '../TemplateCard'; +import { TemplateCard } from '../TemplateCard'; import { registerComponentRouteRef } from '../../routes'; const useStyles = makeStyles(theme => ({ @@ -51,20 +51,6 @@ const useStyles = makeStyles(theme => ({ }, })); -const getTemplateCardProps = ( - template: TemplateEntityV1alpha1, -): TemplateCardProps & { key: string } => { - return { - key: template.metadata.uid!, - name: template.metadata.name, - title: `${(template.metadata.title || template.metadata.name) ?? ''}`, - type: template.spec.type ?? '', - description: template.metadata.description ?? '-', - tags: (template.metadata?.tags as string[]) ?? [], - entityTemplate: template, - }; -}; - export const ScaffolderPageContents = () => { const styles = useStyles(); const { @@ -189,7 +175,7 @@ export const ScaffolderPageContents = () => { {matchingEntities && matchingEntities?.length > 0 && matchingEntities.map(template => ( - <TemplateCard {...getTemplateCardProps(template)} /> + <TemplateCard template={template} /> ))} </ItemCardGrid> </div> diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index 2e9cfe6470..8c64d981ad 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -28,7 +28,7 @@ import { import React from 'react'; import { generatePath } from 'react-router'; import { rootRouteRef } from '../../routes'; -import { Entity } from '@backstage/catalog-model'; +import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { FavouriteTemplate } from '../FavouriteTemplate/FavouriteTemplate'; const useStyles = makeStyles({ @@ -48,52 +48,66 @@ const useStyles = makeStyles({ }); export type TemplateCardProps = { + template: TemplateEntityV1alpha1; +}; + +type TemplateProps = { description: string; tags: string[]; title: string; type: string; name: string; - entityTemplate: Entity; }; -export const TemplateCard = ({ - description, - tags, - title, - type, - name, - entityTemplate, -}: TemplateCardProps) => { +const getTemplateCardProps = ( + template: TemplateEntityV1alpha1, +): TemplateProps & { key: string } => { + return { + key: template.metadata.uid!, + name: template.metadata.name, + title: `${(template.metadata.title || template.metadata.name) ?? ''}`, + type: template.spec.type ?? '', + description: template.metadata.description ?? '-', + tags: (template.metadata?.tags as string[]) ?? [], + }; +}; + +export const TemplateCard = ({ template }: TemplateCardProps) => { const backstageTheme = useTheme<BackstageTheme>(); const rootLink = useRouteRef(rootRouteRef); + const templateProps = getTemplateCardProps(template); - const themeId = pageTheme[type] ? type : 'other'; + const themeId = pageTheme[templateProps.type] ? templateProps.type : 'other'; const theme = backstageTheme.getPageTheme({ themeId }); const classes = useStyles({ backgroundImage: theme.backgroundImage }); const href = generatePath(`${rootLink()}/templates/:templateName`, { - templateName: name, + templateName: templateProps.name, }); return ( <Card> <CardMedia className={classes.cardHeader}> - <FavouriteTemplate entity={entityTemplate} /> + <FavouriteTemplate entity={template} /> <ItemCardHeader - title={title} - subtitle={type} + title={templateProps.title} + subtitle={templateProps.type} classes={{ root: classes.title }} /> </CardMedia> <CardContent> <Box> - {tags?.map(tag => ( + {templateProps.tags?.map(tag => ( <Chip size="small" label={tag} key={tag} /> ))} </Box> - <Box className={classes.description}>{description}</Box> + <Box className={classes.description}>{templateProps.description}</Box> </CardContent> <CardActions> - <Button color="primary" to={href} aria-label={`Choose ${title} `}> + <Button + color="primary" + to={href} + aria-label={`Choose ${templateProps.title} `} + > Choose </Button> </CardActions> From 512889f3ca11f266786b0344900ef71ee432e4b9 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 18:28:55 +0200 Subject: [PATCH 196/262] WIP tests for DefaultProcessingDatabase Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../DefaultProcessingDatabase.test.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index f67b8603db..a5c1e56cff 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -429,4 +429,66 @@ describe('Default Processing Database', () => { ).toBeFalsy(); }); }); + + describe('updateProcessedEntity', () => { + it('should throw if the entity does not exist', async () => { + await processingDatabase.transaction(async tx => { + await expect( + processingDatabase.updateProcessedEntity(tx, { + id: '9', + processedEntity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + deferredEntities: [], + relations: [], + }), + ).rejects.toThrow('Processing state not found for 9'); + }); + }); + + it('should update a processed entity', async () => { + await db<DbRefreshStateRow>('refresh_state').insert({ + entity_id: '123', + entity_ref: 'Component:default/wacka', + unprocessed_entity: '', + errors: '', + next_update_at: 'now()', + last_discovery_at: 'now()', + }); + + const deferredEntity = { + apiVersion: '1.0.0', + metadata: { + name: 'deferred', + }, + kind: 'Location', + } as Entity; + + await processingDatabase.transaction(async tx => { + await processingDatabase.updateProcessedEntity(tx, { + id: '123', + processedEntity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + deferredEntities: [deferredEntity], + relations: [], + }); + }); + + console.log( + await db<DbRefreshStateRow>('refresh_state') + .where({ entity_ref: 'deferred' }) + .select(), + ); + expect(1).toBeDefined(); + }); + }); }); From 412f96edc10bccc1ccf0716f63dca1bc0dcd244b Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 18:30:00 +0200 Subject: [PATCH 197/262] Combine stitiching queries Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/src/next/Stitcher.ts | 118 ++++++++++++++----- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index 57f5ae9167..04a8ab8cfc 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -26,6 +26,14 @@ import { import { Entity, parseEntityRef } from '@backstage/catalog-model'; import { createHash } from 'crypto'; import stableStringify from 'fast-json-stable-stringify'; +import { buildEntitySearch } from '../database/search'; +import { DbEntitiesSearchRow } from '../database/types'; + +// The number of items that are sent per batch to the database layer, when +// doing .batchInsert calls to knex. This needs to be low enough to not cause +// errors in the underlying engine due to exceeding query limits, but large +// enough to get the speed benefits. +const BATCH_SIZE = 50; export type DbFinalEntitiesRow = { entity_id: string; @@ -49,64 +57,114 @@ export class Stitcher { for (const entityRef of entityRefs) { await this.transaction(async txOpaque => { const tx = txOpaque as Knex.Transaction; - const [result] = await tx<DbRefreshStateRow>('refresh_state') - .select('entity_id', 'processed_entity') - .where({ entity_ref: entityRef }); - if (!result) { + const result: Array<{ + entityId: string; + processedEntity?: string; + errors: string; + incomingReferenceCount: string | number; + previousEtag?: string; + relationType?: string; + relationTarget?: string; + }> = await tx + .with('incoming_references', function incomingReferences(builder) { + return builder + .from('refresh_state_references') + .where({ target_entity_ref: entityRef }) + .count({ count: '*' }); + }) + .select({ + entityId: 'refresh_state.entity_id', + processedEntity: 'refresh_state.processed_entity', + errors: 'refresh_state.errors', + incomingReferenceCount: 'incoming_references.count', + previousEtag: 'final_entities.etag', + relationType: 'relations.type', + relationTarget: 'relations.target_entity_ref', + }) + .from('refresh_state') + .leftJoin('incoming_references', {}) + .leftOuterJoin('final_entities', { + 'final_entities.entity_id': 'refresh_state.entity_id', + }) + .leftOuterJoin('relations', { + 'relations.source_entity_ref': 'refresh_state.entity_ref', + }) + .where({ 'refresh_state.entity_ref': entityRef }); + + if (!result.length) { this.logger.debug( `Unable to stitch ${entityRef}, item does not exist in refresh state table`, ); return; - } else if (!result.processed_entity) { + } + + const { + entityId, + processedEntity, + errors, + incomingReferenceCount, + previousEtag, + } = result[0]; + + if (!processedEntity) { this.logger.debug( `Unable to stitch ${entityRef}, the entity has not yet been processed`, ); return; } - const entity: Entity = JSON.parse(result.processed_entity); + const entity = JSON.parse(processedEntity) as Entity; + const isOrphan = Number(incomingReferenceCount) === 0; - const entityId = entity?.metadata?.uid; - if (!entityId) { - this.logger.error(`missing ID in entity ${JSON.stringify(entity)}`); - return; - } - - const [reference_count_result] = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .where({ target_entity_ref: entityRef }) - .count({ reference_count: 'target_entity_ref' }); - - if (Number(reference_count_result.reference_count) === 0) { - this.logger.debug(`${entityRef} is orphan`); + if (isOrphan) { + this.logger.debug(`${entityRef} is an orphan`); entity.metadata.annotations = { ...entity.metadata.annotations, ['backstage.io/orphan']: 'true', }; } - const relationResults = await tx<DbRelationsRow>('relations') - .where({ source_entity_ref: entityRef }) - .select(); - - // TODO: entityRef is lower case and should be uppercase in the final result. - entity.relations = relationResults.map(relation => ({ - type: relation.type, - target: parseEntityRef(relation.target_entity_ref), - })); + // TODO: entityRef is lower case and should be uppercase in the final result + entity.relations = result + .filter(row => row.relationType) + .map(row => ({ + type: row.relationType!, + target: parseEntityRef(row.relationTarget!), + })); entity.metadata.generation = 1; + + // If the output entity was actually not changed, just abort const etag = generateEntityEtag(entity); + if (etag === previousEtag) { + console.log(`Skipped stitching of ${entityRef}, no changes`); + return; + } + entity.metadata.etag = etag; + await tx<DbFinalEntitiesRow>('final_entities') .insert({ - finalized_entity: JSON.stringify(entity), entity_id: entityId, + finalized_entity: JSON.stringify(entity), etag, }) .onConflict('entity_id') .merge(['finalized_entity', 'etag']); + + try { + const entries = buildEntitySearch(entityId, entity); + await tx<DbEntitiesSearchRow>('search') + .where({ entity_id: entityId }) + .delete(); + await tx.batchInsert('search', entries, BATCH_SIZE); + } catch (e) { + this.logger.debug( + `Failed to write search entries for ${entityId}`, + e, + ); + // intentionally ignored + } }); } } From 20346793a20e32299e88858c636985cd4836236d Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 18:30:22 +0200 Subject: [PATCH 198/262] Create search table Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../20210302150147_refresh_state.js | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 2afeda02c0..755a645894 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -154,6 +154,28 @@ exports.up = async function up(knex) { table.index('source_entity_ref', 'relations_source_entity_ref_idx'); table.index('originating_entity_id', 'relations_source_entity_id_idx'); }); + + await knex.schema.createTable('search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('entity_id') + .inTable('refresh_state') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + table.index(['key'], 'search_key_idx'); + table.index(['value'], 'search_value_idx'); + }); }; /** @@ -177,6 +199,12 @@ exports.down = async function down(knex) { table.index('source_entity_ref', 'relations_source_entity_ref_idx'); table.index('originating_entity_id', 'relations_source_entity_id_idx'); }); + await knex.schema.alterTable('search', table => { + table.dropIndex([], 'search_key_idx'); + table.dropIndex([], 'search_value_idx'); + }); + + await knex.schema.dropTable('search'); await knex.schema.dropTable('final_entities'); await knex.schema.dropTable('relations'); await knex.schema.dropTable('references'); From a1783f3060bc306fd3e2261eee14491aa43c397b Mon Sep 17 00:00:00 2001 From: Tim Hansen <timbonicus@gmail.com> Date: Tue, 27 Apr 2021 11:04:07 -0600 Subject: [PATCH 199/262] Add nebula-preview Signed-off-by: Tim Hansen <timbonicus@gmail.com> --- .changeset/thin-coins-compete.md | 5 +++++ .../src/scaffolder/actions/builtin/publish/github.ts | 1 + .../src/scaffolder/stages/publish/github.ts | 1 + 3 files changed, 7 insertions(+) create mode 100644 .changeset/thin-coins-compete.md diff --git a/.changeset/thin-coins-compete.md b/.changeset/thin-coins-compete.md new file mode 100644 index 0000000000..36511ec1cb --- /dev/null +++ b/.changeset/thin-coins-compete.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Added the `nebula-preview` preview to `Octokit` for repository visibility. diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 3ae43c5763..66dfc1d655 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -149,6 +149,7 @@ export function createPublishGithubAction(options: { const client = new Octokit({ auth: token, baseUrl: integrationConfig.config.apiBaseUrl, + previews: ['nebula-preview'], }); const user = await client.users.getByUsername({ diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index d0bfc89529..829856ec0c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -72,6 +72,7 @@ export class GithubPublisher implements PublisherBase { const client = new Octokit({ auth: token, baseUrl: this.config.apiBaseUrl, + previews: ['nebula-preview'], }); const description = values.description as string; From 1a3ce09aee63fa19714f149d73b3985a960fc43c Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Tue, 27 Apr 2021 21:23:35 +0200 Subject: [PATCH 200/262] chore(tests): Added some more tests for DefaultLocationStore and fixing migration so it will run properly on PG Signed-off-by: blam <ben@blam.sh> --- .../20210302150147_refresh_state.js | 2 +- .../src/next/DefaultLocationStore.test.ts | 146 ++++++++++++++++++ .../src/next/DefaultLocationStore.ts | 26 ++-- 3 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 plugins/catalog-backend/src/next/DefaultLocationStore.test.ts diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 755a645894..bbaf4820cd 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -160,7 +160,7 @@ exports.up = async function up(knex) { 'Flattened key-values from the entities, used for quick filtering', ); table - .uuid('entity_id') + .text('entity_id') .references('entity_id') .inTable('refresh_state') .onDelete('CASCADE') diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts new file mode 100644 index 0000000000..be20179e9a --- /dev/null +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts @@ -0,0 +1,146 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { DatabaseManager } from './database/DatabaseManager'; +import { DefaultLocationStore } from './DefaultLocationStore'; +import { v4 } from 'uuid'; + +describe('Default Location Store', () => { + const createLocationStore = async () => { + const db = await DatabaseManager.createTestDatabase(); + const connection = { applyMutation: jest.fn() }; + const store = new DefaultLocationStore(db); + await store.connect(connection); + return { store, connection }; + }; + + it('should do a full sync with the locations on connect', async () => { + const { connection } = await createLocationStore(); + + expect(connection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [], + }); + }); + + describe('listLocations', () => { + it('lists empty locations when there is no locations', async () => { + const { store } = await createLocationStore(); + + expect(await store.listLocations()).toEqual([]); + }); + + it('lists locations that are added to the db', async () => { + const { store } = await createLocationStore(); + + await store.createLocation({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }); + + const listLocations = await store.listLocations(); + + expect(listLocations).toHaveLength(1); + expect(listLocations).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }), + ]), + ); + }); + }); + + describe('createLocation', () => { + it('throws when the location already exists', async () => { + const { store } = await createLocationStore(); + const spec = { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }; + await store.createLocation(spec); + + await expect(() => store.createLocation(spec)).rejects.toThrow( + new RegExp(`Location ${spec.type}:${spec.target} already exists`), + ); + }); + + it('calls apply mutation when adding a new location', async () => { + const { store, connection } = await createLocationStore(); + + await store.createLocation({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }); + + expect(connection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + removed: [], + added: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }, + }), + ]), + }); + }); + }); + + describe('deleteLocation', () => { + it('throws if the location does not exist', async () => { + const { store } = await createLocationStore(); + + const id = v4(); + + await expect(() => store.deleteLocation(id)).rejects.toThrow( + new RegExp(`Found no location with ID ${id}`), + ); + }); + + it('calls apply mutation when adding a new location', async () => { + const { store, connection } = await createLocationStore(); + + const location = await store.createLocation({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }); + + await store.deleteLocation(location.id); + + expect(connection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [], + removed: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }, + }), + ]), + }); + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index a56e5d1585..28db3790b6 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -34,10 +34,8 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { return 'DefaultLocationStore'; } - createLocation(spec: LocationSpec): Promise<Location> { + async createLocation(spec: LocationSpec): Promise<Location> { return this.db.transaction(async tx => { - // TODO: id should really be type and target combined and not a uuid. - // Attempt to find a previous location matching the spec const previousLocations = await this.listLocations(); const previousLocation = previousLocations.some( @@ -50,6 +48,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { ); } + // TODO: id should really be type and target combined and not a uuid. const location = await this.db.addLocation(tx, { id: uuidv4(), type: spec.type, @@ -68,11 +67,17 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { async listLocations(): Promise<Location[]> { const dbLocations = await this.db.locations(); - return dbLocations.map(item => ({ - id: item.id, - target: item.target, - type: item.type, - })); + return ( + dbLocations + // TODO(blam): We should create a mutation to remove this location for everyone + // eventually when it's all done and dusted + .filter(({ type }) => type !== 'bootstrap') + .map(item => ({ + id: item.id, + target: item.target, + type: item.type, + })) + ); } getLocation(id: string): Promise<Location> { @@ -86,9 +91,6 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { return this.db.transaction(async tx => { const location = await this.db.location(id); - if (!location) { - throw new ConflictError(`No location found with id: ${id}`); - } await this.db.removeLocation(tx, id); await this.connection.applyMutation({ type: 'delta', @@ -108,7 +110,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { async connect(connection: EntityProviderConnection): Promise<void> { this._connection = connection; - const locations = await this.db.locations(); + const locations = await this.listLocations(); const entities = locations.map(location => { return locationSpecToLocationEntity(location); }); From 0aff8985d1fd437cd26ded862912e3cdfce61f56 Mon Sep 17 00:00:00 2001 From: azhurbilo <artemzhurbilo@gmail.com> Date: Thu, 22 Apr 2021 21:31:42 +0300 Subject: [PATCH 201/262] ability to disable postgres CA mount Signed-off-by: azhurbilo <artemzhurbilo@gmail.com> --- contrib/chart/backstage/README.md | 10 ++++++++++ contrib/chart/backstage/templates/_helpers.tpl | 2 +- .../backstage/templates/backend-deployment.yaml | 4 ++-- .../templates/lighthouse-deployment.yaml | 4 ++++ .../postgresql-password-backend-secret.yaml | 15 --------------- contrib/chart/backstage/values.yaml | 2 ++ 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/contrib/chart/backstage/README.md b/contrib/chart/backstage/README.md index 7d04a2cf1e..40bb2666bc 100644 --- a/contrib/chart/backstage/README.md +++ b/contrib/chart/backstage/README.md @@ -129,6 +129,16 @@ For the CA, create a `configMap` named `<release name>-<chart name>-postgres-ca` kubectl create configmap my-company-backstage-postgres-ca --from-file=ca.crt" ``` +or disable CA mount + +```yaml +backend: + postgresCertMountEnabled: false + +lighthouse: + postgresCertMountEnabled: false +``` + > Where the release name contains the chart name "backstage" then only the release name will be used. Now install the helm chart: diff --git a/contrib/chart/backstage/templates/_helpers.tpl b/contrib/chart/backstage/templates/_helpers.tpl index 5d49ba6975..123d4dba5b 100644 --- a/contrib/chart/backstage/templates/_helpers.tpl +++ b/contrib/chart/backstage/templates/_helpers.tpl @@ -214,7 +214,7 @@ Postgres port for the backend {{- .Values.postgresql.service.port }} {{- else if .Values.appConfig.backend.database.connection.port -}} {{- .Values.appConfig.backend.database.connection.port }} -{{ else }} +{{- else -}} 5432 {{- end -}} {{- end -}} diff --git a/contrib/chart/backstage/templates/backend-deployment.yaml b/contrib/chart/backstage/templates/backend-deployment.yaml index 7009a22de0..4059ee3cc9 100644 --- a/contrib/chart/backstage/templates/backend-deployment.yaml +++ b/contrib/chart/backstage/templates/backend-deployment.yaml @@ -49,7 +49,7 @@ spec: name: {{ include "backend.postgresql.passwordSecret" .}} key: postgresql-password volumeMounts: - {{- if .Values.postgresql.enabled }} + {{- if .Values.backend.postgresCertMountEnabled }} - name: postgres-ca mountPath: {{ include "backstage.backend.postgresCaDir" . }} {{- end }} @@ -58,7 +58,7 @@ spec: subPath: {{ include "backstage.appConfigFilename" . }} volumes: - {{- if .Values.postgresql.enabled }} + {{- if .Values.backend.postgresCertMountEnabled }} - name: postgres-ca configMap: name: {{ include "backstage.fullname" . }}-postgres-ca diff --git a/contrib/chart/backstage/templates/lighthouse-deployment.yaml b/contrib/chart/backstage/templates/lighthouse-deployment.yaml index 6104d4e73c..849c48d7a6 100644 --- a/contrib/chart/backstage/templates/lighthouse-deployment.yaml +++ b/contrib/chart/backstage/templates/lighthouse-deployment.yaml @@ -51,14 +51,18 @@ spec: name: {{ include "lighthouse.postgresql.passwordSecret" . }} key: postgresql-password + {{- if .Values.lighthouse.postgresCertMountEnabled }} volumeMounts: - name: postgres-ca mountPath: {{ include "backstage.lighthouse.postgresCaDir" . }} + {{- end }} + {{- if .Values.lighthouse.postgresCertMountEnabled }} volumes: - name: postgres-ca configMap: name: {{ include "backstage.fullname" . }}-postgres-ca + {{- end }} {{- if .Values.global.nodeSelector }} nodeSelector: {{- toYaml .Values.global.nodeSelector | nindent 8 }} diff --git a/contrib/chart/backstage/templates/postgresql-password-backend-secret.yaml b/contrib/chart/backstage/templates/postgresql-password-backend-secret.yaml index e53369adb9..a71cef7b21 100644 --- a/contrib/chart/backstage/templates/postgresql-password-backend-secret.yaml +++ b/contrib/chart/backstage/templates/postgresql-password-backend-secret.yaml @@ -13,18 +13,3 @@ metadata: data: postgresql-password: {{ .Values.appConfig.backend.database.connection.password | b64enc }} {{- end }} -{{- if not .Values.postgresql.enabled }} ---- -apiVersion: v1 -kind: Secret -type: Opaque -metadata: - name: {{ include "lighthouse.postgresql.passwordSecret" . }} - labels: - release: {{ .Release.Name }} - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/hook-delete-policy": "before-hook-creation" -data: - postgresql-password: {{ .Values.lighthouse.database.connection.password | b64enc }} -{{- end }} diff --git a/contrib/chart/backstage/values.yaml b/contrib/chart/backstage/values.yaml index e21148b04b..645de91313 100644 --- a/contrib/chart/backstage/values.yaml +++ b/contrib/chart/backstage/values.yaml @@ -28,6 +28,7 @@ backend: pullPolicy: IfNotPresent containerPort: 7000 serviceType: ClusterIP + postgresCertMountEnabled: true resources: requests: memory: 512Mi @@ -43,6 +44,7 @@ lighthouse: pullPolicy: IfNotPresent containerPort: 3003 serviceType: ClusterIP + postgresCertMountEnabled: true resources: requests: memory: 128Mi From 0265764749ed726e6a040593489ecb4726e0911b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Apr 2021 04:19:31 +0000 Subject: [PATCH 202/262] chore(deps): bump eslint-plugin-jest from 24.1.5 to 24.3.6 Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 24.1.5 to 24.3.6. - [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases) - [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v24.1.5...v24.3.6) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index b21e2a9bf5..230ff83c19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12518,9 +12518,9 @@ eslint-plugin-import@^2.20.2: tsconfig-paths "^3.9.0" eslint-plugin-jest@^24.1.0: - version "24.1.5" - resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.1.5.tgz#1e866a9f0deac587d0a3d5d7cefe99815a580de2" - integrity sha512-FIP3lwC8EzEG+rOs1y96cOJmMVpdFNreoDJv29B5vIupVssRi8zrSY3QadogT0K3h1Y8TMxJ6ZSAzYUmFCp2hg== + version "24.3.6" + resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.3.6.tgz#5f0ca019183c3188c5ad3af8e80b41de6c8e9173" + integrity sha512-WOVH4TIaBLIeCX576rLcOgjNXqP+jNlCiEmRgFTfQtJ52DpwnIQKAVGlGPAN7CZ33bW6eNfHD6s8ZbEUTQubJg== dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" @@ -23538,7 +23538,7 @@ semver@7.0.0: resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@~7.3.0: version "7.3.5" resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -23555,13 +23555,6 @@ semver@~5.3.0: resolved "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= -semver@~7.3.0: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - send@0.17.1: version "0.17.1" resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" From d49c94f2f7c5485da0aedff54ac2b4c5616a5795 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Apr 2021 04:22:54 +0000 Subject: [PATCH 203/262] chore(deps): bump core-js from 3.8.3 to 3.11.0 Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.8.3 to 3.11.0. - [Release notes](https://github.com/zloirock/core-js/releases) - [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/zloirock/core-js/commits/v3.11.0/packages/core-js) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index b21e2a9bf5..19aff83248 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10451,9 +10451,9 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1: integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== core-js@3, core-js@^3.0.1, core-js@^3.0.4, core-js@^3.5.0, core-js@^3.6.0, core-js@^3.6.5: - version "3.8.3" - resolved "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" - integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== + version "3.11.0" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.11.0.tgz#05dac6aa70c0a4ad842261f8957b961d36eb8926" + integrity sha512-bd79DPpx+1Ilh9+30aT5O1sgpQd4Ttg8oqkqi51ZzhedMM1omD2e6IOF48Z/DzDCZ2svp49tN/3vneTK6ZBkXw== core-js@^2.4.0, core-js@^2.5.7, core-js@^2.6.10, core-js@^2.6.5: version "2.6.11" @@ -23538,7 +23538,7 @@ semver@7.0.0: resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@~7.3.0: version "7.3.5" resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -23555,13 +23555,6 @@ semver@~5.3.0: resolved "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= -semver@~7.3.0: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - send@0.17.1: version "0.17.1" resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" From c04403f6195cfebd1e0b99e2525965d149a2a68c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Apr 2021 04:26:55 +0000 Subject: [PATCH 204/262] chore(deps): bump json-schema from 0.2.5 to 0.3.0 Bumps [json-schema](https://github.com/kriszyp/json-schema) from 0.2.5 to 0.3.0. - [Release notes](https://github.com/kriszyp/json-schema/releases) - [Commits](https://github.com/kriszyp/json-schema/compare/v0.2.5...v0.3.0) Signed-off-by: dependabot[bot] <support@github.com> --- packages/catalog-model/package.json | 2 +- packages/cli/package.json | 2 +- packages/config-loader/package.json | 2 +- plugins/scaffolder/package.json | 2 +- yarn.lock | 17 +++++------------ 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 64550b35d1..941877aec5 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -33,7 +33,7 @@ "@types/json-schema": "^7.0.5", "@types/yup": "^0.29.8", "ajv": "^7.0.3", - "json-schema": "^0.2.5", + "json-schema": "^0.3.0", "lodash": "^4.17.15", "uuid": "^8.0.0", "yup": "^0.29.3" diff --git a/packages/cli/package.json b/packages/cli/package.json index cd61193efe..1110efefe6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -82,7 +82,7 @@ "inquirer": "^7.0.4", "jest": "^26.0.1", "jest-css-modules": "^2.1.0", - "json-schema": "^0.2.5", + "json-schema": "^0.3.0", "lodash": "^4.17.19", "mini-css-extract-plugin": "^0.9.0", "ora": "^5.3.0", diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 0a0a76c2d6..55d86314af 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -35,7 +35,7 @@ "@types/json-schema": "^7.0.6", "ajv": "^7.0.3", "fs-extra": "^9.0.0", - "json-schema": "^0.2.5", + "json-schema": "^0.3.0", "json-schema-merge-allof": "^0.7.0", "typescript-json-schema": "^0.49.0", "yaml": "^1.9.2", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 2b4feecb7b..8af5339a0f 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -44,7 +44,7 @@ "@rjsf/core": "^2.4.0", "@rjsf/material-ui": "^2.4.0", "classnames": "^2.2.6", - "json-schema": "^0.2.5", + "json-schema": "^0.3.0", "git-url-parse": "^11.4.4", "humanize-duration": "^3.25.1", "immer": "^9.0.1", diff --git a/yarn.lock b/yarn.lock index b21e2a9bf5..6076e21713 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16965,10 +16965,10 @@ json-schema@0.2.3: resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= -json-schema@^0.2.5: - version "0.2.5" - resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.5.tgz#97997f50972dd0500214e208c407efa4b5d7063b" - integrity sha512-gWJOWYFrhQ8j7pVm0EM8Slr+EPVq1Phf6lvzvD/WCeqkrx/f2xBI0xOsRRS9xCn3I4vKtP519dvs3TP09r24wQ== +json-schema@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.3.0.tgz#90a9c5054bd065422c00241851ce8d59475b701b" + integrity sha512-TYfxx36xfl52Rf1LU9HyWSLGPdYLL+SQ8/E/0yVyKG8wCCDaSrhPap0vEdlsZWRaS6tnKKLPGiEJGiREVC8kxQ== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" @@ -23538,7 +23538,7 @@ semver@7.0.0: resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@~7.3.0: version "7.3.5" resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -23555,13 +23555,6 @@ semver@~5.3.0: resolved "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= -semver@~7.3.0: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - send@0.17.1: version "0.17.1" resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" From da546ce005ab90240a0fec4c2969826e7cfb1d38 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Wed, 28 Apr 2021 09:12:15 +0200 Subject: [PATCH 205/262] Support `gridItem` variant for `EntityLinksCard` This makes it similar to other cards. Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/small-snakes-shake.md | 5 +++++ .../src/components/EntityLinksCard/EntityLinksCard.tsx | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .changeset/small-snakes-shake.md diff --git a/.changeset/small-snakes-shake.md b/.changeset/small-snakes-shake.md new file mode 100644 index 0000000000..6db9db3754 --- /dev/null +++ b/.changeset/small-snakes-shake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Support `gridItem` variant for `EntityLinksCard`. diff --git a/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx b/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx index f7e558e285..59de0a4587 100644 --- a/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx +++ b/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx @@ -27,9 +27,10 @@ type Props = { /** @deprecated The entity is now grabbed from context instead */ entity?: Entity; cols?: ColumnBreakpoints | number; + variant?: 'gridItem'; }; -export const EntityLinksCard = ({ cols = undefined }: Props) => { +export const EntityLinksCard = ({ cols = undefined, variant }: Props) => { const { entity } = useEntity(); const app = useApp(); @@ -39,7 +40,7 @@ export const EntityLinksCard = ({ cols = undefined }: Props) => { const links = entity?.metadata?.links; return ( - <InfoCard title="Links"> + <InfoCard title="Links" variant={variant}> {!links || links.length === 0 ? ( <EntityLinksEmptyState /> ) : ( From f7167e9aacd2ec721c1998896f12694c1f7b8917 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Wed, 28 Apr 2021 09:18:35 +0200 Subject: [PATCH 206/262] Update processed entity tests Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../DefaultProcessingDatabase.test.ts | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index a5c1e56cff..d76bd74260 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -19,10 +19,11 @@ import { Knex } from 'knex'; import { DbRefreshStateReferencesRow, DbRefreshStateRow, + DbRelationsRow, DefaultProcessingDatabase, } from './DefaultProcessingDatabase'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, EntityRelationSpec } from '@backstage/catalog-model'; import * as uuid from 'uuid'; import { getVoidLogger } from '@backstage/backend-common'; @@ -452,8 +453,8 @@ describe('Default Processing Database', () => { it('should update a processed entity', async () => { await db<DbRefreshStateRow>('refresh_state').insert({ - entity_id: '123', - entity_ref: 'Component:default/wacka', + entity_id: '321', + entity_ref: 'location:default/new-root', unprocessed_entity: '', errors: '', next_update_at: 'now()', @@ -468,9 +469,23 @@ describe('Default Processing Database', () => { kind: 'Location', } as Entity; + const relation: EntityRelationSpec = { + source: { + kind: 'Component', + namespace: 'Default', + name: 'foo', + }, + target: { + kind: 'Component', + namespace: 'Default', + name: 'foo', + }, + type: 'url', + }; + await processingDatabase.transaction(async tx => { await processingDatabase.updateProcessedEntity(tx, { - id: '123', + id: '321', processedEntity: { apiVersion: '1.0.0', metadata: { @@ -479,16 +494,24 @@ describe('Default Processing Database', () => { kind: 'Location', } as Entity, deferredEntities: [deferredEntity], - relations: [], + relations: [relation], }); }); - console.log( - await db<DbRefreshStateRow>('refresh_state') - .where({ entity_ref: 'deferred' }) - .select(), - ); - expect(1).toBeDefined(); + const deferredResult = await db<DbRefreshStateRow>('refresh_state') + .where({ entity_ref: 'location:default/deferred' }) + .select(); + expect(deferredResult.length).toBe(1); + + const [relations] = await db<DbRelationsRow>('relations') + .where({ originating_entity_id: '321' }) + .select(); + expect(relations).toEqual({ + originating_entity_id: '321', + source_entity_ref: 'component:default/foo', + type: 'url', + target_entity_ref: 'component:default/foo', + }); }); }); }); From 17b8da50a959a0c452a457f4207328d8ae1ca98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 09:18:36 +0200 Subject: [PATCH 207/262] update the stitcher including search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../20210302150147_refresh_state.js | 7 +- .../catalog-backend/src/next/Stitcher.test.ts | 205 ++++++++++++++++++ plugins/catalog-backend/src/next/Stitcher.ts | 59 ++--- .../catalog-backend/src/next/search.test.ts | 160 ++++++++++++++ plugins/catalog-backend/src/next/search.ts | 191 ++++++++++++++++ plugins/catalog-backend/src/next/types.ts | 1 + 6 files changed, 592 insertions(+), 31 deletions(-) create mode 100644 plugins/catalog-backend/src/next/Stitcher.test.ts create mode 100644 plugins/catalog-backend/src/next/search.test.ts create mode 100644 plugins/catalog-backend/src/next/search.ts diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index bbaf4820cd..4d2c30f194 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -33,7 +33,6 @@ exports.up = async function up(knex) { ); table .text('entity_ref') - .unique() .notNullable() .comment('A reference to the entity that the refresh state is tied to'); table @@ -59,13 +58,14 @@ exports.up = async function up(knex) { .notNullable() .comment('JSON array containing all errors related to entity'); table - .dateTime('next_update_at') // TOOD: timezone or change to epoch-millis or similar + .dateTime('next_update_at') // TODO: timezone or change to epoch-millis or similar .notNullable() .comment('Timestamp of when entity should be updated'); table - .dateTime('last_discovery_at') // TOOD: timezone or change to epoch-millis or similar + .dateTime('last_discovery_at') // TODO: timezone or change to epoch-millis or similar .notNullable() .comment('The last timestamp of which this entity was discovered'); + table.unique(['entity_ref'], 'refresh_state_entity_ref_uniq'); table.index('entity_id', 'refresh_state_entity_id_idx'); table.index('entity_ref', 'refresh_state_entity_ref_idx'); table.index('next_update_at', 'refresh_state_next_update_at_idx'); @@ -188,6 +188,7 @@ exports.down = async function down(knex) { table.dropIndex([], 'refresh_state_references_target_entity_id_idx'); }); await knex.schema.alterTable('refresh_state', table => { + table.dropUnique([], 'refresh_state_entity_ref_uniq'); table.dropIndex([], 'refresh_state_entity_id_idx'); table.dropIndex([], 'refresh_state_entity_ref_idx'); table.dropIndex([], 'refresh_state_next_update_at_idx'); diff --git a/plugins/catalog-backend/src/next/Stitcher.test.ts b/plugins/catalog-backend/src/next/Stitcher.test.ts new file mode 100644 index 0000000000..327d922c07 --- /dev/null +++ b/plugins/catalog-backend/src/next/Stitcher.test.ts @@ -0,0 +1,205 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger } from '@backstage/backend-common'; +import { Knex } from 'knex'; +import { DatabaseManager } from './database/DatabaseManager'; +import { + DbRefreshStateReferencesRow, + DbRefreshStateRow, + DbRelationsRow, +} from './database/DefaultProcessingDatabase'; +import { DbSearchRow } from './search'; +import { DbFinalEntitiesRow, Stitcher } from './Stitcher'; + +describe('Stitcher', () => { + let db: Knex; + const logger = getVoidLogger(); + + beforeEach(async () => { + db = await DatabaseManager.createTestDatabaseConnection(); + await DatabaseManager.createDatabase(db); + }); + + it('runs the happy path', async () => { + const stitcher = new Stitcher(db, logger); + + await db.transaction(async tx => { + await tx<DbRefreshStateRow>('refresh_state').insert([ + { + entity_id: 'my-id', + entity_ref: 'k:ns/n', + unprocessed_entity: JSON.stringify({}), + processed_entity: JSON.stringify({ + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'n', + namespace: 'ns', + }, + spec: { + k: 'v', + }, + }), + errors: '[]', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + }, + ]); + await tx<DbRefreshStateReferencesRow>('refresh_state_references').insert([ + { source_key: 'a', target_entity_ref: 'k:ns/n' }, + ]); + await tx<DbRelationsRow>('relations').insert([ + { + originating_entity_id: 'my-id', + source_entity_ref: 'k:ns/n', + type: 'looksAt', + target_entity_ref: 'k:ns/other', + }, + ]); + }); + + await stitcher.stitch(new Set(['k:ns/n'])); + + let firstEtag: string; + await db.transaction(async tx => { + const entities = await tx<DbFinalEntitiesRow>('final_entities'); + + expect(entities.length).toBe(1); + const entity = JSON.parse(entities[0].finalized_entity); + expect(entity).toEqual({ + relations: [ + { + type: 'looksAt', + target: { + kind: 'k', + namespace: 'ns', + name: 'other', + }, + }, + ], + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'n', + namespace: 'ns', + etag: expect.any(String), + generation: 1, + uid: 'my-id', + }, + spec: { + k: 'v', + }, + }); + + firstEtag = entity.metadata.etag; + + const search = await tx<DbSearchRow>('search'); + expect(search).toEqual( + expect.arrayContaining([ + { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/other' }, + { entity_id: 'my-id', key: 'apiversion', value: 'a' }, + { entity_id: 'my-id', key: 'kind', value: 'k' }, + { entity_id: 'my-id', key: 'metadata.name', value: 'n' }, + { entity_id: 'my-id', key: 'metadata.namespace', value: 'ns' }, + { entity_id: 'my-id', key: 'metadata.uid', value: 'my-id' }, + { entity_id: 'my-id', key: 'spec.k', value: 'v' }, + ]), + ); + }); + + // Re-stitch without any changes + await stitcher.stitch(new Set(['k:ns/n'])); + + await db.transaction(async tx => { + const entities = await tx<DbFinalEntitiesRow>('final_entities'); + expect(entities.length).toBe(1); + const entity = JSON.parse(entities[0].finalized_entity); + expect(entities[0].etag).toEqual(firstEtag); + expect(entity.metadata.etag).toEqual(firstEtag); + }); + + // Now add one more relation and re-stitch + await db.transaction(async tx => { + await tx<DbRelationsRow>('relations').insert([ + { + originating_entity_id: 'my-id', + source_entity_ref: 'k:ns/n', + type: 'looksAt', + target_entity_ref: 'k:ns/third', + }, + ]); + }); + + await stitcher.stitch(new Set(['k:ns/n'])); + + await db.transaction(async tx => { + const entities = await tx<DbFinalEntitiesRow>('final_entities'); + + expect(entities.length).toBe(1); + const entity = JSON.parse(entities[0].finalized_entity); + expect(entity).toEqual({ + relations: expect.arrayContaining([ + { + type: 'looksAt', + target: { + kind: 'k', + namespace: 'ns', + name: 'other', + }, + }, + { + type: 'looksAt', + target: { + kind: 'k', + namespace: 'ns', + name: 'third', + }, + }, + ]), + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'n', + namespace: 'ns', + etag: expect.any(String), + generation: 1, + uid: 'my-id', + }, + spec: { + k: 'v', + }, + }); + + expect(entities[0].etag).not.toEqual(firstEtag); + expect(entities[0].etag).toEqual(entity.metadata.etag); + + const search = await tx<DbSearchRow>('search'); + expect(search).toEqual( + expect.arrayContaining([ + { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/other' }, + { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/third' }, + { entity_id: 'my-id', key: 'apiversion', value: 'a' }, + { entity_id: 'my-id', key: 'kind', value: 'k' }, + { entity_id: 'my-id', key: 'metadata.name', value: 'n' }, + { entity_id: 'my-id', key: 'metadata.namespace', value: 'ns' }, + { entity_id: 'my-id', key: 'metadata.uid', value: 'my-id' }, + { entity_id: 'my-id', key: 'spec.k', value: 'v' }, + ]), + ); + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index 04a8ab8cfc..cd9220e934 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -14,20 +14,14 @@ * limitations under the License. */ +import { Entity, parseEntityRef } from '@backstage/catalog-model'; +import { ConflictError } from '@backstage/errors'; +import { createHash } from 'crypto'; +import stableStringify from 'fast-json-stable-stringify'; import { Knex } from 'knex'; import { Logger } from 'winston'; import { Transaction } from '../database'; -import { ConflictError } from '@backstage/errors'; -import { - DbRefreshStateReferencesRow, - DbRefreshStateRow, - DbRelationsRow, -} from './database/DefaultProcessingDatabase'; -import { Entity, parseEntityRef } from '@backstage/catalog-model'; -import { createHash } from 'crypto'; -import stableStringify from 'fast-json-stable-stringify'; -import { buildEntitySearch } from '../database/search'; -import { DbEntitiesSearchRow } from '../database/types'; +import { buildEntitySearch, DbSearchRow } from './search'; // The number of items that are sent per batch to the database layer, when // doing .batchInsert calls to knex. This needs to be low enough to not cause @@ -58,6 +52,13 @@ export class Stitcher { await this.transaction(async txOpaque => { const tx = txOpaque as Knex.Transaction; + // Selecting from refresh_state and final_entities should yield exactly + // one row (except in abnormal cases where the stitch was invoked for + // something that didn't exist at all, in which case it's zero rows). + // The join with the temporary incoming_references still gives one row. + // The only result set "expanding" join is the one with relations, so + // the output should be at least one row (if zero or one relations were + // found), or at most the same number of rows as relations. const result: Array<{ entityId: string; processedEntity?: string; @@ -90,8 +91,14 @@ export class Stitcher { .leftOuterJoin('relations', { 'relations.source_entity_ref': 'refresh_state.entity_ref', }) - .where({ 'refresh_state.entity_ref': entityRef }); + .where({ 'refresh_state.entity_ref': entityRef }) + .orderBy('relationType', 'asc') + .orderBy('relationTarget', 'asc'); + // If there were no rows returned, it would mean that there was no + // matching row even in the refresh_state. This can happen for example + // if we emit a relation to something that hasn't been ingested yet. + // It's safe to ignore this stitch attempt in that case. if (!result.length) { this.logger.debug( `Unable to stitch ${entityRef}, item does not exist in refresh state table`, @@ -102,11 +109,15 @@ export class Stitcher { const { entityId, processedEntity, - errors, + // errors, incomingReferenceCount, previousEtag, } = result[0]; + // If there was no processed entity in place, the target hasn't been + // through the processing steps yet. It's safe to ignore this stitch + // attempt in that case, since another stitch will be triggered when + // that processing has finished. if (!processedEntity) { this.logger.debug( `Unable to stitch ${entityRef}, the entity has not yet been processed`, @@ -114,6 +125,7 @@ export class Stitcher { return; } + // Grab the processed entity and stitch all of the relevant data into it const entity = JSON.parse(processedEntity) as Entity; const isOrphan = Number(incomingReferenceCount) === 0; @@ -132,15 +144,16 @@ export class Stitcher { type: row.relationType!, target: parseEntityRef(row.relationTarget!), })); - entity.metadata.generation = 1; // If the output entity was actually not changed, just abort const etag = generateEntityEtag(entity); if (etag === previousEtag) { - console.log(`Skipped stitching of ${entityRef}, no changes`); + this.logger.debug(`Skipped stitching of ${entityRef}, no changes`); return; } + entity.metadata.uid = entityId; + entity.metadata.generation = 1; entity.metadata.etag = etag; await tx<DbFinalEntitiesRow>('final_entities') @@ -152,19 +165,9 @@ export class Stitcher { .onConflict('entity_id') .merge(['finalized_entity', 'etag']); - try { - const entries = buildEntitySearch(entityId, entity); - await tx<DbEntitiesSearchRow>('search') - .where({ entity_id: entityId }) - .delete(); - await tx.batchInsert('search', entries, BATCH_SIZE); - } catch (e) { - this.logger.debug( - `Failed to write search entries for ${entityId}`, - e, - ); - // intentionally ignored - } + const searchEntries = buildEntitySearch(entityId, entity); + await tx<DbSearchRow>('search').where({ entity_id: entityId }).delete(); + await tx.batchInsert('search', searchEntries, BATCH_SIZE); }); } } diff --git a/plugins/catalog-backend/src/next/search.test.ts b/plugins/catalog-backend/src/next/search.test.ts new file mode 100644 index 0000000000..be9a98fe69 --- /dev/null +++ b/plugins/catalog-backend/src/next/search.test.ts @@ -0,0 +1,160 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { buildEntitySearch, mapToRows, traverse } from './search'; + +describe('search', () => { + describe('traverse', () => { + it('expands lists of strings to several rows', () => { + const input = { a: ['b', 'c', 'd'] }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'a', value: 'b' }, + { key: 'a.b', value: true }, + { key: 'a', value: 'c' }, + { key: 'a.c', value: true }, + { key: 'a', value: 'd' }, + { key: 'a.d', value: true }, + ]); + }); + + it('expands objects', () => { + const input = { a: { b: { c: 'd' }, e: 'f' } }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'a.b.c', value: 'd' }, + { key: 'a.e', value: 'f' }, + ]); + }); + + it('expands list of objects', () => { + const input = { root: { list: [{ a: 1 }, { a: 2 }] } }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'root.list.a', value: 1 }, + { key: 'root.list.a', value: 2 }, + ]); + }); + + it('skips over special keys', () => { + const input = { + state: { x: 1 }, + relations: [{ y: 2 }], + a: 'a', + metadata: { + b: 'b', + name: 'name', + namespace: 'namespace', + uid: 'uid', + etag: 'etag', + generation: 'generation', + c: 'c', + }, + d: 'd', + }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'a', value: 'a' }, + { key: 'metadata.b', value: 'b' }, + { key: 'metadata.c', value: 'c' }, + { key: 'd', value: 'd' }, + ]); + }); + }); + + describe('mapToRows', () => { + it('converts base types to strings or null', () => { + const input = [ + { key: 'a', value: true }, + { key: 'b', value: false }, + { key: 'c', value: 7 }, + { key: 'd', value: 'string' }, + { key: 'e', value: null }, + { key: 'f', value: undefined }, + ]; + const output = mapToRows(input, 'eid'); + expect(output).toEqual([ + { entity_id: 'eid', key: 'a', value: 'true' }, + { entity_id: 'eid', key: 'b', value: 'false' }, + { entity_id: 'eid', key: 'c', value: '7' }, + { entity_id: 'eid', key: 'd', value: 'string' }, + { entity_id: 'eid', key: 'e', value: null }, + { entity_id: 'eid', key: 'f', value: null }, + ]); + }); + + it('emits lowercase version of keys and values', () => { + const input = [{ key: 'fOo', value: 'BaR' }]; + const output = mapToRows(input, 'eid'); + expect(output).toEqual([{ entity_id: 'eid', key: 'foo', value: 'bar' }]); + }); + + it('skips very large values', () => { + const input = [{ key: 'foo', value: 'a'.repeat(10000) }]; + const output = mapToRows(input, 'eid'); + expect(output).toEqual([]); + }); + }); + + describe('buildEntitySearch', () => { + it('adds special keys even if missing', () => { + const input: Entity = { + apiVersion: 'a', + kind: 'b', + metadata: { name: 'n' }, + }; + expect(buildEntitySearch('eid', input)).toEqual([ + { entity_id: 'eid', key: 'apiversion', value: 'a' }, + { entity_id: 'eid', key: 'kind', value: 'b' }, + { entity_id: 'eid', key: 'metadata.name', value: 'n' }, + { entity_id: 'eid', key: 'metadata.namespace', value: null }, + { entity_id: 'eid', key: 'metadata.uid', value: null }, + { + entity_id: 'eid', + key: 'metadata.namespace', + value: ENTITY_DEFAULT_NAMESPACE, + }, + ]); + }); + + it('adds relations', () => { + const input: Entity = { + relations: [ + { type: 't1', target: { kind: 'k', namespace: 'ns', name: 'a' } }, + { type: 't2', target: { kind: 'k', namespace: 'ns', name: 'b' } }, + ], + apiVersion: 'a', + kind: 'b', + metadata: { name: 'n' }, + }; + expect(buildEntitySearch('eid', input)).toEqual([ + { entity_id: 'eid', key: 'apiversion', value: 'a' }, + { entity_id: 'eid', key: 'kind', value: 'b' }, + { entity_id: 'eid', key: 'metadata.name', value: 'n' }, + { entity_id: 'eid', key: 'metadata.namespace', value: null }, + { entity_id: 'eid', key: 'metadata.uid', value: null }, + { + entity_id: 'eid', + key: 'metadata.namespace', + value: ENTITY_DEFAULT_NAMESPACE, + }, + { entity_id: 'eid', key: 'relations', value: 't1:k:ns/a' }, + { entity_id: 'eid', key: 'relations', value: 't2:k:ns/b' }, + ]); + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/search.ts b/plugins/catalog-backend/src/next/search.ts new file mode 100644 index 0000000000..4aa8bae1a8 --- /dev/null +++ b/plugins/catalog-backend/src/next/search.ts @@ -0,0 +1,191 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Entity, + ENTITY_DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; + +export type DbSearchRow = { + entity_id: string; + key: string; + value: string | null; +}; + +// These are excluded in the generic loop, either because they do not make sense +// to index, or because they are special-case always inserted whether they are +// null or not +const SPECIAL_KEYS = [ + 'state', + 'relations', + 'metadata.name', + 'metadata.namespace', + 'metadata.uid', + 'metadata.etag', + 'metadata.generation', +]; + +// The maximum length allowed for search values. These columns are indexed, and +// database engines do not like to index on massive values. For example, +// postgres will balk after 8191 byte line sizes. +const MAX_VALUE_LENGTH = 200; + +type Kv = { + key: string; + value: unknown; +}; + +// Helper for traversing through a nested structure and outputting a list of +// path->value entries of the leaves. +// +// For example, this yaml structure +// +// a: 1 +// b: +// c: null +// e: [f, g] +// h: +// - i: 1 +// j: k +// - i: 2 +// j: l +// +// will result in +// +// "a", 1 +// "b.c", null +// "b.e": "f" +// "b.e.f": true +// "b.e": "g" +// "b.e.g": true +// "h.i": 1 +// "h.j": "k" +// "h.i": 2 +// "h.j": "l" +export function traverse(root: unknown): Kv[] { + const output: Kv[] = []; + + function visit(path: string, current: unknown) { + if (SPECIAL_KEYS.includes(path)) { + return; + } + + // empty or scalar + if ( + current === undefined || + current === null || + ['string', 'number', 'boolean'].includes(typeof current) + ) { + output.push({ key: path, value: current }); + return; + } + + // unknown + if (typeof current !== 'object') { + return; + } + + // array + if (Array.isArray(current)) { + for (const item of current) { + // NOTE(freben): The reason that these are output in two different ways, + // is to support use cases where you want to express that MORE than one + // tag is present in a list. Since the EntityFilters structure is a + // record, you can't have several entries of the same key. Therefore + // you will have to match on + // + // { "a.b": ["true"], "a.c": ["true"] } + // + // rather than + // + // { "a": ["b", "c"] } + // + // because the latter means EITHER b or c has to be present. + visit(path, item); + if (typeof item === 'string') { + output.push({ key: `${path}.${item}`, value: true }); + } + } + return; + } + + // object + for (const [key, value] of Object.entries(current!)) { + visit(path ? `${path}.${key}` : key, value); + } + } + + visit('', root); + + return output; +} + +// Translates a number of raw data rows to search table rows +export function mapToRows(input: Kv[], entityId: string): DbSearchRow[] { + const result: DbSearchRow[] = []; + + for (const { key: rawKey, value: rawValue } of input) { + const key = rawKey.toLocaleLowerCase('en-US'); + if (rawValue === undefined || rawValue === null) { + result.push({ entity_id: entityId, key, value: null }); + } else { + const value = String(rawValue).toLocaleLowerCase('en-US'); + if (value.length <= MAX_VALUE_LENGTH) { + result.push({ entity_id: entityId, key, value }); + } + } + } + + return result; +} + +/** + * Generates all of the search rows that are relevant for this entity. + * + * @param entityId The uid of the entity + * @param entity The entity + * @returns A list of entity search rows + */ +export function buildEntitySearch( + entityId: string, + entity: Entity, +): DbSearchRow[] { + // Visit the base structure recursively + const raw = traverse(entity); + + // Start with some special keys that are always present because you want to + // be able to easily search for null specifically + raw.push({ key: 'metadata.name', value: entity.metadata.name }); + raw.push({ key: 'metadata.namespace', value: entity.metadata.namespace }); + raw.push({ key: 'metadata.uid', value: entity.metadata.uid }); + + // Namespace not specified has the default value "default", so we want to + // match on that as well + if (!entity.metadata.namespace) { + raw.push({ key: 'metadata.namespace', value: ENTITY_DEFAULT_NAMESPACE }); + } + + // Visit relations + for (const relation of entity.relations ?? []) { + raw.push({ + key: 'relations', + value: `${relation.type}:${stringifyEntityRef(relation.target)}`, + }); + } + + return mapToRows(raw, entityId); +} diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index e0616fb336..cc9cc48ad6 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -120,6 +120,7 @@ export type ReplaceProcessingItemsRequest = removed: Entity[]; type: 'delta'; }; + export interface ProcessingStateManager { setProcessingItemResult(result: ProcessingItemResult): Promise<void>; getNextProcessingItem(): Promise<ProcessingItem>; From bd231a3d63310049c2467fff15670f351cec3e41 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Sun, 4 Apr 2021 19:45:23 +0200 Subject: [PATCH 208/262] catalog-backend/next: add Context Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .../src/next/Context/BaseContext.ts | 26 ++++++++++++ .../src/next/Context/ContextWithValue.ts | 40 +++++++++++++++++++ .../src/next/Context/TransactionContext.ts | 40 +++++++++++++++++++ .../catalog-backend/src/next/Context/index.ts | 21 ++++++++++ .../catalog-backend/src/next/Context/types.ts | 23 +++++++++++ 5 files changed, 150 insertions(+) create mode 100644 plugins/catalog-backend/src/next/Context/BaseContext.ts create mode 100644 plugins/catalog-backend/src/next/Context/ContextWithValue.ts create mode 100644 plugins/catalog-backend/src/next/Context/TransactionContext.ts create mode 100644 plugins/catalog-backend/src/next/Context/index.ts create mode 100644 plugins/catalog-backend/src/next/Context/types.ts diff --git a/plugins/catalog-backend/src/next/Context/BaseContext.ts b/plugins/catalog-backend/src/next/Context/BaseContext.ts new file mode 100644 index 0000000000..c9553cffd5 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/BaseContext.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { Context, ContextKey } from './types'; + +/** + * A base Context implementation that does not hold any value. + */ +export class BaseContext implements Context { + getContextValue<T>(key: ContextKey<T>): T { + return key.defaultValue; + } +} diff --git a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts new file mode 100644 index 0000000000..8e61e2c6f2 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { BaseContext } from './BaseContext'; +import { Context, ContextKey } from './types'; + +/** + * A Context implementation that holds a single value, optionally extending an existing context. + */ +export class ContextWithValue implements Context { + static create(key: ContextKey<unknown>, value: unknown, parent?: Context) { + return new ContextWithValue(parent ?? new BaseContext(), key, value); + } + + private constructor( + private readonly parent: Context, + private readonly key: ContextKey<unknown>, + private readonly value: unknown, + ) {} + + getContextValue<T>(key: ContextKey<T>): T { + if (this.key === key) { + return this.value as T; + } + return this.parent.getContextValue(key); + } +} diff --git a/plugins/catalog-backend/src/next/Context/TransactionContext.ts b/plugins/catalog-backend/src/next/Context/TransactionContext.ts new file mode 100644 index 0000000000..6ac50fbc07 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/TransactionContext.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { Context, ContextKey } from './types'; +import { Knex } from 'knex'; +import { ContextWithValue } from './ContextWithValue'; + +const transactionContextKey = new ContextKey<Knex.Transaction | undefined>( + undefined, +); + +/** + * TransactionContext handles the wrapping of a knex transaction in a Context. + */ +export class TransactionContext { + static create(tx: Knex.Transaction, parent?: Context) { + return ContextWithValue.create(transactionContextKey, tx, parent); + } + + static getTransaction(context: Context): Knex.Transaction { + const transaction = context.getContextValue(transactionContextKey); + if (!transaction) { + throw new Error(`No transaction available in context`); + } + return transaction; + } +} diff --git a/plugins/catalog-backend/src/next/Context/index.ts b/plugins/catalog-backend/src/next/Context/index.ts new file mode 100644 index 0000000000..992f5e89a6 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { BaseContext } from './BaseContext'; +export { ContextWithValue } from './ContextWithValue'; +export { TransactionContext } from './TransactionContext'; +export { ContextKey } from './types'; +export type { Context } from './types'; diff --git a/plugins/catalog-backend/src/next/Context/types.ts b/plugins/catalog-backend/src/next/Context/types.ts new file mode 100644 index 0000000000..0973b83515 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/types.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class ContextKey<T> { + constructor(readonly defaultValue: T) {} +} + +export interface Context { + getContextValue<T>(key: ContextKey<T>): T; +} From 065e532aade1047d3d06a0d6a308091e63e6eb06 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 28 Apr 2021 10:30:03 +0200 Subject: [PATCH 209/262] catalog-backend: tweak Context API Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .../Context/{BaseContext.ts => BackgroundContext.ts} | 2 +- .../src/next/Context/ContextWithValue.ts | 5 ++--- .../{TransactionContext.ts => TransactionValue.ts} | 10 +++++----- plugins/catalog-backend/src/next/Context/index.ts | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) rename plugins/catalog-backend/src/next/Context/{BaseContext.ts => BackgroundContext.ts} (93%) rename plugins/catalog-backend/src/next/Context/{TransactionContext.ts => TransactionValue.ts} (77%) diff --git a/plugins/catalog-backend/src/next/Context/BaseContext.ts b/plugins/catalog-backend/src/next/Context/BackgroundContext.ts similarity index 93% rename from plugins/catalog-backend/src/next/Context/BaseContext.ts rename to plugins/catalog-backend/src/next/Context/BackgroundContext.ts index c9553cffd5..72b9a3b1ed 100644 --- a/plugins/catalog-backend/src/next/Context/BaseContext.ts +++ b/plugins/catalog-backend/src/next/Context/BackgroundContext.ts @@ -19,7 +19,7 @@ import { Context, ContextKey } from './types'; /** * A base Context implementation that does not hold any value. */ -export class BaseContext implements Context { +export class BackgroundContext implements Context { getContextValue<T>(key: ContextKey<T>): T { return key.defaultValue; } diff --git a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts index 8e61e2c6f2..e8f94fd922 100644 --- a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts +++ b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts @@ -14,15 +14,14 @@ * limitations under the License. */ -import { BaseContext } from './BaseContext'; import { Context, ContextKey } from './types'; /** * A Context implementation that holds a single value, optionally extending an existing context. */ export class ContextWithValue implements Context { - static create(key: ContextKey<unknown>, value: unknown, parent?: Context) { - return new ContextWithValue(parent ?? new BaseContext(), key, value); + static create(parent: Context, key: ContextKey<unknown>, value: unknown) { + return new ContextWithValue(parent, key, value); } private constructor( diff --git a/plugins/catalog-backend/src/next/Context/TransactionContext.ts b/plugins/catalog-backend/src/next/Context/TransactionValue.ts similarity index 77% rename from plugins/catalog-backend/src/next/Context/TransactionContext.ts rename to plugins/catalog-backend/src/next/Context/TransactionValue.ts index 6ac50fbc07..6959d13a18 100644 --- a/plugins/catalog-backend/src/next/Context/TransactionContext.ts +++ b/plugins/catalog-backend/src/next/Context/TransactionValue.ts @@ -23,14 +23,14 @@ const transactionContextKey = new ContextKey<Knex.Transaction | undefined>( ); /** - * TransactionContext handles the wrapping of a knex transaction in a Context. + * TransactionValue handles the wrapping of a knex transaction in a Context. */ -export class TransactionContext { - static create(tx: Knex.Transaction, parent?: Context) { - return ContextWithValue.create(transactionContextKey, tx, parent); +export class TransactionValue { + static in(parent: Context, tx: Knex.Transaction) { + return ContextWithValue.create(parent, transactionContextKey, tx); } - static getTransaction(context: Context): Knex.Transaction { + static from(context: Context): Knex.Transaction { const transaction = context.getContextValue(transactionContextKey); if (!transaction) { throw new Error(`No transaction available in context`); diff --git a/plugins/catalog-backend/src/next/Context/index.ts b/plugins/catalog-backend/src/next/Context/index.ts index 992f5e89a6..61dd4a2958 100644 --- a/plugins/catalog-backend/src/next/Context/index.ts +++ b/plugins/catalog-backend/src/next/Context/index.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -export { BaseContext } from './BaseContext'; +export { BackgroundContext } from './BackgroundContext'; export { ContextWithValue } from './ContextWithValue'; -export { TransactionContext } from './TransactionContext'; +export { TransactionValue } from './TransactionValue'; export { ContextKey } from './types'; export type { Context } from './types'; From 213cd261b6ccc691bc457907106ffba32b95a695 Mon Sep 17 00:00:00 2001 From: Martina Iglesias Fernandez <martina@roadie.io> Date: Fri, 23 Apr 2021 18:51:52 +0200 Subject: [PATCH 210/262] [chart] Update docker image Signed-off-by: Martina Iglesias Fernandez <martina@roadie.io> --- contrib/chart/backstage/templates/backend-deployment.yaml | 7 +++++++ contrib/chart/backstage/templates/frontend-deployment.yaml | 2 +- contrib/chart/backstage/values.yaml | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/contrib/chart/backstage/templates/backend-deployment.yaml b/contrib/chart/backstage/templates/backend-deployment.yaml index 144fc93e62..3096fc37ab 100644 --- a/contrib/chart/backstage/templates/backend-deployment.yaml +++ b/contrib/chart/backstage/templates/backend-deployment.yaml @@ -26,6 +26,13 @@ spec: {{- end}} containers: - name: {{ .Chart.Name }}-backend + command: ["node"] + args: + - "packages/backend" + - "--config" + - "app-config.yaml" + - "--config" + - {{ printf "/usr/src/app/%s" (include "backstage.appConfigFilename" .) | quote }} image: {{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }} imagePullPolicy: {{ .Values.backend.image.pullPolicy }} ports: diff --git a/contrib/chart/backstage/templates/frontend-deployment.yaml b/contrib/chart/backstage/templates/frontend-deployment.yaml index 9c674cc160..56f720e834 100644 --- a/contrib/chart/backstage/templates/frontend-deployment.yaml +++ b/contrib/chart/backstage/templates/frontend-deployment.yaml @@ -1,3 +1,4 @@ +{{- if .Values.frontend.enabled }} apiVersion: apps/v1 kind: Deployment metadata: @@ -46,7 +47,6 @@ spec: {{- if .Values.global.nodeSelector }} nodeSelector: {{- toYaml .Values.global.nodeSelector | nindent 8 }} {{- end }} -{{- if .Values.frontend.enabled }} --- apiVersion: v1 kind: Service diff --git a/contrib/chart/backstage/values.yaml b/contrib/chart/backstage/values.yaml index bd80bc22b6..78eb7cb92a 100644 --- a/contrib/chart/backstage/values.yaml +++ b/contrib/chart/backstage/values.yaml @@ -3,7 +3,7 @@ # Declare variables to be passed into your templates. frontend: - enabled: true + enabled: false replicaCount: 1 image: repository: martinaif/backstage-k8s-demo-frontend @@ -23,7 +23,7 @@ backend: replicaCount: 1 image: repository: martinaif/backstage-k8s-demo-backend - tag: test1 + tag: 20210423T1550 pullPolicy: IfNotPresent containerPort: 7000 resources: From 7e1617ce0e79dbff7f905389a337d5f6f6d2e6d2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 21 Apr 2021 19:58:02 +0200 Subject: [PATCH 211/262] catalog-backend: WIP EntityProvider mutation interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: blam <ben@blam.sh> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .../next/DefaultCatalogProcessingEngine.ts | 15 ++-- .../src/next/DefaultLocationStore.ts | 68 ++++++++++--------- .../src/next/NextCatalogBuilder.ts | 3 +- plugins/catalog-backend/src/next/types.ts | 21 +++--- 4 files changed, 55 insertions(+), 52 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 934ab3a1cc..b423b61041 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -19,6 +19,8 @@ import { CatalogProcessingEngine, EntityProvider, EntityMessage, + EntityProviderConnection, + EntityProviderMutation, ProcessingStateManager, CatalogProcessingOrchestrator, } from './types'; @@ -27,8 +29,13 @@ import { Logger } from 'winston'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { Stitcher } from './Stitcher'; +class Connection implements EntityProviderConnection { + constructor(private readonly stateManager: ProcessingStateManager) {} + + async applyMutation(mutation: EntityProviderMutation): Promise<void> {} +} + export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { - private subscriptions: Subscription[] = []; private running: boolean = false; constructor( @@ -41,11 +48,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async start() { for (const provider of this.entityProviders) { - const id = 'databaseProvider'; - const subscription = provider - .entityChange$() - .subscribe({ next: m => this.onNext(id, m) }); - this.subscriptions.push(subscription); + provider.connect(new Connection(this.stateManager)); } this.running = true; diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index b21fe9da02..a6b4adcca4 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -16,24 +16,29 @@ import { LocationSpec, Location } from '@backstage/catalog-model'; import { Database } from '../database'; -import { LocationStore } from './types'; +import { + LocationStore, + EntityProvider, + EntityProviderConnection, +} from './types'; import { v4 as uuidv4 } from 'uuid'; +import { locationSpecToLocationEntity } from './util'; import { ConflictError } from '@backstage/errors'; -import { Observable } from '@backstage/core'; -import ObservableImpl from 'zen-observable'; export type LocationMessage = | { all: Location[] } | { added: Location[]; removed: Location[] }; -export class DefaultLocationStore implements LocationStore { - private subscribers = new Set< - ZenObservable.SubscriptionObserver<LocationMessage> - >(); +export class DefaultLocationStore implements LocationStore, EntityProvider { + private _connection: EntityProviderConnection | undefined; constructor(private readonly db: Database) {} createLocation(spec: LocationSpec): Promise<Location> { + if (!this.connection) { + throw new Error('location store is not initialized'); + } + return this.db.transaction(async tx => { // TODO: id should really be type and target combined and not a uuid. @@ -55,7 +60,11 @@ export class DefaultLocationStore implements LocationStore { target: spec.target, }); - this.notifyAddition(location); + await this.connection.applyMutation({ + type: 'delta', + added: [locationSpecToLocationEntity(location)], + removed: [], + }); return location; }); @@ -75,40 +84,33 @@ export class DefaultLocationStore implements LocationStore { } deleteLocation(id: string): Promise<void> { + if (!this.connection) { + throw new Error('location store is not initialized'); + } + return this.db.transaction(async tx => { const location = await this.db.location(id); if (!location) { throw new ConflictError(`No location found with id: ${id}`); } await this.db.removeLocation(tx, id); - this.notifyDeletion(location); - }); - } - - private notifyAddition(location: Location) { - for (const subscriber of this.subscribers) { - subscriber.next({ - added: [location], - removed: [], - }); - } - } - - private notifyDeletion(location: Location) { - for (const subscriber of this.subscribers) { - subscriber.next({ + await this.connection.applyMutation({ + type: 'delta', added: [], - removed: [location], + removed: [locationSpecToLocationEntity(location)], }); - } + }); } - location$(): Observable<LocationMessage> { - return new ObservableImpl<LocationMessage>(subscriber => { - this.subscribers.add(subscriber); - return () => { - this.subscribers.delete(subscriber); - }; - }); + private get connection(): EntityProviderConnection { + if (!this._connection) { + throw new Error('location store is not initialized'); + } + + return this._connection; + } + + async connect(connection: EntityProviderConnection): Promise<void> { + this._connection = connection; } } diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index c3e0a6bd9c..1796847164 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -272,11 +272,10 @@ export class NextCatalogBuilder { const entitiesCatalog = new NextEntitiesCatalog(dbClient); const locationStore = new DefaultLocationStore(db); - const dbLocationProvider = new DatabaseLocationProvider(locationStore); const stitcher = new Stitcher(dbClient, logger); const processingEngine = new DefaultCatalogProcessingEngine( logger, - [dbLocationProvider], // entityproviders + [locationStore], // entityproviders stateManager, orchestrator, stitcher, diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index 0aeb290224..c3854d631f 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Entity, EntityName, @@ -21,7 +22,6 @@ import { EntityRelationSpec, } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/config'; -import { Observable } from '@backstage/core'; // << nooo export interface LocationEntity { apiVersion: 'backstage.io/v1alpha1'; @@ -45,20 +45,11 @@ export interface LocationService { deleteLocation(id: string): Promise<void>; } -export type EntityMessage = - | { all: Entity[] } - | { added: Entity[]; removed: EntityName[] }; - export interface LocationStore { - // extends EntityProvider createLocation(spec: LocationSpec): Promise<Location>; listLocations(): Promise<Location[]>; getLocation(id: string): Promise<Location>; deleteLocation(id: string): Promise<void>; - - location$(): Observable< - { all: Location[] } | { added: Location[]; removed: Location[] } - >; } export interface CatalogProcessingEngine { @@ -66,8 +57,16 @@ export interface CatalogProcessingEngine { stop(): Promise<void>; } +export type EntityProviderMutation = + | { type: 'full'; entities: Iterable<Entity> } + | { type: 'delta'; added: Iterable<Entity>; removed: Iterable<Entity> }; + +export interface EntityProviderConnection { + applyMutation(mutation: EntityProviderMutation): Promise<void>; +} + export interface EntityProvider { - entityChange$(): Observable<EntityMessage>; + connect(connection: EntityProviderConnection): Promise<void>; } export type EntityProcessingRequest = { From d9e5eeb575d316f60924dbd19a0c034cc433d162 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Thu, 22 Apr 2021 19:41:40 +0200 Subject: [PATCH 212/262] chore: worked on some more of the new catalog migration with fixing deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Co-authored-by: Johan Haals <johan.haals@gmail.com> Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Signed-off-by: blam <ben@blam.sh> --- .../20210302150147_refresh_state.js | 33 ++-- .../next/DefaultCatalogProcessingEngine.ts | 38 +++- .../src/next/DefaultLocationStore.ts | 4 - .../src/next/DefaultProcessingStateManager.ts | 13 +- .../src/next/database/DatabaseManager.ts | 114 +++++++++++ .../DefaultProcessingDatabase.test.ts | 31 +++ .../database/DefaultProcessingDatabase.ts | 180 +++++++++++++++++- .../src/next/database/types.ts | 17 ++ plugins/catalog-backend/src/next/types.ts | 21 +- 9 files changed, 405 insertions(+), 46 deletions(-) create mode 100644 plugins/catalog-backend/src/next/database/DatabaseManager.ts create mode 100644 plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 6abab6270b..14c75b2530 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -59,13 +59,14 @@ exports.up = async function up(knex) { .notNullable() .comment('JSON array containing all errors related to entity'); table - .dateTime('next_update_at') + .dateTime('next_update_at') // TOOD: timezone or change to epoch-millis or similar .notNullable() .comment('Timestamp of when entity should be updated'); table - .dateTime('last_discovery_at') + .dateTime('last_discovery_at') // TOOD: timezone or change to epoch-millis or similar .notNullable() .comment('The last timestamp of which this entity was discovered'); + table.index('entity_id', 'refresh_state_entity_id_idx'); table.index('entity_ref', 'refresh_state_entity_ref_idx'); table.index('next_update_at', 'refresh_state_next_update_at_idx'); }); @@ -94,38 +95,35 @@ exports.up = async function up(knex) { 'Holds edges between refresh state rows. Every time when an entity is processed and emits another entity, an edge will be stored to represent that fact. This is used to detect orphans and ultimately deletions.', ); table - .text('source_special_key') + .text('source_key') .nullable() .comment( 'When the reference source is not an entity, this is an opaque identifier for that source.', ); table - .text('source_entity_id') + .text('source_entity_ref') .nullable() - .references('entity_id') + .references('entity_ref') .inTable('refresh_state') .onDelete('CASCADE') .comment( - 'When the reference source is an entity, this is the ID of the source entity.', + 'When the reference source is an entity, this is the EntityRef of the source entity.', ); table - .text('target_entity_id') + .text('target_entity_ref') .notNullable() - .references('entity_id') + .references('entity_ref') .inTable('refresh_state') .onDelete('CASCADE') - .comment('The ID of the target entity.'); + .comment('The EntityRef of the target entity.'); + table.index('source_key', 'refresh_state_references_source_key_idx'); table.index( - 'source_special_key', - 'refresh_state_references_source_special_key_idx', + 'source_entity_ref', + 'refresh_state_references_source_entity_ref_idx', ); table.index( - 'source_entity_id', - 'refresh_state_references_source_entity_id_idx', - ); - table.index( - 'target_entity_id', - 'refresh_state_references_target_entity_id_idx', + 'target_entity_ref', + 'refresh_state_references_target_entity_ref_idx', ); }); @@ -165,6 +163,7 @@ exports.down = async function down(knex) { table.dropIndex([], 'refresh_state_references_target_entity_id_idx'); }); await knex.schema.alterTable('refresh_state', table => { + table.dropIndex([], 'refresh_state_entity_id_idx'); table.dropIndex([], 'refresh_state_entity_ref_idx'); table.dropIndex([], 'refresh_state_next_update_at_idx'); }); diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index b423b61041..7f49bf832d 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -30,9 +30,31 @@ import { stringifyEntityRef } from '@backstage/catalog-model'; import { Stitcher } from './Stitcher'; class Connection implements EntityProviderConnection { - constructor(private readonly stateManager: ProcessingStateManager) {} + constructor( + private readonly config: { + stateManager: ProcessingStateManager; + id: string; + }, + ) {} - async applyMutation(mutation: EntityProviderMutation): Promise<void> {} + async applyMutation(mutation: EntityProviderMutation): Promise<void> { + if (mutation.type === 'full') { + await this.config.stateManager.replaceProcessingItems({ + id: this.config.id, + type: 'full', + items: mutation.entities, + }); + + return; + } + + await this.config.stateManager.replaceProcessingItems({ + id: this.config.id, + type: 'delta', + added: mutation.added, + removed: mutation.removed, + }); + } } export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { @@ -48,7 +70,9 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async start() { for (const provider of this.entityProviders) { - provider.connect(new Connection(this.stateManager)); + // TODO: this ID should be some form of identifier for the EntityProvider + const id = 'databaseProvider'; + provider.connect(new Connection({ stateManager: this.stateManager, id })); } this.running = true; @@ -57,12 +81,12 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { const { id, entity, - state: intialState, + state: initialState, } = await this.stateManager.getNextProcessingItem(); const result = await this.orchestrator.process({ entity, - state: intialState, + state: initialState, }); for (const error of result.errors) { @@ -95,10 +119,6 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async stop() { this.running = false; - - for (const subscription of this.subscriptions) { - subscription.unsubscribe(); - } } private async onNext(id: string, message: EntityMessage) { diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index a6b4adcca4..dff424b1a9 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -35,10 +35,6 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { constructor(private readonly db: Database) {} createLocation(spec: LocationSpec): Promise<Location> { - if (!this.connection) { - throw new Error('location store is not initialized'); - } - return this.db.transaction(async tx => { // TODO: id should really be type and target combined and not a uuid. diff --git a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts index 91090bc139..d2765c3101 100644 --- a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts +++ b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts @@ -17,14 +17,23 @@ import { ProcessingDatabase, RefreshStateItem } from './database/types'; import { AddProcessingItemRequest, - ProccessingItem, + ProcessingItem, ProcessingItemResult, ProcessingStateManager, + ReplaceProcessingItemsRequest, } from './types'; export class DefaultProcessingStateManager implements ProcessingStateManager { constructor(private readonly db: ProcessingDatabase) {} + replaceProcessingItems( + request: ReplaceProcessingItemsRequest, + ): Promise<void> { + return this.db.transaction(async tx => { + await this.db.replaceUnprocessedEntities(tx, request); + }); + } + async setProcessingItemResult(result: ProcessingItemResult) { return this.db.transaction(async tx => { await this.db.updateProcessedEntity(tx, { @@ -44,7 +53,7 @@ export class DefaultProcessingStateManager implements ProcessingStateManager { }); } - async getNextProcessingItem(): Promise<ProccessingItem> { + async getNextProcessingItem(): Promise<ProcessingItem> { const entities = await new Promise<RefreshStateItem[]>(resolve => this.popFromQueue(resolve), ); diff --git a/plugins/catalog-backend/src/next/database/DatabaseManager.ts b/plugins/catalog-backend/src/next/database/DatabaseManager.ts new file mode 100644 index 0000000000..4c9e45950f --- /dev/null +++ b/plugins/catalog-backend/src/next/database/DatabaseManager.ts @@ -0,0 +1,114 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger, resolvePackagePath } from '@backstage/backend-common'; +import knexFactory, { Knex } from 'knex'; +import { v4 as uuidv4 } from 'uuid'; +import { Logger } from 'winston'; +import { CommonDatabase } from '../../database/CommonDatabase'; +import { Database } from '../../database/types'; +import fs from 'fs-extra'; + +export type CreateDatabaseOptions = { + logger: Logger; +}; + +const defaultOptions: CreateDatabaseOptions = { + logger: getVoidLogger(), +}; + +export class DatabaseManager { + public static async createDatabase( + knex: Knex, + options: Partial<CreateDatabaseOptions> = {}, + ): Promise<Database> { + const allMigrations = resolvePackagePath( + '@backstage/plugin-catalog-backend', + 'migrations', + ); + + const migrationsDir = resolvePackagePath( + '@backstage/plugin-catalog-backend', + 'migrationsv2', + ); + await fs.copy(allMigrations, migrationsDir); + + await knex.migrate.latest({ + directory: migrationsDir, + }); + const { logger } = { ...defaultOptions, ...options }; + return new CommonDatabase(knex, logger); + } + + public static async createInMemoryDatabase(): Promise<Database> { + const knex = await this.createInMemoryDatabaseConnection(); + return await this.createDatabase(knex); + } + + public static async createInMemoryDatabaseConnection(): Promise<Knex> { + const knex = knexFactory({ + client: 'sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }); + + knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { + resource.run('PRAGMA foreign_keys = ON', () => {}); + }); + + return knex; + } + + public static async createTestDatabase(): Promise<Database> { + const knex = await this.createTestDatabaseConnection(); + return await this.createDatabase(knex); + } + + public static async createTestDatabaseConnection(): Promise<Knex> { + const config: Knex.Config<any> = { + /* + client: 'pg', + connection: { + host: 'localhost', + user: 'postgres', + password: 'postgres', + }, + */ + client: 'sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }; + + let knex = knexFactory(config); + if (typeof config.connection !== 'string') { + const tempDbName = `d${uuidv4().replace(/-/g, '')}`; + await knex.raw(`CREATE DATABASE ${tempDbName};`); + knex = knexFactory({ + ...config, + connection: { + ...config.connection, + database: tempDbName, + }, + }); + } + + knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { + resource.run('PRAGMA foreign_keys = ON', () => {}); + }); + + return knex; + } +} diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts new file mode 100644 index 0000000000..fd2e9e6750 --- /dev/null +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { DefaultProcessingDatabase } from './DefaultProcessingDatabase'; +import { DatabaseManager } from './DatabaseManager'; +import { Knex } from 'knex'; + +describe('Default Processing Database', () => { + let db: Knex | undefined; + + beforeEach(async () => { + db = await DatabaseManager.createTestDatabaseConnection(); + await DatabaseManager.createDatabase(db); + }); + + it('should write some stuff', async () => { + await db('refresh_state_referencess').select(); + }); +}); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index cf2d4e121c..b799bd6284 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -15,6 +15,7 @@ */ import { ConflictError, NotFoundError } from '@backstage/errors'; +import { stringifyEntityRef, Entity } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { Transaction } from '../../database'; import lodash from 'lodash'; @@ -24,20 +25,21 @@ import { AddUnprocessedEntitiesOptions, UpdateProcessedEntityOptions, GetProcessableEntitiesResult, + ReplaceUnprocessedEntitiesOptions, } from './types'; import type { Logger } from 'winston'; -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; + import { v4 as uuid } from 'uuid'; export type DbRefreshStateRow = { entity_id: string; entity_ref: string; unprocessed_entity: string; - processed_entity: string; - cache: string; + processed_entity?: string; + cache?: string; next_update_at: string; last_discovery_at: string; // remove? - errors: string; + errors?: string; }; export type DbRelationsRow = { @@ -47,10 +49,10 @@ export type DbRelationsRow = { type: string; }; -export type DbRefreshStateReferences = { - source_special_key?: string; - source_entity_id?: string; - target_entity_id: string; +export type DbRefreshStateReferencesRow = { + source_key?: string; + source_entity_ref?: string; + target_entity_ref: string; }; // The number of items that are sent per batch to the database layer, when @@ -128,6 +130,164 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); } + async replaceUnprocessedEntities( + txOpaque: Transaction, + options: ReplaceUnprocessedEntitiesOptions, + ): Promise<void> { + const tx = txOpaque as Knex.Transaction; + const entityIds = new Array<string>(); + + if (options.type === 'full') { + const oldRefs = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .where({ source_key: options.sourceKey }) + .select('target_entity_ref') + .then(rows => rows.map(r => r.target_entity_ref)); + + const items = options.items.map(entity => ({ + entity, + ref: stringifyEntityRef(entity), + id: uuid(), + })); + + const oldRefsSet = new Set(oldRefs); + const newRefsSet = new Set(items.map(item => item.ref)); + const toAdd = items.filter(item => !oldRefsSet.has(item.ref)); + const toRemove = oldRefs.filter(ref => !newRefsSet.has(ref)); + + if (toRemove.length) { + // TODO(freben): Batch split, to not hit variable limits? + + // get all refs where source = any of the toRemove + // delete all state rows matching any of the toRemove + // revisit the targets of all of those refs + // verify if they have references, otherwise delete from refresh_state + + const current = [...toRemove]; + while (true) { + + tx.withRecursive('r', function refs() { + return tx.select({ }) + .from({ r1: 'refresh_state_references' }) + .where({ source_key: options.sourceKey }) + .whereIn('target_entity_ref', toRemove) + .unionAll(function recurse() { + return tx.select({ }) + .from({ r2: 'refresh_state_references' }) + .whereNotExists() + }) + }) + .select().from('refs'); + + const nextLayerToRemove = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .whereIn('source_entity_ref', toRemove) + .leftOuterJoin('refresh_state_references AS b', function f() { + + }) + + .whereNotNull('b.source_target_ref') + .select('target_entity_ref'); + + await tx<DbRefreshStateRow>('refresh_state') + .whereIn('entity_ref', toRemove) + .delete(); + + const refsThatStillHaveASourcePointingAtThe = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .whereIn('target_entity_ref', nextLayerTargetRefs) + .groupBy('target_entity_ref') + .select('target_entity_ref'); + + } + + + + + if (toAdd.length) { + const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(item => ({ + entity_id: item.id, + entity_ref: item.ref, + unprocessed_entity: JSON.stringify(item.entity), + errors: '', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + })); + const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( + item => ({ + source_key: options.sourceKey, + target_entity_ref: item.ref, + }), + ); + // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense + await tx.batchInsert('refresh_state', state, BATCH_SIZE); + await tx.batchInsert('refresh_state_references', stateReferences, BATCH_SIZE); + } + + + for (const entity of options.items) { + const entityRef = stringifyEntityRef(entity); + await tx<DbRefreshStateRow>('refresh_state') + .insert({ + entity_id: uuid(), + entity_ref: entityRef, + unprocessed_entity: JSON.stringify(entity), + errors: '', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + }) + .onConflict('entity_ref') + .merge(['unprocessed_entity', 'last_discovery_at']); + + const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( + 'refresh_state', + ).where({ entity_ref: entityRef }); + entityIds.push(entityId); + } + const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( + entityId => ({ + source_key: options.sourceKey, + target_entityRef: entityRef, + }), + ); + await tx.batchInsert( + 'refresh_state_references', + referenceRows, + BATCH_SIZE, + ); + return; + } + + for (const entity of options.removed) { + const entityRef = stringifyEntityRef(entity); + const [result] = await tx<DbRefreshStateRow>('refresh_state') + .where({ entity_ref: entityRef }) + .select('entity_id'); + + if (!result) { + this.logger.info( + `Unable to delete entity '${entityRef}', entity does not exist in refresh state`, + ); + continue; + } + + const referenceResults = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + // todo correct key? + .where({ source_entity_id: result.entity_id }) + .select(); + + await tx<DbRefreshStateReferencesRow>('refresh_state_references') + // todo correct key? + .where({ source_entity_id: result.entity_id }) + .delete(); + } + } + async addUnprocessedEntities( txOpaque: Transaction, options: AddUnprocessedEntitiesOptions, @@ -160,11 +320,11 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ? { source_special_key: options.id } : { source_entity_id: options.id }; // copied from update refs - await tx<DbRefreshStateReferences>('refresh_state_references') + await tx<DbRefreshStateReferencesRow>('refresh_state_references') .where(key) .delete(); - const referenceRows: DbRefreshStateReferences[] = entityIds.map( + const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( entityId => ({ ...key, target_entity_id: entityId, diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index 22e9e90c8e..b926676887 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -50,6 +50,19 @@ export type GetProcessableEntitiesResult = { items: RefreshStateItem[]; }; +export type ReplaceUnprocessedEntitiesOptions = + | { + sourceKey: string; + items: Entity[]; + type: 'full'; + } + | { + sourceKey: string; + added: Entity[]; + removed: Entity[]; + type: 'delta'; + }; + export interface ProcessingDatabase { transaction<T>(fn: (tx: Transaction) => Promise<T>): Promise<T>; @@ -58,6 +71,10 @@ export interface ProcessingDatabase { options: AddUnprocessedEntitiesOptions, ): Promise<void>; + replaceUnprocessedEntities( + txOpaque: Transaction, + options: ReplaceUnprocessedEntitiesOptions, + ): Promise<void>; getProcessableEntities( txOpaque: Transaction, request: { processBatchSize: number }, diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index c3854d631f..f8b4de1c41 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -58,8 +58,8 @@ export interface CatalogProcessingEngine { } export type EntityProviderMutation = - | { type: 'full'; entities: Iterable<Entity> } - | { type: 'delta'; added: Iterable<Entity>; removed: Iterable<Entity> }; + | { type: 'full'; entities: Entity[] } + | { type: 'delta'; added: Entity[]; removed: Entity[] }; export interface EntityProviderConnection { applyMutation(mutation: EntityProviderMutation): Promise<void>; @@ -108,14 +108,27 @@ export type AddProcessingItemRequest = { entities: Entity[]; }; -export type ProccessingItem = { +export type ProcessingItem = { id: string; entity: Entity; state: Map<string, JsonObject>; }; +export type ReplaceProcessingItemsRequest = + | { + id: string; + items: Entity[]; + type: 'full'; + } + | { + id: string; + added: Entity[]; + removed: Entity[]; + type: 'delta'; + }; export interface ProcessingStateManager { setProcessingItemResult(result: ProcessingItemResult): Promise<void>; - getNextProcessingItem(): Promise<ProccessingItem>; + getNextProcessingItem(): Promise<ProcessingItem>; addProcessingItems(request: AddProcessingItemRequest): Promise<void>; + replaceProcessingItems(request: ReplaceProcessingItemsRequest): Promise<void>; } From 87ff2b455a9390ff9067fea7e01c20d4f984dcfe Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 23 Apr 2021 15:05:04 +0200 Subject: [PATCH 213/262] feat: added support for full sync replace with an awesome sql statement courtesy of @freben MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: Johan Haals <johan.haals@gmail.com> Signed-off-by: blam <ben@blam.sh> --- .../20210302150147_refresh_state.js | 3 + .../DefaultProcessingDatabase.test.ts | 271 +++++++++++++++++- .../database/DefaultProcessingDatabase.ts | 220 +++++++------- 3 files changed, 390 insertions(+), 104 deletions(-) diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 14c75b2530..2afeda02c0 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -94,6 +94,9 @@ exports.up = async function up(knex) { table.comment( 'Holds edges between refresh state rows. Every time when an entity is processed and emits another entity, an edge will be stored to represent that fact. This is used to detect orphans and ultimately deletions.', ); + table + .increments('id') + .comment('Primary key to distinguish unique lines from each other'); table .text('source_key') .nullable() diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index fd2e9e6750..ee04a2baf8 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -16,16 +16,283 @@ // import { DefaultProcessingDatabase } from './DefaultProcessingDatabase'; import { DatabaseManager } from './DatabaseManager'; import { Knex } from 'knex'; +import { + DbRefreshStateReferencesRow, + DbRefreshStateRow, + DefaultProcessingDatabase, +} from './DefaultProcessingDatabase'; + +import { Entity } from '@backstage/catalog-model'; +import * as uuid from 'uuid'; +import { getVoidLogger } from '@backstage/backend-common'; describe('Default Processing Database', () => { let db: Knex | undefined; + let processingDatabase: DefaultProcessingDatabase | undefined; + + const logger = getVoidLogger(); beforeEach(async () => { db = await DatabaseManager.createTestDatabaseConnection(); await DatabaseManager.createDatabase(db); + + processingDatabase = new DefaultProcessingDatabase(db!, logger); }); - it('should write some stuff', async () => { - await db('refresh_state_referencess').select(); + describe('replaceUnprocessedEntities', () => { + const insertRefRow = async (ref: DbRefreshStateReferencesRow) => { + return db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).insert(ref); + }; + + const insertRefreshStateRow = async (ref: DbRefreshStateRow) => { + await db!<DbRefreshStateRow>('refresh_state').insert(ref); + }; + + const createLocations = async (entityRefs: string[]) => { + for (const ref of entityRefs) { + await insertRefreshStateRow({ + entity_id: uuid.v4(), + entity_ref: ref, + unprocessed_entity: '{}', + processed_entity: '{}', + errors: '', + next_update_at: 'now()', + last_discovery_at: 'now()', + }); + } + }; + + it('replaces all existing state correctly for simple dependency chains', async () => { + /* + config -> location:default/root -> location:default/root-1 -> location:default/root-2 + database -> location:default/second -> location:default/root-2 + */ + await createLocations([ + 'location:default/root', + 'location:default/root-1', + 'location:default/root-2', + 'location:default/second', + ]); + + await insertRefRow({ + source_key: 'config', + target_entity_ref: 'location:default/root', + }); + + await insertRefRow({ + source_key: 'database', + target_entity_ref: 'location:default/second', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root', + target_entity_ref: 'location:default/root-1', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root-1', + target_entity_ref: 'location:default/root-2', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/second', + target_entity_ref: 'location:default/root-2', + }); + + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'config', + items: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + for (const ref of ['location:default/root', 'location:default/root-1']) { + expect(currentRefreshState.some(t => t.entity_ref === ref)).toBeFalsy(); + } + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root' && + t.target_entity_ref === 'location:default/root-1', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root-1' && + t.target_entity_ref === 'location:default/root-2', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.target_entity_ref === 'location:default/root-1' && + t.source_key === 'config', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.target_entity_ref === 'location:default/new-root' && + t.source_key === 'config', + ), + ).toBeTruthy(); + }); + + it('should work for more complex chains', async () => { + /* + config -> location:default/root -> location:default/root-1 -> location:default/root-2 + config -> location:default/root -> location:default/root-1a -> location:default/root-2 + */ + await createLocations([ + 'location:default/root', + 'location:default/root-1', + 'location:default/root-2', + 'location:default/root-1a', + ]); + + await insertRefRow({ + source_key: 'config', + target_entity_ref: 'location:default/root', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root', + target_entity_ref: 'location:default/root-1', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root', + target_entity_ref: 'location:default/root-1a', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root-1', + target_entity_ref: 'location:default/root-2', + }); + + await insertRefRow({ + source_entity_ref: 'location:default/root-1a', + target_entity_ref: 'location:default/root-2', + }); + + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'config', + items: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + const deletedRefs = [ + 'location:default/root', + 'location:default/root-1', + 'location:default/root-1a', + 'location:default/root-2', + ]; + + for (const ref of deletedRefs) { + expect(currentRefreshState.some(t => t.entity_ref === ref)).toBeFalsy(); + } + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'config' && + t.target_entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'config' && + t.target_entity_ref === 'location:default/root', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root' && + t.target_entity_ref === 'location:default/root-1', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root' && + t.target_entity_ref === 'location:default/root-1a', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root-1' && + t.target_entity_ref === 'location:default/root-2', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_entity_ref === 'location:default/root-1a' && + t.target_entity_ref === 'location:default/root-2', + ), + ).toBeFalsy(); + }); }); }); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index b799bd6284..f0c5443651 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -135,7 +135,6 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { options: ReplaceUnprocessedEntitiesOptions, ): Promise<void> { const tx = txOpaque as Knex.Transaction; - const entityIds = new Array<string>(); if (options.type === 'full') { const oldRefs = await tx<DbRefreshStateReferencesRow>( @@ -158,55 +157,95 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (toRemove.length) { // TODO(freben): Batch split, to not hit variable limits? - - // get all refs where source = any of the toRemove - // delete all state rows matching any of the toRemove - // revisit the targets of all of those refs - // verify if they have references, otherwise delete from refresh_state - - const current = [...toRemove]; - while (true) { - - tx.withRecursive('r', function refs() { - return tx.select({ }) - .from({ r1: 'refresh_state_references' }) - .where({ source_key: options.sourceKey }) - .whereIn('target_entity_ref', toRemove) - .unionAll(function recurse() { - return tx.select({ }) - .from({ r2: 'refresh_state_references' }) - .whereNotExists() - }) + /* + WITH RECURSIVE + -- All the refs that can be reached from each individual root + root_reach(id, entity_ref) AS ( + -- Start with all roots + SELECT id, target_entity_ref + FROM refresh_state_references + WHERE source_key IS NOT NULL + UNION + -- For each match, select all children + SELECT root_reach.id, target_entity_ref + FROM refresh_state_references, root_reach + WHERE source_entity_ref = root_reach.entity_ref + ) + -- Start out with our own matching row (see the WHERE that + -- matches on source_key and target_entity_ref below) + SELECT us.entity_ref + FROM refresh_state_references + -- Expand the entire tree that emanates from that row + JOIN root_reach AS us + ON us.id = refresh_state_references.id + -- Expand with all roots that target the same node but + -- aren't ourselves + LEFT OUTER JOIN root_reach AS them + ON them.entity_ref = us.entity_ref + AND them.id != us.id + -- Keep only the matches that had no other rooots + WHERE refresh_state_references.source_key = "R1" + AND refresh_state_references.target_entity_ref = "A" + AND them.id IS NULL; + */ + const removedCount = await tx<DbRefreshStateRow>('refresh_state') + .whereIn('entity_ref', function orphanedEntityRefs(orphans) { + return ( + orphans + // All the refs that can be reached from each individual root + .withRecursive('root_reach', function rootReach(outer) { + // Start with all roots + return outer + .select({ id: 'id', entity_ref: 'target_entity_ref' }) + .from('refresh_state_references') + .whereNotNull('source_key') + .union(function recurse(inner) { + return ( + inner + // For each match, select all children + .select({ + id: 'root_reach.id', + entity_ref: + 'refresh_state_references.target_entity_ref', + }) + .from('refresh_state_references') + .crossJoin('root_reach', { + 'root_reach.entity_ref': + 'refresh_state_references.source_entity_ref', + }) + ); + }); + }) + .select('us.entity_ref') + // Start out with our own matching row + .from('refresh_state_references') + .where('source_key', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + // Expand the entire tree that emanates from that row + .leftJoin({ us: 'root_reach' }, function us() { + this.on('us.id', '=', 'refresh_state_references.id'); + }) + // Expand with all roots that target the same node but aren't ourselves + .leftOuterJoin({ them: 'root_reach' }, function them() { + this.on('them.entity_ref', '=', 'us.entity_ref'); + this.andOn('them.id', '!=', 'us.id'); + }) + // Keep only the matches that had no other rooots + .whereNull('them.id') + ); }) - .select().from('refs'); + .delete(); - const nextLayerToRemove = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .whereIn('source_entity_ref', toRemove) - .leftOuterJoin('refresh_state_references AS b', function f() { - - }) - - .whereNotNull('b.source_target_ref') - .select('target_entity_ref'); - - await tx<DbRefreshStateRow>('refresh_state') - .whereIn('entity_ref', toRemove) - .delete(); - - const refsThatStillHaveASourcePointingAtThe = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .whereIn('target_entity_ref', nextLayerTargetRefs) - .groupBy('target_entity_ref') - .select('target_entity_ref'); + await tx<DbRefreshStateReferencesRow>('refresh_state_references') + .where('source_key', '=', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + .delete(); + console.log( + `REMOVED, ${removedCount} entities: ${JSON.stringify(toRemove)}`, + ); } - - - if (toAdd.length) { const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(item => ({ entity_id: item.id, @@ -224,67 +263,44 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense await tx.batchInsert('refresh_state', state, BATCH_SIZE); - await tx.batchInsert('refresh_state_references', stateReferences, BATCH_SIZE); - } - - - for (const entity of options.items) { - const entityRef = stringifyEntityRef(entity); - await tx<DbRefreshStateRow>('refresh_state') - .insert({ - entity_id: uuid(), - entity_ref: entityRef, - unprocessed_entity: JSON.stringify(entity), - errors: '', - next_update_at: tx.fn.now(), - last_discovery_at: tx.fn.now(), - }) - .onConflict('entity_ref') - .merge(['unprocessed_entity', 'last_discovery_at']); - - const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( - 'refresh_state', - ).where({ entity_ref: entityRef }); - entityIds.push(entityId); - } - const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( - entityId => ({ - source_key: options.sourceKey, - target_entityRef: entityRef, - }), - ); - await tx.batchInsert( - 'refresh_state_references', - referenceRows, - BATCH_SIZE, - ); - return; - } - - for (const entity of options.removed) { - const entityRef = stringifyEntityRef(entity); - const [result] = await tx<DbRefreshStateRow>('refresh_state') - .where({ entity_ref: entityRef }) - .select('entity_id'); - - if (!result) { - this.logger.info( - `Unable to delete entity '${entityRef}', entity does not exist in refresh state`, + await tx.batchInsert( + 'refresh_state_references', + stateReferences, + BATCH_SIZE, ); - continue; } - const referenceResults = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - // todo correct key? - .where({ source_entity_id: result.entity_id }) - .select(); + // for (const entity of options.items) { + // const entityRef = stringifyEntityRef(entity); + // await tx<DbRefreshStateRow>('refresh_state') + // .insert({ + // entity_id: uuid(), + // entity_ref: entityRef, + // unprocessed_entity: JSON.stringify(entity), + // errors: '', + // next_update_at: tx.fn.now(), + // last_discovery_at: tx.fn.now(), + // }) + // .onConflict('entity_ref') + // .merge(['unprocessed_entity', 'last_discovery_at']); - await tx<DbRefreshStateReferencesRow>('refresh_state_references') - // todo correct key? - .where({ source_entity_id: result.entity_id }) - .delete(); + // const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( + // 'refresh_state', + // ).where({ entity_ref: entityRef }); + // entityIds.push(entityId); + // } + // const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( + // entityId => ({ + // source_key: options.sourceKey, + // target_entityRef: entityRef, + // }), + // ); + // await tx.batchInsert( + // 'refresh_state_references', + // referenceRows, + // BATCH_SIZE, + // ); + // return; } } From 3f6c50a5291775994b0f90890f286b0018f74a7e Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Fri, 23 Apr 2021 16:01:36 +0200 Subject: [PATCH 214/262] feat: support delta and full sync with the same code and simplify things MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: Johan Haals <johan.haals@gmail.com> Signed-off-by: blam <ben@blam.sh> --- .../DefaultProcessingDatabase.test.ts | 89 +++++++ .../database/DefaultProcessingDatabase.ts | 242 ++++++++---------- 2 files changed, 201 insertions(+), 130 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index ee04a2baf8..c4784c081d 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -294,5 +294,94 @@ describe('Default Processing Database', () => { ), ).toBeFalsy(); }); + + it('should add new locations using the delta options', async () => { + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'delta', + sourceKey: 'lols', + removed: [], + added: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'lols' && + t.target_entity_ref === 'location:default/new-root', + ), + ).toBeTruthy(); + }); + + it('should remove old locations using the delta options', async () => { + await createLocations(['location:default/new-root']); + + await insertRefRow({ + source_key: 'lols', + target_entity_ref: 'location:default/new-root', + }); + + await processingDatabase!.transaction(async tx => { + await processingDatabase!.replaceUnprocessedEntities(tx, { + type: 'delta', + sourceKey: 'lols', + added: [], + removed: [ + { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + ], + }); + }); + + const currentRefreshState = await db!<DbRefreshStateRow>( + 'refresh_state', + ).select(); + + const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + expect( + currentRefreshState.some( + t => t.entity_ref === 'location:default/new-root', + ), + ).toBeFalsy(); + + expect( + currentRefRowState.some( + t => + t.source_key === 'lols' && + t.target_entity_ref === 'location:default/new-root', + ), + ).toBeFalsy(); + }); }); }); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index f0c5443651..a80325d469 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -130,34 +130,48 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); } + private async createDelta( + tx: Knex.Transaction, + options: ReplaceUnprocessedEntitiesOptions, + ): Promise<{ toAdd: Entity[]; toRemove: string[] }> { + if (options.type === 'delta') { + return { + toAdd: options.added, + toRemove: options.removed.map(e => stringifyEntityRef(e)), + }; + } + + const oldRefs = await tx<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ) + .where({ source_key: options.sourceKey }) + .select('target_entity_ref') + .then(rows => rows.map(r => r.target_entity_ref)); + + const items = options.items.map(entity => ({ + entity, + ref: stringifyEntityRef(entity), + })); + + const oldRefsSet = new Set(oldRefs); + const newRefsSet = new Set(items.map(item => item.ref)); + const toAdd = items.filter(item => !oldRefsSet.has(item.ref)); + const toRemove = oldRefs.filter(ref => !newRefsSet.has(ref)); + + return { toAdd: toAdd.map(({ entity }) => entity), toRemove }; + } + async replaceUnprocessedEntities( txOpaque: Transaction, options: ReplaceUnprocessedEntitiesOptions, ): Promise<void> { const tx = txOpaque as Knex.Transaction; - if (options.type === 'full') { - const oldRefs = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .where({ source_key: options.sourceKey }) - .select('target_entity_ref') - .then(rows => rows.map(r => r.target_entity_ref)); + const { toAdd, toRemove } = await this.createDelta(tx, options); - const items = options.items.map(entity => ({ - entity, - ref: stringifyEntityRef(entity), - id: uuid(), - })); - - const oldRefsSet = new Set(oldRefs); - const newRefsSet = new Set(items.map(item => item.ref)); - const toAdd = items.filter(item => !oldRefsSet.has(item.ref)); - const toRemove = oldRefs.filter(ref => !newRefsSet.has(ref)); - - if (toRemove.length) { - // TODO(freben): Batch split, to not hit variable limits? - /* + if (toRemove.length) { + // TODO(freben): Batch split, to not hit variable limits? + /* WITH RECURSIVE -- All the refs that can be reached from each individual root root_reach(id, entity_ref) AS ( @@ -188,119 +202,87 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { AND refresh_state_references.target_entity_ref = "A" AND them.id IS NULL; */ - const removedCount = await tx<DbRefreshStateRow>('refresh_state') - .whereIn('entity_ref', function orphanedEntityRefs(orphans) { - return ( - orphans - // All the refs that can be reached from each individual root - .withRecursive('root_reach', function rootReach(outer) { - // Start with all roots - return outer - .select({ id: 'id', entity_ref: 'target_entity_ref' }) - .from('refresh_state_references') - .whereNotNull('source_key') - .union(function recurse(inner) { - return ( - inner - // For each match, select all children - .select({ - id: 'root_reach.id', - entity_ref: - 'refresh_state_references.target_entity_ref', - }) - .from('refresh_state_references') - .crossJoin('root_reach', { - 'root_reach.entity_ref': - 'refresh_state_references.source_entity_ref', - }) - ); - }); - }) - .select('us.entity_ref') - // Start out with our own matching row - .from('refresh_state_references') - .where('source_key', options.sourceKey) - .whereIn('target_entity_ref', toRemove) - // Expand the entire tree that emanates from that row - .leftJoin({ us: 'root_reach' }, function us() { - this.on('us.id', '=', 'refresh_state_references.id'); - }) - // Expand with all roots that target the same node but aren't ourselves - .leftOuterJoin({ them: 'root_reach' }, function them() { - this.on('them.entity_ref', '=', 'us.entity_ref'); - this.andOn('them.id', '!=', 'us.id'); - }) - // Keep only the matches that had no other rooots - .whereNull('them.id') - ); - }) - .delete(); + const removedCount = await tx<DbRefreshStateRow>('refresh_state') + .whereIn('entity_ref', function orphanedEntityRefs(orphans) { + return ( + orphans + // All the refs that can be reached from each individual root + .withRecursive('root_reach', function rootReach(outer) { + // Start with all roots + return outer + .select({ id: 'id', entity_ref: 'target_entity_ref' }) + .from('refresh_state_references') + .whereNotNull('source_key') + .union(function recurse(inner) { + return ( + inner + // For each match, select all children + .select({ + id: 'root_reach.id', + entity_ref: + 'refresh_state_references.target_entity_ref', + }) + .from('refresh_state_references') + .crossJoin('root_reach', { + 'root_reach.entity_ref': + 'refresh_state_references.source_entity_ref', + }) + ); + }); + }) + .select('us.entity_ref') + // Start out with our own matching row + .from('refresh_state_references') + .where('source_key', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + // Expand the entire tree that emanates from that row + .leftJoin({ us: 'root_reach' }, function us() { + this.on('us.id', '=', 'refresh_state_references.id'); + }) + // Expand with all roots that target the same node but aren't ourselves + .leftOuterJoin({ them: 'root_reach' }, function them() { + this.on('them.entity_ref', '=', 'us.entity_ref'); + this.andOn('them.id', '!=', 'us.id'); + }) + // Keep only the matches that had no other rooots + .whereNull('them.id') + ); + }) + .delete(); - await tx<DbRefreshStateReferencesRow>('refresh_state_references') - .where('source_key', '=', options.sourceKey) - .whereIn('target_entity_ref', toRemove) - .delete(); + await tx<DbRefreshStateReferencesRow>('refresh_state_references') + .where('source_key', '=', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + .delete(); - console.log( - `REMOVED, ${removedCount} entities: ${JSON.stringify(toRemove)}`, - ); - } + this.logger.debug( + `removed, ${removedCount} entities: ${JSON.stringify(toRemove)}`, + ); + } - if (toAdd.length) { - const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(item => ({ - entity_id: item.id, - entity_ref: item.ref, - unprocessed_entity: JSON.stringify(item.entity), - errors: '', - next_update_at: tx.fn.now(), - last_discovery_at: tx.fn.now(), - })); - const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( - item => ({ - source_key: options.sourceKey, - target_entity_ref: item.ref, - }), - ); - // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense - await tx.batchInsert('refresh_state', state, BATCH_SIZE); - await tx.batchInsert( - 'refresh_state_references', - stateReferences, - BATCH_SIZE, - ); - } + if (toAdd.length) { + const state: Knex.DbRecord<DbRefreshStateRow>[] = toAdd.map(entity => ({ + entity_id: uuid(), + entity_ref: stringifyEntityRef(entity), + unprocessed_entity: JSON.stringify(entity), + errors: '', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + })); - // for (const entity of options.items) { - // const entityRef = stringifyEntityRef(entity); - // await tx<DbRefreshStateRow>('refresh_state') - // .insert({ - // entity_id: uuid(), - // entity_ref: entityRef, - // unprocessed_entity: JSON.stringify(entity), - // errors: '', - // next_update_at: tx.fn.now(), - // last_discovery_at: tx.fn.now(), - // }) - // .onConflict('entity_ref') - // .merge(['unprocessed_entity', 'last_discovery_at']); - - // const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( - // 'refresh_state', - // ).where({ entity_ref: entityRef }); - // entityIds.push(entityId); - // } - // const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( - // entityId => ({ - // source_key: options.sourceKey, - // target_entityRef: entityRef, - // }), - // ); - // await tx.batchInsert( - // 'refresh_state_references', - // referenceRows, - // BATCH_SIZE, - // ); - // return; + const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( + entity => ({ + source_key: options.sourceKey, + target_entity_ref: stringifyEntityRef(entity), + }), + ); + // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense + await tx.batchInsert('refresh_state', state, BATCH_SIZE); + await tx.batchInsert( + 'refresh_state_references', + stateReferences, + BATCH_SIZE, + ); } } From 11ef45c0972a439085dbf772057d299dadccc63c Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 10:14:45 +0200 Subject: [PATCH 215/262] catalog-backend: Remove obervables Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/package.json | 4 +- .../src/next/DatabaseLocationProvider.ts | 71 ------------------- .../next/DefaultCatalogProcessingEngine.ts | 27 +------ .../src/next/DefaultLocationStore.ts | 4 -- plugins/catalog-backend/src/next/types.ts | 5 +- 5 files changed, 5 insertions(+), 106 deletions(-) delete mode 100644 plugins/catalog-backend/src/next/DatabaseLocationProvider.ts diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 9afb537637..5f70ec60e1 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -33,7 +33,6 @@ "@backstage/backend-common": "^0.6.3", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.6", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", "@backstage/plugin-search-backend-node": "^0.1.3", @@ -61,8 +60,7 @@ "winston": "^3.2.1", "yaml": "^1.9.2", "yn": "^4.0.0", - "yup": "^0.29.3", - "zen-observable": "^0.8.15" + "yup": "^0.29.3" }, "devDependencies": { "@backstage/cli": "^0.6.9", diff --git a/plugins/catalog-backend/src/next/DatabaseLocationProvider.ts b/plugins/catalog-backend/src/next/DatabaseLocationProvider.ts deleted file mode 100644 index eaf5a78556..0000000000 --- a/plugins/catalog-backend/src/next/DatabaseLocationProvider.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2021 Spotify AB - * - * 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 { Observable } from '@backstage/core'; -import { ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; -import { EntityProvider, LocationStore, EntityMessage } from './types'; -import ObservableImpl from 'zen-observable'; -import { - locationSpecToLocationEntity, - locationSpecToMetadataName, -} from './util'; - -export class DatabaseLocationProvider implements EntityProvider { - private subscribers = new Set< - ZenObservable.SubscriptionObserver<EntityMessage> - >(); - - constructor(private readonly store: LocationStore) { - store.location$().subscribe({ - next: locations => { - if ('all' in locations) { - this.notify({ - all: locations.all.map(l => locationSpecToLocationEntity(l)), - }); - } else { - this.notify({ - added: locations.added.map(l => locationSpecToLocationEntity(l)), - removed: locations.removed.map(l => ({ - kind: 'Location', - namespace: ENTITY_DEFAULT_NAMESPACE, - name: locationSpecToMetadataName(l), - })), - }); - } - }, - }); - } - - private notify(message: EntityMessage) { - for (const subscriber of this.subscribers) { - subscriber.next(message); - } - } - - entityChange$(): Observable<EntityMessage> { - return new ObservableImpl(subscriber => { - this.store.listLocations().then(locations => { - subscriber.next({ - all: locations.map(l => locationSpecToLocationEntity(l)), - }); - this.subscribers.add(subscriber); - }); - return () => { - this.subscribers.delete(subscriber); - }; - }); - } -} diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 7f49bf832d..b71b2c1045 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -14,11 +14,9 @@ * limitations under the License. */ -import { Subscription } from '@backstage/core'; import { CatalogProcessingEngine, EntityProvider, - EntityMessage, EntityProviderConnection, EntityProviderMutation, ProcessingStateManager, @@ -40,7 +38,7 @@ class Connection implements EntityProviderConnection { async applyMutation(mutation: EntityProviderMutation): Promise<void> { if (mutation.type === 'full') { await this.config.stateManager.replaceProcessingItems({ - id: this.config.id, + sourceKey: this.config.id, type: 'full', items: mutation.entities, }); @@ -49,7 +47,7 @@ class Connection implements EntityProviderConnection { } await this.config.stateManager.replaceProcessingItems({ - id: this.config.id, + sourceKey: this.config.id, type: 'delta', added: mutation.added, removed: mutation.removed, @@ -120,25 +118,4 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async stop() { this.running = false; } - - private async onNext(id: string, message: EntityMessage) { - if ('all' in message) { - // TODO unhandled rejection - await this.stateManager.addProcessingItems({ - id, - type: 'provider', - entities: message.all, - }); - } - - if ('added' in message) { - await this.stateManager.addProcessingItems({ - id, - type: 'provider', - entities: message.added, - }); - - // TODO deletions of message.removed - } - } } diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index dff424b1a9..21206f0a7b 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -25,10 +25,6 @@ import { v4 as uuidv4 } from 'uuid'; import { locationSpecToLocationEntity } from './util'; import { ConflictError } from '@backstage/errors'; -export type LocationMessage = - | { all: Location[] } - | { added: Location[]; removed: Location[] }; - export class DefaultLocationStore implements LocationStore, EntityProvider { private _connection: EntityProviderConnection | undefined; diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index f8b4de1c41..a39ab9a8ff 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -16,7 +16,6 @@ import { Entity, - EntityName, LocationSpec, Location, EntityRelationSpec, @@ -116,12 +115,12 @@ export type ProcessingItem = { export type ReplaceProcessingItemsRequest = | { - id: string; + sourceKey: string; items: Entity[]; type: 'full'; } | { - id: string; + sourceKey: string; added: Entity[]; removed: Entity[]; type: 'delta'; From fd7cd5d44959a3bd1d356eca4837dfd419372eb4 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 13:56:32 +0200 Subject: [PATCH 216/262] Refactor deferredEntities processing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/DefaultLocationStore.ts | 8 + .../src/next/DefaultProcessingStateManager.ts | 39 ++- .../src/next/NextCatalogBuilder.ts | 1 - plugins/catalog-backend/src/next/Stitcher.ts | 4 +- .../DefaultProcessingDatabase.test.ts | 83 ++++-- .../database/DefaultProcessingDatabase.ts | 236 ++++++++++-------- .../src/next/database/types.ts | 7 +- 7 files changed, 222 insertions(+), 156 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index 21206f0a7b..40870cff7b 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -104,5 +104,13 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { async connect(connection: EntityProviderConnection): Promise<void> { this._connection = connection; + const locations = await this.db.locations(); + const entities = locations.map(location => { + return locationSpecToLocationEntity(location); + }); + await this.connection.applyMutation({ + type: 'full', + entities, + }); } } diff --git a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts index d2765c3101..0003b7a7cf 100644 --- a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts +++ b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts @@ -49,35 +49,28 @@ export class DefaultProcessingStateManager implements ProcessingStateManager { async addProcessingItems(request: AddProcessingItemRequest) { return this.db.transaction(async tx => { - await this.db.addUnprocessedEntities(tx, request); + // await this.db.addUnprocessedEntities(tx, request); }); } async getNextProcessingItem(): Promise<ProcessingItem> { - const entities = await new Promise<RefreshStateItem[]>(resolve => - this.popFromQueue(resolve), - ); - const { id, state, unprocessedEntity } = entities[0]; - return { - id, - entity: unprocessedEntity, - state, - }; - } - - async popFromQueue(resolve: (rows: RefreshStateItem[]) => void) { - const entities = await this.db.transaction(async tx => { - return this.db.getProcessableEntities(tx, { - processBatchSize: 1, + for (;;) { + const { items } = await this.db.transaction(async tx => { + return this.db.getProcessableEntities(tx, { + processBatchSize: 1, + }); }); - }); - // No entities require refresh, wait and try again. - if (!entities.items.length) { - setTimeout(() => this.popFromQueue(resolve), 1000); - return; + if (items.length) { + const { id, state, unprocessedEntity } = items[0]; + return { + id, + entity: unprocessedEntity, + state, + }; + } + + await new Promise<void>(resolve => setTimeout(resolve, 1000)); } - - resolve(entities.items); } } diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 1796847164..d720bd331a 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -67,7 +67,6 @@ import { LocationAnalyzer } from '../ingestion/types'; import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; import { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; -import { DatabaseLocationProvider } from '../next/DatabaseLocationProvider'; import { DefaultLocationStore } from './DefaultLocationStore'; import { DefaultProcessingStateManager } from './DefaultProcessingStateManager'; import { CatalogProcessingEngine } from '../next/types'; diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index 3e5e3ac24b..f53b7c6fad 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -76,8 +76,8 @@ export class Stitcher { const [reference_count_result] = await tx<DbRefreshStateReferences>( 'refresh_state_references', ) - .where({ target_entity_id: entity.metadata.uid }) - .count({ reference_count: 'target_entity_id' }); + .where({ target_entity_ref: entityRef }) + .count({ reference_count: 'target_entity_ref' }); if (Number(reference_count_result.reference_count) === 0) { this.logger.debug(`${entityRef} is orphan`); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index c4784c081d..14990a2a79 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -27,27 +27,26 @@ import * as uuid from 'uuid'; import { getVoidLogger } from '@backstage/backend-common'; describe('Default Processing Database', () => { - let db: Knex | undefined; - let processingDatabase: DefaultProcessingDatabase | undefined; - + let db: Knex; + let processingDatabase: DefaultProcessingDatabase; const logger = getVoidLogger(); beforeEach(async () => { db = await DatabaseManager.createTestDatabaseConnection(); await DatabaseManager.createDatabase(db); - processingDatabase = new DefaultProcessingDatabase(db!, logger); + processingDatabase = new DefaultProcessingDatabase(db, logger); }); describe('replaceUnprocessedEntities', () => { const insertRefRow = async (ref: DbRefreshStateReferencesRow) => { - return db!<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ).insert(ref); + return db<DbRefreshStateReferencesRow>('refresh_state_references').insert( + ref, + ); }; const insertRefreshStateRow = async (ref: DbRefreshStateRow) => { - await db!<DbRefreshStateRow>('refresh_state').insert(ref); + await db<DbRefreshStateRow>('refresh_state').insert(ref); }; const createLocations = async (entityRefs: string[]) => { @@ -101,8 +100,8 @@ describe('Default Processing Database', () => { target_entity_ref: 'location:default/root-2', }); - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'full', sourceKey: 'config', items: [ @@ -117,11 +116,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); @@ -205,8 +204,8 @@ describe('Default Processing Database', () => { target_entity_ref: 'location:default/root-2', }); - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'full', sourceKey: 'config', items: [ @@ -221,11 +220,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); @@ -296,8 +295,8 @@ describe('Default Processing Database', () => { }); it('should add new locations using the delta options', async () => { - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'delta', sourceKey: 'lols', removed: [], @@ -313,11 +312,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); @@ -336,6 +335,42 @@ describe('Default Processing Database', () => { ).toBeTruthy(); }); + it('should not remove locations that are referenced elsewhere', async () => { + /* + config-1 -> location:default/root + config-2 -> location:default/root + */ + await createLocations(['location:default/root']); + + await insertRefRow({ + source_key: 'config-1', + target_entity_ref: 'location:default/root', + }); + await insertRefRow({ + source_key: 'config-2', + target_entity_ref: 'location:default/root', + }); + + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'config-1', + items: [], + }); + }); + + const currentRefRowState = await db<DbRefreshStateReferencesRow>( + 'refresh_state_references', + ).select(); + + expect(currentRefRowState).toEqual({ + source_key: 'config-2', + target_entity_ref: 'location:default/root', + }); + + // TODO: assert that root wasn't removed + }); + it('should remove old locations using the delta options', async () => { await createLocations(['location:default/new-root']); @@ -344,8 +379,8 @@ describe('Default Processing Database', () => { target_entity_ref: 'location:default/new-root', }); - await processingDatabase!.transaction(async tx => { - await processingDatabase!.replaceUnprocessedEntities(tx, { + await processingDatabase.transaction(async tx => { + await processingDatabase.replaceUnprocessedEntities(tx, { type: 'delta', sourceKey: 'lols', added: [], @@ -361,11 +396,11 @@ describe('Default Processing Database', () => { }); }); - const currentRefreshState = await db!<DbRefreshStateRow>( + const currentRefreshState = await db<DbRefreshStateRow>( 'refresh_state', ).select(); - const currentRefRowState = await db!<DbRefreshStateReferencesRow>( + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index a80325d469..dc5e6036f5 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -26,10 +26,12 @@ import { UpdateProcessedEntityOptions, GetProcessableEntitiesResult, ReplaceUnprocessedEntitiesOptions, + RefreshStateItem, } from './types'; import type { Logger } from 'winston'; import { v4 as uuid } from 'uuid'; +import { JsonObject } from '@backstage/config'; export type DbRefreshStateRow = { entity_id: string; @@ -88,7 +90,6 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { errors, }) .where('entity_id', id); - if (refreshResult === 0) { throw new NotFoundError(`Processing state not found for ${id}`); } @@ -96,8 +97,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { // Schedule all deferred entities for future processing. await this.addUnprocessedEntities(tx, { entities: deferredEntities, - id, - type: 'entity', + entityRef: stringifyEntityRef(processedEntity), }); // Update fragments @@ -172,80 +172,104 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (toRemove.length) { // TODO(freben): Batch split, to not hit variable limits? /* - WITH RECURSIVE - -- All the refs that can be reached from each individual root - root_reach(id, entity_ref) AS ( - -- Start with all roots - SELECT id, target_entity_ref - FROM refresh_state_references - WHERE source_key IS NOT NULL - UNION - -- For each match, select all children - SELECT root_reach.id, target_entity_ref - FROM refresh_state_references, root_reach - WHERE source_entity_ref = root_reach.entity_ref - ) - -- Start out with our own matching row (see the WHERE that - -- matches on source_key and target_entity_ref below) - SELECT us.entity_ref - FROM refresh_state_references - -- Expand the entire tree that emanates from that row - JOIN root_reach AS us - ON us.id = refresh_state_references.id - -- Expand with all roots that target the same node but - -- aren't ourselves - LEFT OUTER JOIN root_reach AS them - ON them.entity_ref = us.entity_ref - AND them.id != us.id - -- Keep only the matches that had no other rooots - WHERE refresh_state_references.source_key = "R1" - AND refresh_state_references.target_entity_ref = "A" - AND them.id IS NULL; - */ + WITH RECURSIVE + -- All the nodes that can be reached downwards from our root + descendants(root_id, entity_ref) AS ( + SELECT id, target_entity_ref + FROM refresh_state_references + WHERE source_key = "R1" AND target_entity_ref = "A" + UNION + SELECT descendants.root_id, target_entity_ref + FROM descendants + JOIN refresh_state_references ON source_entity_ref = descendants.entity_ref + ), + -- All the nodes that can be reached upwards from the descendants + ancestors(root_id, via_entity_ref, to_entity_ref) AS ( + SELECT NULL, entity_ref, entity_ref + FROM descendants + UNION + SELECT + CASE WHEN source_key IS NOT NULL THEN id ELSE NULL END, + source_entity_ref, + ancestors.to_entity_ref + FROM ancestors + JOIN refresh_state_references ON target_entity_ref = ancestors.via_entity_ref + ) + -- Start out with all of the descendants + SELECT descendants.entity_ref + FROM descendants + -- Expand with all ancestors that point to those, but aren't the current root + LEFT OUTER JOIN ancestors + ON ancestors.to_entity_ref = descendants.entity_ref + AND ancestors.root_id IS NOT NULL + AND ancestors.root_id != descendants.root_id + -- Exclude all lines that had such a foreign ancestor + WHERE ancestors.root_id IS NULL; + */ const removedCount = await tx<DbRefreshStateRow>('refresh_state') .whereIn('entity_ref', function orphanedEntityRefs(orphans) { return ( orphans - // All the refs that can be reached from each individual root - .withRecursive('root_reach', function rootReach(outer) { - // Start with all roots + // All the nodes that can be reached downwards from our root + .withRecursive('descendants', function descendants(outer) { return outer - .select({ id: 'id', entity_ref: 'target_entity_ref' }) + .select({ root_id: 'id', entity_ref: 'target_entity_ref' }) .from('refresh_state_references') - .whereNotNull('source_key') - .union(function recurse(inner) { - return ( - inner - // For each match, select all children - .select({ - id: 'root_reach.id', - entity_ref: - 'refresh_state_references.target_entity_ref', - }) - .from('refresh_state_references') - .crossJoin('root_reach', { - 'root_reach.entity_ref': - 'refresh_state_references.source_entity_ref', - }) - ); + .where('source_key', options.sourceKey) + .whereIn('target_entity_ref', toRemove) + .union(function recursive(inner) { + return inner + .select({ + root_id: 'descendants.root_id', + entity_ref: + 'refresh_state_references.target_entity_ref', + }) + .from('descendants') + .join('refresh_state_references', { + 'descendants.entity_ref': + 'refresh_state_references.source_entity_ref', + }); }); }) - .select('us.entity_ref') - // Start out with our own matching row - .from('refresh_state_references') - .where('source_key', options.sourceKey) - .whereIn('target_entity_ref', toRemove) - // Expand the entire tree that emanates from that row - .leftJoin({ us: 'root_reach' }, function us() { - this.on('us.id', '=', 'refresh_state_references.id'); + // All the nodes that can be reached upwards from the descendants + .withRecursive('ancestors', function ancestors(outer) { + return outer + .select({ + root_id: tx.raw('NULL', []), + via_entity_ref: 'entity_ref', + to_entity_ref: 'entity_ref', + }) + .from('descendants') + .union(function recursive(inner) { + return inner + .select({ + root_id: tx.raw( + 'CASE WHEN source_key IS NOT NULL THEN id ELSE NULL END', + [], + ), + via_entity_ref: 'source_entity_ref', + to_entity_ref: 'ancestors.to_entity_ref', + }) + .from('ancestors') + .join('refresh_state_references', { + target_entity_ref: 'ancestors.via_entity_ref', + }); + }); }) - // Expand with all roots that target the same node but aren't ourselves - .leftOuterJoin({ them: 'root_reach' }, function them() { - this.on('them.entity_ref', '=', 'us.entity_ref'); - this.andOn('them.id', '!=', 'us.id'); + // Start out with all of the descendants + .select('descendants.entity_ref') + .from('descendants') + // Expand with all ancestors that point to those, but aren't the current root + .leftOuterJoin('ancestors', function keepaliveRoots() { + this.on( + 'ancestors.to_entity_ref', + '=', + 'descendants.entity_ref', + ); + this.andOnNotNull('ancestors.root_id'); + this.andOn('ancestors.root_id', '!=', 'descendants.root_id'); }) - // Keep only the matches that had no other rooots - .whereNull('them.id') + .whereNull('ancestors.root_id') ); }) .delete(); @@ -291,44 +315,45 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { options: AddUnprocessedEntitiesOptions, ): Promise<void> { const tx = txOpaque as Knex.Transaction; - const entityIds = new Array<string>(); - for (const entity of options.entities) { - const entityRef = stringifyEntityRef(entity); - await tx<DbRefreshStateRow>('refresh_state') - .insert({ + const stateRows = options.entities.map( + entity => + ({ entity_id: uuid(), - entity_ref: entityRef, + entity_ref: stringifyEntityRef(entity), unprocessed_entity: JSON.stringify(entity), errors: '', next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), - }) + } as Knex.DbRecord<DbRefreshStateRow>), + ); + const stateReferenceRows = stateRows.map( + stateRow => + ({ + source_entity_ref: options.entityRef, + target_entity_ref: stateRow.entity_ref, + } as Knex.DbRecord<DbRefreshStateReferencesRow>), + ); + + // Upsert all of the unprocessed entities into the refresh_state table, by + // their entity ref. + // TODO(freben): Can this be batched somehow? + for (const row of stateRows) { + await tx<DbRefreshStateRow>('refresh_state') + .insert(row) .onConflict('entity_ref') .merge(['unprocessed_entity', 'last_discovery_at']); - - const [{ entity_id: entityId }] = await tx<DbRefreshStateRow>( - 'refresh_state', - ).where({ entity_ref: entityRef }); - entityIds.push(entityId); } - const key = - options.type === 'provider' - ? { source_special_key: options.id } - : { source_entity_id: options.id }; - // copied from update refs + // Replace all references for the originating entity before creating new ones await tx<DbRefreshStateReferencesRow>('refresh_state_references') - .where(key) + .where({ source_entity_ref: options.entityRef }) .delete(); - - const referenceRows: DbRefreshStateReferencesRow[] = entityIds.map( - entityId => ({ - ...key, - target_entity_id: entityId, - }), + await tx.batchInsert( + 'refresh_state_references', + stateReferenceRows, + BATCH_SIZE, ); - await tx.batchInsert('refresh_state_references', referenceRows, BATCH_SIZE); } async getProcessableEntities( @@ -356,16 +381,23 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { }); return { - items: items.map(i => ({ - id: i.entity_id, - entityRef: i.entity_ref, - unprocessedEntity: JSON.parse(i.unprocessed_entity) as Entity, - processedEntity: JSON.parse(i.processed_entity) as Entity, - nextUpdateAt: i.next_update_at, - lastDiscoveryAt: i.last_discovery_at, - state: JSON.parse(i.cache), - errors: i.errors, - })), + items: items.map( + i => + ({ + id: i.entity_id, + entityRef: i.entity_ref, + unprocessedEntity: JSON.parse(i.unprocessed_entity) as Entity, + processedEntity: i.processed_entity + ? (JSON.parse(i.processed_entity) as Entity) + : undefined, + nextUpdateAt: i.next_update_at, + lastDiscoveryAt: i.last_discovery_at, + state: i.cache + ? JSON.parse(i.cache) + : new Map<string, JsonObject>(), + errors: i.errors, + } as RefreshStateItem), + ), }; } diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index b926676887..d7a1dcd20b 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -19,8 +19,7 @@ import { JsonObject } from '@backstage/config'; import { Transaction } from '../../database/types'; export type AddUnprocessedEntitiesOptions = { - type: 'entity' | 'provider'; - id: string; + entityRef: string; entities: Entity[]; }; @@ -39,11 +38,11 @@ export type RefreshStateItem = { id: string; entityRef: string; unprocessedEntity: Entity; - processedEntity: Entity; + processedEntity?: Entity; nextUpdateAt: string; lastDiscoveryAt: string; // remove? state: Map<string, JsonObject>; - errors: string; + errors?: string; }; export type GetProcessableEntitiesResult = { From 19b07a6f67b3c5ba58d11258be9db4a6c2596326 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 14:02:41 +0200 Subject: [PATCH 217/262] Remove addProcessingItems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/src/next/Stitcher.ts | 4 ++-- plugins/catalog-backend/src/next/types.ts | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index f53b7c6fad..57f5ae9167 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -19,7 +19,7 @@ import { Logger } from 'winston'; import { Transaction } from '../database'; import { ConflictError } from '@backstage/errors'; import { - DbRefreshStateReferences, + DbRefreshStateReferencesRow, DbRefreshStateRow, DbRelationsRow, } from './database/DefaultProcessingDatabase'; @@ -73,7 +73,7 @@ export class Stitcher { return; } - const [reference_count_result] = await tx<DbRefreshStateReferences>( + const [reference_count_result] = await tx<DbRefreshStateReferencesRow>( 'refresh_state_references', ) .where({ target_entity_ref: entityRef }) diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index a39ab9a8ff..ef3bab797b 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -101,12 +101,6 @@ export type ProcessingItemResult = { deferredEntities: Entity[]; }; -export type AddProcessingItemRequest = { - type: 'entity' | 'provider'; - id: string; - entities: Entity[]; -}; - export type ProcessingItem = { id: string; entity: Entity; @@ -128,6 +122,5 @@ export type ReplaceProcessingItemsRequest = export interface ProcessingStateManager { setProcessingItemResult(result: ProcessingItemResult): Promise<void>; getNextProcessingItem(): Promise<ProcessingItem>; - addProcessingItems(request: AddProcessingItemRequest): Promise<void>; replaceProcessingItems(request: ReplaceProcessingItemsRequest): Promise<void>; } From e0c39cd7e308a20f5e91b4cb04283589c5bc2251 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 14:12:57 +0200 Subject: [PATCH 218/262] Add moar tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../DefaultProcessingDatabase.test.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index 14990a2a79..f67b8603db 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -359,16 +359,26 @@ describe('Default Processing Database', () => { }); }); + const currentRefreshState = await db<DbRefreshStateRow>( + 'refresh_state', + ).select(); + const currentRefRowState = await db<DbRefreshStateReferencesRow>( 'refresh_state_references', ).select(); - expect(currentRefRowState).toEqual({ - source_key: 'config-2', - target_entity_ref: 'location:default/root', - }); + expect(currentRefRowState).toEqual([ + expect.objectContaining({ + source_key: 'config-2', + target_entity_ref: 'location:default/root', + }), + ]); - // TODO: assert that root wasn't removed + expect(currentRefreshState).toEqual([ + expect.objectContaining({ + entity_ref: 'location:default/root', + }), + ]); }); it('should remove old locations using the delta options', async () => { From ac48004b7d8f60e3389ca30890a4abdc5d00493e Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 14:15:29 +0200 Subject: [PATCH 219/262] Remove dead code Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/DefaultProcessingStateManager.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts index 0003b7a7cf..9c1d20ae9c 100644 --- a/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts +++ b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts @@ -14,9 +14,8 @@ * limitations under the License. */ -import { ProcessingDatabase, RefreshStateItem } from './database/types'; +import { ProcessingDatabase } from './database/types'; import { - AddProcessingItemRequest, ProcessingItem, ProcessingItemResult, ProcessingStateManager, @@ -47,12 +46,6 @@ export class DefaultProcessingStateManager implements ProcessingStateManager { }); } - async addProcessingItems(request: AddProcessingItemRequest) { - return this.db.transaction(async tx => { - // await this.db.addUnprocessedEntities(tx, request); - }); - } - async getNextProcessingItem(): Promise<ProcessingItem> { for (;;) { const { items } = await this.db.transaction(async tx => { From c58f8fd1477b6ca536d54ce6ef3aae2b92cd944a Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 15:38:31 +0200 Subject: [PATCH 220/262] Add all migration files to migrationsv2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../migrationsv2/20200511113813_init.js | 133 ++++++++++ ...0200520140700_location_update_log_table.js | 43 ++++ ...7114117_location_update_log_latest_view.js | 45 ++++ .../migrationsv2/20200702153613_entities.js | 236 ++++++++++++++++++ ..._location_update_log_latest_deduplicate.js | 44 ++++ ...904_location_update_log_duplication_fix.js | 87 +++++++ .../20200807120600_entitySearch.js | 41 +++ .../20200809202832_add_bootstrap_location.js | 42 ++++ .../20200923104503_case_insensitivity.js | 32 +++ .../20201005122705_add_entity_full_name.js | 60 +++++ .../20201006130744_entity_data_column.js | 66 +++++ ...6203131_entity_remove_redundant_columns.js | 50 ++++ .../20201007201501_index_entity_search.js | 37 +++ .../20201019130742_add_relations_table.js | 54 ++++ .../20201123205611_relations_table_uniq.js | 93 +++++++ .../migrationsv2/20201210185851_fk_index.js | 45 ++++ .../20201230103504_update_log_varchar.js | 73 ++++++ .../20210209121210_locations_fk_index.js | 45 ++++ .../src/next/database/DatabaseManager.ts | 15 -- 19 files changed, 1226 insertions(+), 15 deletions(-) create mode 100644 plugins/catalog-backend/migrationsv2/20200511113813_init.js create mode 100644 plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js create mode 100644 plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js create mode 100644 plugins/catalog-backend/migrationsv2/20200702153613_entities.js create mode 100644 plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js create mode 100644 plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js create mode 100644 plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js create mode 100644 plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js create mode 100644 plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js create mode 100644 plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js create mode 100644 plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js create mode 100644 plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js create mode 100644 plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js create mode 100644 plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js create mode 100644 plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js create mode 100644 plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js create mode 100644 plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js create mode 100644 plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js diff --git a/plugins/catalog-backend/migrationsv2/20200511113813_init.js b/plugins/catalog-backend/migrationsv2/20200511113813_init.js new file mode 100644 index 0000000000..7f3d75e35c --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200511113813_init.js @@ -0,0 +1,133 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + return ( + knex.schema + // + // locations + // + .createTable('locations', table => { + table.comment( + 'Registered locations that shall be contiuously scanned for catalog item updates', + ); + table + .uuid('id') + .primary() + .notNullable() + .comment('Auto-generated ID of the location'); + table.string('type').notNullable().comment('The type of location'); + table + .string('target') + .notNullable() + .comment('The actual target of the location'); + }) + // + // entities + // + .createTable('entities', table => { + table.comment('All entities currently stored in the catalog'); + table.uuid('id').primary().comment('Auto-generated ID of the entity'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .nullable() + .comment('The location that originated the entity'); + table + .string('etag') + .notNullable() + .comment( + 'An opaque string that changes for each update operation to any part of the entity, including metadata.', + ); + table + .string('generation') + .notNullable() + .unsigned() + .comment( + 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', + ); + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table + .string('kind') + .notNullable() + .comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + table + .string('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .string('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + }) + .alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); + }) + // + // entities_search + // + .createTable('entities_search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + }) + ); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + return knex.schema + .dropTable('entities_search') + .alterTable('entities', table => { + table.dropUnique([], 'entities_unique_name'); + }) + .dropTable('entities') + .dropTable('locations'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js b/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js new file mode 100644 index 0000000000..d8093fc9b4 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200520140700_location_update_log_table.js @@ -0,0 +1,43 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + return knex.schema.createTable('location_update_log', table => { + table.uuid('id').primary(); + table.enum('status', ['success', 'fail']).notNullable(); + table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); + table.string('message'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .onUpdate('CASCADE') + .onDelete('CASCADE'); + table.string('entity_name').nullable(); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + return knex.schema.dropTableIfExists('location_update_log'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js b/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js new file mode 100644 index 0000000000..a0f0f33a65 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200527114117_location_update_log_latest_view.js @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Get list sorted by created_at timestamp in descending order + // Grouped by location_id + return knex.schema.raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(created_at) AS MAXDATE + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.created_at = t2.MAXDATE + ORDER BY created_at DESC; + `); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + return knex.schema.raw(`DROP VIEW location_update_log_latest;`); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200702153613_entities.js b/plugins/catalog-backend/migrationsv2/20200702153613_entities.js new file mode 100644 index 0000000000..0f1c204f9b --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200702153613_entities.js @@ -0,0 +1,236 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // SQLite does not support FK and PK + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.dropForeign(['entity_id']); + }); + await knex.schema.alterTable('entities', table => { + table.dropPrimary('entities_pkey'); + }); + } + await knex.schema.alterTable('entities', table => { + table.dropUnique([], 'entities_unique_name'); + }); + // Setup temporary tables + await knex.schema.renameTable('entities_search', 'tmp_entities_search'); + await knex.schema.renameTable('entities', 'tmp_entities'); + + // + // entities + // + await knex.schema + .createTable('entities', table => { + table.comment('All entities currently stored in the catalog'); + table.uuid('id').primary().comment('Auto-generated ID of the entity'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .nullable() + .comment('The location that originated the entity'); + table + .string('etag') + .notNullable() + .comment( + 'An opaque string that changes for each update operation to any part of the entity, including metadata.', + ); + table + .string('generation') + .notNullable() + .unsigned() + .comment( + 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', + ); + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table + .string('kind') + .notNullable() + .comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + table + .text('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .text('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + }) + .alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); + }); + + await knex.schema.raw(`INSERT INTO entities SELECT * FROM tmp_entities`); + + // + // entities_search + // + await knex.schema.createTable('entities_search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + }); + await knex.schema.raw( + `INSERT INTO entities_search SELECT * FROM tmp_entities_search`, + ); + + // Clean up + await knex.schema.dropTable('tmp_entities'); + return knex.schema.dropTable('tmp_entities_search'); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + // SQLite does not support FK and PK + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.dropForeign(['entity_id']); + }); + await knex.schema.alterTable('entities', table => { + table.dropPrimary('entities_pkey'); + }); + } + await knex.schema.alterTable('entities', table => { + table.dropUnique([], 'entities_unique_name'); + }); + + // Setup temporary tables + await knex.schema.renameTable('entities_search', 'tmp_entities_search'); + await knex.schema.renameTable('entities', 'tmp_entities'); + + // + // entities + // + await knex.schema + .createTable('entities', table => { + table.comment('All entities currently stored in the catalog'); + table.uuid('id').primary().comment('Auto-generated ID of the entity'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .nullable() + .comment('The location that originated the entity'); + table + .string('etag') + .notNullable() + .comment( + 'An opaque string that changes for each update operation to any part of the entity, including metadata.', + ); + table + .string('generation') + .notNullable() + .unsigned() + .comment( + 'A positive nonzero number that indicates the current generation of data for this entity; the value is incremented each time the spec changes.', + ); + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table + .string('kind') + .notNullable() + .comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + table + .string('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .string('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + }) + .alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['kind', 'name', 'namespace'], 'entities_unique_name'); + }); + + await knex.schema.raw(`INSERT INTO entities SELECT * FROM tmp_entities`); + + // + // entities_search + // + await knex.schema.createTable('entities_search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + }); + await knex.schema.raw( + `INSERT INTO entities_search SELECT * FROM tmp_entities_search`, + ); + + // Clean up + await knex.schema.dropTable('tmp_entities'); + return knex.schema.dropTable('tmp_entities_search'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js b/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js new file mode 100644 index 0000000000..87b41a80fc --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200721115244_location_update_log_latest_deduplicate.js @@ -0,0 +1,44 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = function up(knex) { + return knex.schema.raw(`DROP VIEW location_update_log_latest;`).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(created_at) AS MAXDATE + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.created_at = t2.MAXDATE + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; +`); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = function down(knex) { + knex.schema.raw(`DROP VIEW location_update_log_latest;`); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js b/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js new file mode 100644 index 0000000000..de2b194cff --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200805163904_location_update_log_duplication_fix.js @@ -0,0 +1,87 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = function up(knex) { + return knex.schema + .raw('DROP VIEW location_update_log_latest;') + .dropTable('location_update_log') + .createTable('location_update_log', table => { + table.bigIncrements('id').primary(); // instead of uuid, so we can MAX it + table.enum('status', ['success', 'fail']).notNullable(); + table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); + table.string('message'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .onUpdate('CASCADE') + .onDelete('CASCADE'); + table.string('entity_name').nullable(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(id) AS MAXID + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.id = t2.MAXID + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = function down(knex) { + return knex.schema + .raw('DROP VIEW location_update_log_latest;') + .dropTable('location_update_log') + .createTable('location_update_log', table => { + table.uuid('id').primary(); + table.enum('status', ['success', 'fail']).notNullable(); + table.dateTime('created_at').defaultTo(knex.fn.now()).notNullable(); + table.string('message'); + table + .uuid('location_id') + .references('id') + .inTable('locations') + .onUpdate('CASCADE') + .onDelete('CASCADE'); + table.string('entity_name').nullable(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(created_at) AS MAXDATE + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.created_at = t2.MAXDATE + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js b/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js new file mode 100644 index 0000000000..45226e53b4 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200807120600_entitySearch.js @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Sqlite does not support alter column. + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.text('value').nullable().alter(); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + // Sqlite does not support alter column. + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_search', table => { + table.string('value').nullable().alter(); + }); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js b/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js new file mode 100644 index 0000000000..a90813fe85 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200809202832_add_bootstrap_location.js @@ -0,0 +1,42 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Adds a single 'bootstrap' location that can be used to trigger work in processors. + // This is primarily here to fulfill foreign key constraints. + await knex('locations').insert({ + id: require('uuid').v4(), + type: 'bootstrap', + target: 'bootstrap', + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex('locations') + .where({ + type: 'bootstrap', + target: 'bootstrap', + }) + .del(); +}; diff --git a/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js b/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js new file mode 100644 index 0000000000..ea5ba9e58d --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20200923104503_case_insensitivity.js @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex('entities') + .where({ namespace: null }) + .update({ namespace: 'default' }); + await knex('entities_search').update({ + key: knex.raw('LOWER(key)'), + value: knex.raw('LOWER(value)'), + }); +}; + +exports.down = async function down() {}; diff --git a/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js b/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js new file mode 100644 index 0000000000..aae1861658 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201005122705_add_entity_full_name.js @@ -0,0 +1,60 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities', table => { + table.text('full_name').nullable(); + }); + + await knex('entities').update({ + full_name: knex.raw( + "LOWER(kind) || ':' || LOWER(COALESCE(namespace, 'default')) || '/' || LOWER(name)", + ), + }); + + // SQLite does not support alter column + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.text('full_name').notNullable().alter(); + }); + } + + await knex.schema.alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.unique(['full_name'], 'entities_unique_full_name'); + table.dropUnique([], 'entities_unique_name'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities', table => { + // https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta + table.dropUnique([], 'entities_unique_full_name'); + table.unique(['kind', 'namespace', 'name'], 'entities_unique_name'); + }); + + await knex.schema.alterTable('entities_search', table => { + table.dropColumn('full_name'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js b/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js new file mode 100644 index 0000000000..a8964efbf6 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201006130744_entity_data_column.js @@ -0,0 +1,66 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities', table => { + table + .text('data') + .nullable() + .comment('The entire JSON data blob of the entity'); + }); + + await knex('entities').update({ + // apiVersion and kind should not contain any JSON unsafe chars, and both + // metadata and spec are already valid serialized JSON + data: knex.raw( + `'{"apiVersion":"' || api_version || '","kind":"' || kind || '","metadata":' || metadata || COALESCE(',"spec":' || spec, '') || '}'`, + ), + }); + + await knex.schema.alterTable('entities', table => { + table.dropColumn('metadata'); + table.dropColumn('spec'); + }); + + // SQLite does not support ALTER COLUMN. + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.text('data').notNullable().alter(); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities', table => { + table + .text('metadata') + .notNullable() + .comment('The entire metadata JSON blob of the entity'); + table + .text('spec') + .nullable() + .comment('The entire spec JSON blob of the entity'); + table.dropColumn('data'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js b/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js new file mode 100644 index 0000000000..f40df5f73e --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201006203131_entity_remove_redundant_columns.js @@ -0,0 +1,50 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities', table => { + table.dropColumn('api_version'); + table.dropColumn('kind'); + table.dropColumn('name'); + table.dropColumn('namespace'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities', table => { + table + .string('api_version') + .notNullable() + .comment('The apiVersion field of the entity'); + table.string('kind').notNullable().comment('The kind field of the entity'); + table + .string('name') + .nullable() + .comment('The metadata.name field of the entity'); + table + .string('namespace') + .nullable() + .comment('The metadata.namespace field of the entity'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js b/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js new file mode 100644 index 0000000000..77bf0529eb --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201007201501_index_entity_search.js @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('entities_search', table => { + table.index(['key'], 'entities_search_key'); + table.index(['value'], 'entities_search_value'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entities_search', table => { + table.dropIndex('', 'entities_search_key'); + table.dropIndex('', 'entities_search_value'); + }); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js b/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js new file mode 100644 index 0000000000..85e729f814 --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201019130742_add_relations_table.js @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.createTable('entities_relations', table => { + table.comment('All relations between entities in the catalog'); + table + .uuid('originating_entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .notNullable() + .comment('The entity that provided the relation'); + table + .string('source_full_name') + .notNullable() + .comment('The full name of the source entity of the relation'); + table + .string('type') + .notNullable() + .comment('The type of the relation between the entities'); + table + .string('target_full_name') + .notNullable() + .comment('The full name of the target entity of the relation'); + + table.primary(['source_full_name', 'type', 'target_full_name']); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.dropTable('entities_relations'); +}; diff --git a/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js b/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js new file mode 100644 index 0000000000..9e8198b5eb --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201123205611_relations_table_uniq.js @@ -0,0 +1,93 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client === 'sqlite3') { + // sqlite doesn't support dropPrimary so we recreate it properly instead + await knex.schema.dropTable('entities_relations'); + await knex.schema.createTable('entities_relations', table => { + table.comment('All relations between entities in the catalog'); + table + .uuid('originating_entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .notNullable() + .comment('The entity that provided the relation'); + table + .string('source_full_name') + .notNullable() + .comment('The full name of the source entity of the relation'); + table + .string('type') + .notNullable() + .comment('The type of the relation between the entities'); + table + .string('target_full_name') + .notNullable() + .comment('The full name of the target entity of the relation'); + table.index('source_full_name', 'source_full_name_idx'); + }); + } else { + await knex.schema.alterTable('entities_relations', table => { + table.dropPrimary(); + table.index('source_full_name', 'source_full_name_idx'); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client === 'sqlite3') { + await knex.schema.dropTable('entities_relations'); + await knex.schema.createTable('entities_relations', table => { + table.comment('All relations between entities in the catalog'); + table + .uuid('originating_entity_id') + .references('id') + .inTable('entities') + .onDelete('CASCADE') + .notNullable() + .comment('The entity that provided the relation'); + table + .string('source_full_name') + .notNullable() + .comment('The full name of the source entity of the relation'); + table + .string('type') + .notNullable() + .comment('The type of the relation between the entities'); + table + .string('target_full_name') + .notNullable() + .comment('The full name of the target entity of the relation'); + + table.primary(['source_full_name', 'type', 'target_full_name']); + }); + } else { + await knex.schema.alterTable('entities_relations', table => { + table.dropIndex([], 'source_full_name_idx'); + table.primary(['source_full_name', 'type', 'target_full_name']); + }); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js b/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js new file mode 100644 index 0000000000..abb26cd5fc --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201210185851_fk_index.js @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_relations', table => { + table.index('originating_entity_id', 'originating_entity_id_idx'); + }); + await knex.schema.alterTable('entities_search', table => { + table.index('entity_id', 'entity_id_idx'); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities_relations', table => { + table.dropIndex([], 'originating_entity_id_idx'); + }); + await knex.schema.alterTable('entities_relations', table => { + table.dropIndex([], 'entity_id_idx'); + }); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js b/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js new file mode 100644 index 0000000000..d924b0414a --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20201230103504_update_log_varchar.js @@ -0,0 +1,73 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client !== 'sqlite3') { + // We actually just want to widen columns, but can't do that while a + // view is dependent on them - so we just reconstruct it exactly as it was + await knex.schema + .raw('DROP VIEW location_update_log_latest;') + .alterTable('location_update_log', table => { + table.text('message').alter(); + table.text('entity_name').nullable().alter(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(id) AS MAXID + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.id = t2.MAXID + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema + .raw('DROP VIEW location_update_log_latest;') + .alterTable('location_update_log', table => { + table.string('message').alter(); + table.string('entity_name').nullable().alter(); + }).raw(` + CREATE VIEW location_update_log_latest AS + SELECT t1.* FROM location_update_log t1 + JOIN + ( + SELECT location_id, MAX(id) AS MAXID + FROM location_update_log + GROUP BY location_id + ) t2 + ON t1.location_id = t2.location_id + AND t1.id = t2.MAXID + GROUP BY t1.location_id, t1.id + ORDER BY created_at DESC; + `); + } +}; diff --git a/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js b/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js new file mode 100644 index 0000000000..ccfb1faffb --- /dev/null +++ b/plugins/catalog-backend/migrationsv2/20210209121210_locations_fk_index.js @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.index('location_id', 'entity_location_id_idx'); + }); + await knex.schema.alterTable('location_update_log', table => { + table.index('location_id', 'update_log_location_id_idx'); + }); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + if (knex.client.config.client !== 'sqlite3') { + await knex.schema.alterTable('entities', table => { + table.dropIndex([], 'entity_location_id_idx'); + }); + await knex.schema.alterTable('location_update_log', table => { + table.dropIndex([], 'update_log_location_id_idx'); + }); + } +}; diff --git a/plugins/catalog-backend/src/next/database/DatabaseManager.ts b/plugins/catalog-backend/src/next/database/DatabaseManager.ts index 4c9e45950f..f660f73ecb 100644 --- a/plugins/catalog-backend/src/next/database/DatabaseManager.ts +++ b/plugins/catalog-backend/src/next/database/DatabaseManager.ts @@ -20,7 +20,6 @@ import { v4 as uuidv4 } from 'uuid'; import { Logger } from 'winston'; import { CommonDatabase } from '../../database/CommonDatabase'; import { Database } from '../../database/types'; -import fs from 'fs-extra'; export type CreateDatabaseOptions = { logger: Logger; @@ -35,16 +34,10 @@ export class DatabaseManager { knex: Knex, options: Partial<CreateDatabaseOptions> = {}, ): Promise<Database> { - const allMigrations = resolvePackagePath( - '@backstage/plugin-catalog-backend', - 'migrations', - ); - const migrationsDir = resolvePackagePath( '@backstage/plugin-catalog-backend', 'migrationsv2', ); - await fs.copy(allMigrations, migrationsDir); await knex.migrate.latest({ directory: migrationsDir, @@ -79,14 +72,6 @@ export class DatabaseManager { public static async createTestDatabaseConnection(): Promise<Knex> { const config: Knex.Config<any> = { - /* - client: 'pg', - connection: { - host: 'localhost', - user: 'postgres', - password: 'postgres', - }, - */ client: 'sqlite3', connection: ':memory:', useNullAsDefault: true, From aad89f55460c1d9f96165d677e188edd7d304daf Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 15:43:22 +0200 Subject: [PATCH 221/262] Add configLocationProvider and provider identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw <freben@users.noreply.github.com> Co-authored-by: Ben Lambert <ben@blam.sh> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/ConfigLocationProvider.ts | 49 +++++++++++++++++++ .../next/DefaultCatalogProcessingEngine.ts | 9 ++-- .../src/next/DefaultLocationStore.ts | 4 ++ .../src/next/NextCatalogBuilder.ts | 7 +-- plugins/catalog-backend/src/next/types.ts | 1 + 5 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 plugins/catalog-backend/src/next/ConfigLocationProvider.ts diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts new file mode 100644 index 0000000000..5b93fcfd98 --- /dev/null +++ b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { EntityProviderConnection, EntityProvider } from './types'; +import path from 'path'; +import { Config } from '@backstage/config'; +import { locationSpecToLocationEntity } from './util'; + +export class ConfigLocationProvider implements EntityProvider { + private connection: EntityProviderConnection | undefined; + + constructor(private readonly config: Config) {} + + getProviderName(): string { + return 'ConfigLocationProvider'; + } + + async connect(connection: EntityProviderConnection): Promise<void> { + this.connection = connection; + + const locationConfigs = + this.config.getOptionalConfigArray('catalog.locations') ?? []; + + const entities = locationConfigs.map(location => + locationSpecToLocationEntity({ + type: location.getString('type'), + target: path.resolve(location.getString('target')), + }), + ); + + await this.connection.applyMutation({ + type: 'full', + entities, + }); + } +} diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index b71b2c1045..1934b0aea7 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -68,9 +68,12 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async start() { for (const provider of this.entityProviders) { - // TODO: this ID should be some form of identifier for the EntityProvider - const id = 'databaseProvider'; - provider.connect(new Connection({ stateManager: this.stateManager, id })); + provider.connect( + new Connection({ + stateManager: this.stateManager, + id: provider.getProviderName(), + }), + ); } this.running = true; diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index 40870cff7b..a56e5d1585 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -30,6 +30,10 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { constructor(private readonly db: Database) {} + getProviderName(): string { + return 'DefaultLocationStore'; + } + createLocation(spec: LocationSpec): Promise<Location> { return this.db.transaction(async tx => { // TODO: id should really be type and target combined and not a uuid. diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index d720bd331a..0699a13f58 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -50,6 +50,7 @@ import { GithubDiscoveryProcessor, GithubOrgReaderProcessor, LdapOrgReaderProcessor, + LocationEntityProcessor, MicrosoftGraphOrgReaderProcessor, PlaceholderProcessor, PlaceholderResolver, @@ -73,6 +74,7 @@ import { CatalogProcessingEngine } from '../next/types'; import { NextEntitiesCatalog } from './NextEntitiesCatalog'; import { Stitcher } from './Stitcher'; import { CommonDatabase } from '../database/CommonDatabase'; +import { ConfigLocationProvider } from './ConfigLocationProvider'; export type CatalogEnvironment = { logger: Logger; @@ -272,9 +274,10 @@ export class NextCatalogBuilder { const locationStore = new DefaultLocationStore(db); const stitcher = new Stitcher(dbClient, logger); + const configLocationProvider = new ConfigLocationProvider(config); const processingEngine = new DefaultCatalogProcessingEngine( logger, - [locationStore], // entityproviders + [locationStore, configLocationProvider], stateManager, orchestrator, stitcher, @@ -322,7 +325,6 @@ export class NextCatalogBuilder { // These are always there no matter what const processors: CatalogProcessor[] = [ - StaticLocationProcessor.fromConfig(config), new PlaceholderProcessor({ resolvers: placeholderResolvers, reader }), new BuiltinKindsEntityProcessor(), ]; @@ -338,7 +340,6 @@ export class NextCatalogBuilder { MicrosoftGraphOrgReaderProcessor.fromConfig(config, { logger }), new UrlReaderProcessor({ reader, logger }), CodeOwnersProcessor.fromConfig(config, { logger, reader }), - // new LocationEntityProcessor({ integrations }), new AnnotateLocationEntityProcessor({ integrations }), ); } diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index ef3bab797b..e0616fb336 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -65,6 +65,7 @@ export interface EntityProviderConnection { } export interface EntityProvider { + getProviderName(): string; connect(connection: EntityProviderConnection): Promise<void>; } From b7200a4b70334521fd391e58c4f75f33e3339e13 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Mon, 26 Apr 2021 16:53:44 +0200 Subject: [PATCH 222/262] chore: remove unused imports Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/src/next/NextCatalogBuilder.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 0699a13f58..24b763a098 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -50,11 +50,9 @@ import { GithubDiscoveryProcessor, GithubOrgReaderProcessor, LdapOrgReaderProcessor, - LocationEntityProcessor, MicrosoftGraphOrgReaderProcessor, PlaceholderProcessor, PlaceholderResolver, - StaticLocationProcessor, UrlReaderProcessor, } from '../ingestion'; import { RepoLocationAnalyzer } from '../ingestion/LocationAnalyzer'; From 72becbd2cc5fa95246da21b234c4f916e2a8cb9b Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 14:16:49 +0200 Subject: [PATCH 223/262] catalog-backend: Add ConfigLocationProvider tests Co-authored-by: Ben Lambert <ben@blam.sh> Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../src/next/ConfigLocationProvider.test.ts | 67 +++++++++++++++++++ .../src/next/ConfigLocationProvider.ts | 14 ++-- 2 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts b/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts new file mode 100644 index 0000000000..9aaba13c48 --- /dev/null +++ b/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts @@ -0,0 +1,67 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { ConfigLocationProvider } from './ConfigLocationProvider'; +import { EntityProviderConnection } from './types'; +import { ConfigReader } from '@backstage/config'; +import { resolvePackagePath } from '@backstage/backend-common'; +import path from 'path'; + +describe('Config Location Provider', () => { + it('should apply mutation with the correct paths in the config', async () => { + const mockConfig = new ConfigReader({ + catalog: { + locations: [ + { type: 'file', target: './lols.yaml' }, + { type: 'url', target: 'https://github.com/backstage/backstage' }, + ], + }, + }); + + const mockConnection = ({ + applyMutation: jest.fn(), + } as unknown) as EntityProviderConnection; + const locationProvider = new ConfigLocationProvider(mockConfig); + + await locationProvider.connect(mockConnection); + + expect(mockConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: path.join( + resolvePackagePath('@backstage/plugin-catalog-backend'), + './lols.yaml', + ), + type: 'file', + }, + }), + ]), + }); + expect(mockConnection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: 'https://github.com/backstage/backstage', + type: 'url', + }, + }), + ]), + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts index 5b93fcfd98..8a65487df1 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationProvider.ts @@ -34,12 +34,14 @@ export class ConfigLocationProvider implements EntityProvider { const locationConfigs = this.config.getOptionalConfigArray('catalog.locations') ?? []; - const entities = locationConfigs.map(location => - locationSpecToLocationEntity({ - type: location.getString('type'), - target: path.resolve(location.getString('target')), - }), - ); + const entities = locationConfigs.map(location => { + const type = location.getString('type'); + const target = location.getString('target'); + return locationSpecToLocationEntity({ + type, + target: type === 'file' ? path.resolve(target) : target, + }); + }); await this.connection.applyMutation({ type: 'full', From bbf0878afc247917a82121328b01102fbd87a871 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 18:28:55 +0200 Subject: [PATCH 224/262] WIP tests for DefaultProcessingDatabase Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../DefaultProcessingDatabase.test.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index f67b8603db..a5c1e56cff 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -429,4 +429,66 @@ describe('Default Processing Database', () => { ).toBeFalsy(); }); }); + + describe('updateProcessedEntity', () => { + it('should throw if the entity does not exist', async () => { + await processingDatabase.transaction(async tx => { + await expect( + processingDatabase.updateProcessedEntity(tx, { + id: '9', + processedEntity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + deferredEntities: [], + relations: [], + }), + ).rejects.toThrow('Processing state not found for 9'); + }); + }); + + it('should update a processed entity', async () => { + await db<DbRefreshStateRow>('refresh_state').insert({ + entity_id: '123', + entity_ref: 'Component:default/wacka', + unprocessed_entity: '', + errors: '', + next_update_at: 'now()', + last_discovery_at: 'now()', + }); + + const deferredEntity = { + apiVersion: '1.0.0', + metadata: { + name: 'deferred', + }, + kind: 'Location', + } as Entity; + + await processingDatabase.transaction(async tx => { + await processingDatabase.updateProcessedEntity(tx, { + id: '123', + processedEntity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + deferredEntities: [deferredEntity], + relations: [], + }); + }); + + console.log( + await db<DbRefreshStateRow>('refresh_state') + .where({ entity_ref: 'deferred' }) + .select(), + ); + expect(1).toBeDefined(); + }); + }); }); From c6af78b93b0bc09c19f5d87d23a764eb01f7e7c4 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 18:30:00 +0200 Subject: [PATCH 225/262] Combine stitiching queries Signed-off-by: Johan Haals <johan.haals@gmail.com> --- plugins/catalog-backend/src/next/Stitcher.ts | 118 ++++++++++++++----- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index 57f5ae9167..04a8ab8cfc 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -26,6 +26,14 @@ import { import { Entity, parseEntityRef } from '@backstage/catalog-model'; import { createHash } from 'crypto'; import stableStringify from 'fast-json-stable-stringify'; +import { buildEntitySearch } from '../database/search'; +import { DbEntitiesSearchRow } from '../database/types'; + +// The number of items that are sent per batch to the database layer, when +// doing .batchInsert calls to knex. This needs to be low enough to not cause +// errors in the underlying engine due to exceeding query limits, but large +// enough to get the speed benefits. +const BATCH_SIZE = 50; export type DbFinalEntitiesRow = { entity_id: string; @@ -49,64 +57,114 @@ export class Stitcher { for (const entityRef of entityRefs) { await this.transaction(async txOpaque => { const tx = txOpaque as Knex.Transaction; - const [result] = await tx<DbRefreshStateRow>('refresh_state') - .select('entity_id', 'processed_entity') - .where({ entity_ref: entityRef }); - if (!result) { + const result: Array<{ + entityId: string; + processedEntity?: string; + errors: string; + incomingReferenceCount: string | number; + previousEtag?: string; + relationType?: string; + relationTarget?: string; + }> = await tx + .with('incoming_references', function incomingReferences(builder) { + return builder + .from('refresh_state_references') + .where({ target_entity_ref: entityRef }) + .count({ count: '*' }); + }) + .select({ + entityId: 'refresh_state.entity_id', + processedEntity: 'refresh_state.processed_entity', + errors: 'refresh_state.errors', + incomingReferenceCount: 'incoming_references.count', + previousEtag: 'final_entities.etag', + relationType: 'relations.type', + relationTarget: 'relations.target_entity_ref', + }) + .from('refresh_state') + .leftJoin('incoming_references', {}) + .leftOuterJoin('final_entities', { + 'final_entities.entity_id': 'refresh_state.entity_id', + }) + .leftOuterJoin('relations', { + 'relations.source_entity_ref': 'refresh_state.entity_ref', + }) + .where({ 'refresh_state.entity_ref': entityRef }); + + if (!result.length) { this.logger.debug( `Unable to stitch ${entityRef}, item does not exist in refresh state table`, ); return; - } else if (!result.processed_entity) { + } + + const { + entityId, + processedEntity, + errors, + incomingReferenceCount, + previousEtag, + } = result[0]; + + if (!processedEntity) { this.logger.debug( `Unable to stitch ${entityRef}, the entity has not yet been processed`, ); return; } - const entity: Entity = JSON.parse(result.processed_entity); + const entity = JSON.parse(processedEntity) as Entity; + const isOrphan = Number(incomingReferenceCount) === 0; - const entityId = entity?.metadata?.uid; - if (!entityId) { - this.logger.error(`missing ID in entity ${JSON.stringify(entity)}`); - return; - } - - const [reference_count_result] = await tx<DbRefreshStateReferencesRow>( - 'refresh_state_references', - ) - .where({ target_entity_ref: entityRef }) - .count({ reference_count: 'target_entity_ref' }); - - if (Number(reference_count_result.reference_count) === 0) { - this.logger.debug(`${entityRef} is orphan`); + if (isOrphan) { + this.logger.debug(`${entityRef} is an orphan`); entity.metadata.annotations = { ...entity.metadata.annotations, ['backstage.io/orphan']: 'true', }; } - const relationResults = await tx<DbRelationsRow>('relations') - .where({ source_entity_ref: entityRef }) - .select(); - - // TODO: entityRef is lower case and should be uppercase in the final result. - entity.relations = relationResults.map(relation => ({ - type: relation.type, - target: parseEntityRef(relation.target_entity_ref), - })); + // TODO: entityRef is lower case and should be uppercase in the final result + entity.relations = result + .filter(row => row.relationType) + .map(row => ({ + type: row.relationType!, + target: parseEntityRef(row.relationTarget!), + })); entity.metadata.generation = 1; + + // If the output entity was actually not changed, just abort const etag = generateEntityEtag(entity); + if (etag === previousEtag) { + console.log(`Skipped stitching of ${entityRef}, no changes`); + return; + } + entity.metadata.etag = etag; + await tx<DbFinalEntitiesRow>('final_entities') .insert({ - finalized_entity: JSON.stringify(entity), entity_id: entityId, + finalized_entity: JSON.stringify(entity), etag, }) .onConflict('entity_id') .merge(['finalized_entity', 'etag']); + + try { + const entries = buildEntitySearch(entityId, entity); + await tx<DbEntitiesSearchRow>('search') + .where({ entity_id: entityId }) + .delete(); + await tx.batchInsert('search', entries, BATCH_SIZE); + } catch (e) { + this.logger.debug( + `Failed to write search entries for ${entityId}`, + e, + ); + // intentionally ignored + } }); } } From 5c60c66ff508bae37ccfcb597d5e6e6c030a68aa Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Tue, 27 Apr 2021 18:30:22 +0200 Subject: [PATCH 226/262] Create search table Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../20210302150147_refresh_state.js | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 2afeda02c0..755a645894 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -154,6 +154,28 @@ exports.up = async function up(knex) { table.index('source_entity_ref', 'relations_source_entity_ref_idx'); table.index('originating_entity_id', 'relations_source_entity_id_idx'); }); + + await knex.schema.createTable('search', table => { + table.comment( + 'Flattened key-values from the entities, used for quick filtering', + ); + table + .uuid('entity_id') + .references('entity_id') + .inTable('refresh_state') + .onDelete('CASCADE') + .comment('The entity that matches this key/value'); + table + .string('key') + .notNullable() + .comment('A key that occurs in the entity'); + table + .string('value') + .nullable() + .comment('The corresponding value to match on'); + table.index(['key'], 'search_key_idx'); + table.index(['value'], 'search_value_idx'); + }); }; /** @@ -177,6 +199,12 @@ exports.down = async function down(knex) { table.index('source_entity_ref', 'relations_source_entity_ref_idx'); table.index('originating_entity_id', 'relations_source_entity_id_idx'); }); + await knex.schema.alterTable('search', table => { + table.dropIndex([], 'search_key_idx'); + table.dropIndex([], 'search_value_idx'); + }); + + await knex.schema.dropTable('search'); await knex.schema.dropTable('final_entities'); await knex.schema.dropTable('relations'); await knex.schema.dropTable('references'); From d798708943c6b851a96de8837653040eaad5a757 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Tue, 27 Apr 2021 21:23:35 +0200 Subject: [PATCH 227/262] chore(tests): Added some more tests for DefaultLocationStore and fixing migration so it will run properly on PG Signed-off-by: blam <ben@blam.sh> --- .../20210302150147_refresh_state.js | 2 +- .../src/next/DefaultLocationStore.test.ts | 146 ++++++++++++++++++ .../src/next/DefaultLocationStore.ts | 26 ++-- 3 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 plugins/catalog-backend/src/next/DefaultLocationStore.test.ts diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 755a645894..bbaf4820cd 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -160,7 +160,7 @@ exports.up = async function up(knex) { 'Flattened key-values from the entities, used for quick filtering', ); table - .uuid('entity_id') + .text('entity_id') .references('entity_id') .inTable('refresh_state') .onDelete('CASCADE') diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts new file mode 100644 index 0000000000..be20179e9a --- /dev/null +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts @@ -0,0 +1,146 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { DatabaseManager } from './database/DatabaseManager'; +import { DefaultLocationStore } from './DefaultLocationStore'; +import { v4 } from 'uuid'; + +describe('Default Location Store', () => { + const createLocationStore = async () => { + const db = await DatabaseManager.createTestDatabase(); + const connection = { applyMutation: jest.fn() }; + const store = new DefaultLocationStore(db); + await store.connect(connection); + return { store, connection }; + }; + + it('should do a full sync with the locations on connect', async () => { + const { connection } = await createLocationStore(); + + expect(connection.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [], + }); + }); + + describe('listLocations', () => { + it('lists empty locations when there is no locations', async () => { + const { store } = await createLocationStore(); + + expect(await store.listLocations()).toEqual([]); + }); + + it('lists locations that are added to the db', async () => { + const { store } = await createLocationStore(); + + await store.createLocation({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }); + + const listLocations = await store.listLocations(); + + expect(listLocations).toHaveLength(1); + expect(listLocations).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }), + ]), + ); + }); + }); + + describe('createLocation', () => { + it('throws when the location already exists', async () => { + const { store } = await createLocationStore(); + const spec = { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }; + await store.createLocation(spec); + + await expect(() => store.createLocation(spec)).rejects.toThrow( + new RegExp(`Location ${spec.type}:${spec.target} already exists`), + ); + }); + + it('calls apply mutation when adding a new location', async () => { + const { store, connection } = await createLocationStore(); + + await store.createLocation({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }); + + expect(connection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + removed: [], + added: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }, + }), + ]), + }); + }); + }); + + describe('deleteLocation', () => { + it('throws if the location does not exist', async () => { + const { store } = await createLocationStore(); + + const id = v4(); + + await expect(() => store.deleteLocation(id)).rejects.toThrow( + new RegExp(`Found no location with ID ${id}`), + ); + }); + + it('calls apply mutation when adding a new location', async () => { + const { store, connection } = await createLocationStore(); + + const location = await store.createLocation({ + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }); + + await store.deleteLocation(location.id); + + expect(connection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [], + removed: expect.arrayContaining([ + expect.objectContaining({ + spec: { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }, + }), + ]), + }); + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index a56e5d1585..28db3790b6 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -34,10 +34,8 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { return 'DefaultLocationStore'; } - createLocation(spec: LocationSpec): Promise<Location> { + async createLocation(spec: LocationSpec): Promise<Location> { return this.db.transaction(async tx => { - // TODO: id should really be type and target combined and not a uuid. - // Attempt to find a previous location matching the spec const previousLocations = await this.listLocations(); const previousLocation = previousLocations.some( @@ -50,6 +48,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { ); } + // TODO: id should really be type and target combined and not a uuid. const location = await this.db.addLocation(tx, { id: uuidv4(), type: spec.type, @@ -68,11 +67,17 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { async listLocations(): Promise<Location[]> { const dbLocations = await this.db.locations(); - return dbLocations.map(item => ({ - id: item.id, - target: item.target, - type: item.type, - })); + return ( + dbLocations + // TODO(blam): We should create a mutation to remove this location for everyone + // eventually when it's all done and dusted + .filter(({ type }) => type !== 'bootstrap') + .map(item => ({ + id: item.id, + target: item.target, + type: item.type, + })) + ); } getLocation(id: string): Promise<Location> { @@ -86,9 +91,6 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { return this.db.transaction(async tx => { const location = await this.db.location(id); - if (!location) { - throw new ConflictError(`No location found with id: ${id}`); - } await this.db.removeLocation(tx, id); await this.connection.applyMutation({ type: 'delta', @@ -108,7 +110,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { async connect(connection: EntityProviderConnection): Promise<void> { this._connection = connection; - const locations = await this.db.locations(); + const locations = await this.listLocations(); const entities = locations.map(location => { return locationSpecToLocationEntity(location); }); From a60c2d9f8f4f3dfbb529e10ddaf7ab0679ee7772 Mon Sep 17 00:00:00 2001 From: Johan Haals <johan.haals@gmail.com> Date: Wed, 28 Apr 2021 09:18:35 +0200 Subject: [PATCH 228/262] Update processed entity tests Signed-off-by: Johan Haals <johan.haals@gmail.com> --- .../DefaultProcessingDatabase.test.ts | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index a5c1e56cff..d76bd74260 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -19,10 +19,11 @@ import { Knex } from 'knex'; import { DbRefreshStateReferencesRow, DbRefreshStateRow, + DbRelationsRow, DefaultProcessingDatabase, } from './DefaultProcessingDatabase'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, EntityRelationSpec } from '@backstage/catalog-model'; import * as uuid from 'uuid'; import { getVoidLogger } from '@backstage/backend-common'; @@ -452,8 +453,8 @@ describe('Default Processing Database', () => { it('should update a processed entity', async () => { await db<DbRefreshStateRow>('refresh_state').insert({ - entity_id: '123', - entity_ref: 'Component:default/wacka', + entity_id: '321', + entity_ref: 'location:default/new-root', unprocessed_entity: '', errors: '', next_update_at: 'now()', @@ -468,9 +469,23 @@ describe('Default Processing Database', () => { kind: 'Location', } as Entity; + const relation: EntityRelationSpec = { + source: { + kind: 'Component', + namespace: 'Default', + name: 'foo', + }, + target: { + kind: 'Component', + namespace: 'Default', + name: 'foo', + }, + type: 'url', + }; + await processingDatabase.transaction(async tx => { await processingDatabase.updateProcessedEntity(tx, { - id: '123', + id: '321', processedEntity: { apiVersion: '1.0.0', metadata: { @@ -479,16 +494,24 @@ describe('Default Processing Database', () => { kind: 'Location', } as Entity, deferredEntities: [deferredEntity], - relations: [], + relations: [relation], }); }); - console.log( - await db<DbRefreshStateRow>('refresh_state') - .where({ entity_ref: 'deferred' }) - .select(), - ); - expect(1).toBeDefined(); + const deferredResult = await db<DbRefreshStateRow>('refresh_state') + .where({ entity_ref: 'location:default/deferred' }) + .select(); + expect(deferredResult.length).toBe(1); + + const [relations] = await db<DbRelationsRow>('relations') + .where({ originating_entity_id: '321' }) + .select(); + expect(relations).toEqual({ + originating_entity_id: '321', + source_entity_ref: 'component:default/foo', + type: 'url', + target_entity_ref: 'component:default/foo', + }); }); }); }); From 35b3246116ee756abeb27760073c9e5561f046c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 09:18:36 +0200 Subject: [PATCH 229/262] update the stitcher including search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../20210302150147_refresh_state.js | 7 +- .../catalog-backend/src/next/Stitcher.test.ts | 205 ++++++++++++++++++ plugins/catalog-backend/src/next/Stitcher.ts | 59 ++--- .../catalog-backend/src/next/search.test.ts | 160 ++++++++++++++ plugins/catalog-backend/src/next/search.ts | 191 ++++++++++++++++ plugins/catalog-backend/src/next/types.ts | 1 + 6 files changed, 592 insertions(+), 31 deletions(-) create mode 100644 plugins/catalog-backend/src/next/Stitcher.test.ts create mode 100644 plugins/catalog-backend/src/next/search.test.ts create mode 100644 plugins/catalog-backend/src/next/search.ts diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index bbaf4820cd..4d2c30f194 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -33,7 +33,6 @@ exports.up = async function up(knex) { ); table .text('entity_ref') - .unique() .notNullable() .comment('A reference to the entity that the refresh state is tied to'); table @@ -59,13 +58,14 @@ exports.up = async function up(knex) { .notNullable() .comment('JSON array containing all errors related to entity'); table - .dateTime('next_update_at') // TOOD: timezone or change to epoch-millis or similar + .dateTime('next_update_at') // TODO: timezone or change to epoch-millis or similar .notNullable() .comment('Timestamp of when entity should be updated'); table - .dateTime('last_discovery_at') // TOOD: timezone or change to epoch-millis or similar + .dateTime('last_discovery_at') // TODO: timezone or change to epoch-millis or similar .notNullable() .comment('The last timestamp of which this entity was discovered'); + table.unique(['entity_ref'], 'refresh_state_entity_ref_uniq'); table.index('entity_id', 'refresh_state_entity_id_idx'); table.index('entity_ref', 'refresh_state_entity_ref_idx'); table.index('next_update_at', 'refresh_state_next_update_at_idx'); @@ -188,6 +188,7 @@ exports.down = async function down(knex) { table.dropIndex([], 'refresh_state_references_target_entity_id_idx'); }); await knex.schema.alterTable('refresh_state', table => { + table.dropUnique([], 'refresh_state_entity_ref_uniq'); table.dropIndex([], 'refresh_state_entity_id_idx'); table.dropIndex([], 'refresh_state_entity_ref_idx'); table.dropIndex([], 'refresh_state_next_update_at_idx'); diff --git a/plugins/catalog-backend/src/next/Stitcher.test.ts b/plugins/catalog-backend/src/next/Stitcher.test.ts new file mode 100644 index 0000000000..327d922c07 --- /dev/null +++ b/plugins/catalog-backend/src/next/Stitcher.test.ts @@ -0,0 +1,205 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger } from '@backstage/backend-common'; +import { Knex } from 'knex'; +import { DatabaseManager } from './database/DatabaseManager'; +import { + DbRefreshStateReferencesRow, + DbRefreshStateRow, + DbRelationsRow, +} from './database/DefaultProcessingDatabase'; +import { DbSearchRow } from './search'; +import { DbFinalEntitiesRow, Stitcher } from './Stitcher'; + +describe('Stitcher', () => { + let db: Knex; + const logger = getVoidLogger(); + + beforeEach(async () => { + db = await DatabaseManager.createTestDatabaseConnection(); + await DatabaseManager.createDatabase(db); + }); + + it('runs the happy path', async () => { + const stitcher = new Stitcher(db, logger); + + await db.transaction(async tx => { + await tx<DbRefreshStateRow>('refresh_state').insert([ + { + entity_id: 'my-id', + entity_ref: 'k:ns/n', + unprocessed_entity: JSON.stringify({}), + processed_entity: JSON.stringify({ + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'n', + namespace: 'ns', + }, + spec: { + k: 'v', + }, + }), + errors: '[]', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + }, + ]); + await tx<DbRefreshStateReferencesRow>('refresh_state_references').insert([ + { source_key: 'a', target_entity_ref: 'k:ns/n' }, + ]); + await tx<DbRelationsRow>('relations').insert([ + { + originating_entity_id: 'my-id', + source_entity_ref: 'k:ns/n', + type: 'looksAt', + target_entity_ref: 'k:ns/other', + }, + ]); + }); + + await stitcher.stitch(new Set(['k:ns/n'])); + + let firstEtag: string; + await db.transaction(async tx => { + const entities = await tx<DbFinalEntitiesRow>('final_entities'); + + expect(entities.length).toBe(1); + const entity = JSON.parse(entities[0].finalized_entity); + expect(entity).toEqual({ + relations: [ + { + type: 'looksAt', + target: { + kind: 'k', + namespace: 'ns', + name: 'other', + }, + }, + ], + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'n', + namespace: 'ns', + etag: expect.any(String), + generation: 1, + uid: 'my-id', + }, + spec: { + k: 'v', + }, + }); + + firstEtag = entity.metadata.etag; + + const search = await tx<DbSearchRow>('search'); + expect(search).toEqual( + expect.arrayContaining([ + { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/other' }, + { entity_id: 'my-id', key: 'apiversion', value: 'a' }, + { entity_id: 'my-id', key: 'kind', value: 'k' }, + { entity_id: 'my-id', key: 'metadata.name', value: 'n' }, + { entity_id: 'my-id', key: 'metadata.namespace', value: 'ns' }, + { entity_id: 'my-id', key: 'metadata.uid', value: 'my-id' }, + { entity_id: 'my-id', key: 'spec.k', value: 'v' }, + ]), + ); + }); + + // Re-stitch without any changes + await stitcher.stitch(new Set(['k:ns/n'])); + + await db.transaction(async tx => { + const entities = await tx<DbFinalEntitiesRow>('final_entities'); + expect(entities.length).toBe(1); + const entity = JSON.parse(entities[0].finalized_entity); + expect(entities[0].etag).toEqual(firstEtag); + expect(entity.metadata.etag).toEqual(firstEtag); + }); + + // Now add one more relation and re-stitch + await db.transaction(async tx => { + await tx<DbRelationsRow>('relations').insert([ + { + originating_entity_id: 'my-id', + source_entity_ref: 'k:ns/n', + type: 'looksAt', + target_entity_ref: 'k:ns/third', + }, + ]); + }); + + await stitcher.stitch(new Set(['k:ns/n'])); + + await db.transaction(async tx => { + const entities = await tx<DbFinalEntitiesRow>('final_entities'); + + expect(entities.length).toBe(1); + const entity = JSON.parse(entities[0].finalized_entity); + expect(entity).toEqual({ + relations: expect.arrayContaining([ + { + type: 'looksAt', + target: { + kind: 'k', + namespace: 'ns', + name: 'other', + }, + }, + { + type: 'looksAt', + target: { + kind: 'k', + namespace: 'ns', + name: 'third', + }, + }, + ]), + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'n', + namespace: 'ns', + etag: expect.any(String), + generation: 1, + uid: 'my-id', + }, + spec: { + k: 'v', + }, + }); + + expect(entities[0].etag).not.toEqual(firstEtag); + expect(entities[0].etag).toEqual(entity.metadata.etag); + + const search = await tx<DbSearchRow>('search'); + expect(search).toEqual( + expect.arrayContaining([ + { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/other' }, + { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/third' }, + { entity_id: 'my-id', key: 'apiversion', value: 'a' }, + { entity_id: 'my-id', key: 'kind', value: 'k' }, + { entity_id: 'my-id', key: 'metadata.name', value: 'n' }, + { entity_id: 'my-id', key: 'metadata.namespace', value: 'ns' }, + { entity_id: 'my-id', key: 'metadata.uid', value: 'my-id' }, + { entity_id: 'my-id', key: 'spec.k', value: 'v' }, + ]), + ); + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index 04a8ab8cfc..cd9220e934 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -14,20 +14,14 @@ * limitations under the License. */ +import { Entity, parseEntityRef } from '@backstage/catalog-model'; +import { ConflictError } from '@backstage/errors'; +import { createHash } from 'crypto'; +import stableStringify from 'fast-json-stable-stringify'; import { Knex } from 'knex'; import { Logger } from 'winston'; import { Transaction } from '../database'; -import { ConflictError } from '@backstage/errors'; -import { - DbRefreshStateReferencesRow, - DbRefreshStateRow, - DbRelationsRow, -} from './database/DefaultProcessingDatabase'; -import { Entity, parseEntityRef } from '@backstage/catalog-model'; -import { createHash } from 'crypto'; -import stableStringify from 'fast-json-stable-stringify'; -import { buildEntitySearch } from '../database/search'; -import { DbEntitiesSearchRow } from '../database/types'; +import { buildEntitySearch, DbSearchRow } from './search'; // The number of items that are sent per batch to the database layer, when // doing .batchInsert calls to knex. This needs to be low enough to not cause @@ -58,6 +52,13 @@ export class Stitcher { await this.transaction(async txOpaque => { const tx = txOpaque as Knex.Transaction; + // Selecting from refresh_state and final_entities should yield exactly + // one row (except in abnormal cases where the stitch was invoked for + // something that didn't exist at all, in which case it's zero rows). + // The join with the temporary incoming_references still gives one row. + // The only result set "expanding" join is the one with relations, so + // the output should be at least one row (if zero or one relations were + // found), or at most the same number of rows as relations. const result: Array<{ entityId: string; processedEntity?: string; @@ -90,8 +91,14 @@ export class Stitcher { .leftOuterJoin('relations', { 'relations.source_entity_ref': 'refresh_state.entity_ref', }) - .where({ 'refresh_state.entity_ref': entityRef }); + .where({ 'refresh_state.entity_ref': entityRef }) + .orderBy('relationType', 'asc') + .orderBy('relationTarget', 'asc'); + // If there were no rows returned, it would mean that there was no + // matching row even in the refresh_state. This can happen for example + // if we emit a relation to something that hasn't been ingested yet. + // It's safe to ignore this stitch attempt in that case. if (!result.length) { this.logger.debug( `Unable to stitch ${entityRef}, item does not exist in refresh state table`, @@ -102,11 +109,15 @@ export class Stitcher { const { entityId, processedEntity, - errors, + // errors, incomingReferenceCount, previousEtag, } = result[0]; + // If there was no processed entity in place, the target hasn't been + // through the processing steps yet. It's safe to ignore this stitch + // attempt in that case, since another stitch will be triggered when + // that processing has finished. if (!processedEntity) { this.logger.debug( `Unable to stitch ${entityRef}, the entity has not yet been processed`, @@ -114,6 +125,7 @@ export class Stitcher { return; } + // Grab the processed entity and stitch all of the relevant data into it const entity = JSON.parse(processedEntity) as Entity; const isOrphan = Number(incomingReferenceCount) === 0; @@ -132,15 +144,16 @@ export class Stitcher { type: row.relationType!, target: parseEntityRef(row.relationTarget!), })); - entity.metadata.generation = 1; // If the output entity was actually not changed, just abort const etag = generateEntityEtag(entity); if (etag === previousEtag) { - console.log(`Skipped stitching of ${entityRef}, no changes`); + this.logger.debug(`Skipped stitching of ${entityRef}, no changes`); return; } + entity.metadata.uid = entityId; + entity.metadata.generation = 1; entity.metadata.etag = etag; await tx<DbFinalEntitiesRow>('final_entities') @@ -152,19 +165,9 @@ export class Stitcher { .onConflict('entity_id') .merge(['finalized_entity', 'etag']); - try { - const entries = buildEntitySearch(entityId, entity); - await tx<DbEntitiesSearchRow>('search') - .where({ entity_id: entityId }) - .delete(); - await tx.batchInsert('search', entries, BATCH_SIZE); - } catch (e) { - this.logger.debug( - `Failed to write search entries for ${entityId}`, - e, - ); - // intentionally ignored - } + const searchEntries = buildEntitySearch(entityId, entity); + await tx<DbSearchRow>('search').where({ entity_id: entityId }).delete(); + await tx.batchInsert('search', searchEntries, BATCH_SIZE); }); } } diff --git a/plugins/catalog-backend/src/next/search.test.ts b/plugins/catalog-backend/src/next/search.test.ts new file mode 100644 index 0000000000..be9a98fe69 --- /dev/null +++ b/plugins/catalog-backend/src/next/search.test.ts @@ -0,0 +1,160 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { buildEntitySearch, mapToRows, traverse } from './search'; + +describe('search', () => { + describe('traverse', () => { + it('expands lists of strings to several rows', () => { + const input = { a: ['b', 'c', 'd'] }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'a', value: 'b' }, + { key: 'a.b', value: true }, + { key: 'a', value: 'c' }, + { key: 'a.c', value: true }, + { key: 'a', value: 'd' }, + { key: 'a.d', value: true }, + ]); + }); + + it('expands objects', () => { + const input = { a: { b: { c: 'd' }, e: 'f' } }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'a.b.c', value: 'd' }, + { key: 'a.e', value: 'f' }, + ]); + }); + + it('expands list of objects', () => { + const input = { root: { list: [{ a: 1 }, { a: 2 }] } }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'root.list.a', value: 1 }, + { key: 'root.list.a', value: 2 }, + ]); + }); + + it('skips over special keys', () => { + const input = { + state: { x: 1 }, + relations: [{ y: 2 }], + a: 'a', + metadata: { + b: 'b', + name: 'name', + namespace: 'namespace', + uid: 'uid', + etag: 'etag', + generation: 'generation', + c: 'c', + }, + d: 'd', + }; + const output = traverse(input); + expect(output).toEqual([ + { key: 'a', value: 'a' }, + { key: 'metadata.b', value: 'b' }, + { key: 'metadata.c', value: 'c' }, + { key: 'd', value: 'd' }, + ]); + }); + }); + + describe('mapToRows', () => { + it('converts base types to strings or null', () => { + const input = [ + { key: 'a', value: true }, + { key: 'b', value: false }, + { key: 'c', value: 7 }, + { key: 'd', value: 'string' }, + { key: 'e', value: null }, + { key: 'f', value: undefined }, + ]; + const output = mapToRows(input, 'eid'); + expect(output).toEqual([ + { entity_id: 'eid', key: 'a', value: 'true' }, + { entity_id: 'eid', key: 'b', value: 'false' }, + { entity_id: 'eid', key: 'c', value: '7' }, + { entity_id: 'eid', key: 'd', value: 'string' }, + { entity_id: 'eid', key: 'e', value: null }, + { entity_id: 'eid', key: 'f', value: null }, + ]); + }); + + it('emits lowercase version of keys and values', () => { + const input = [{ key: 'fOo', value: 'BaR' }]; + const output = mapToRows(input, 'eid'); + expect(output).toEqual([{ entity_id: 'eid', key: 'foo', value: 'bar' }]); + }); + + it('skips very large values', () => { + const input = [{ key: 'foo', value: 'a'.repeat(10000) }]; + const output = mapToRows(input, 'eid'); + expect(output).toEqual([]); + }); + }); + + describe('buildEntitySearch', () => { + it('adds special keys even if missing', () => { + const input: Entity = { + apiVersion: 'a', + kind: 'b', + metadata: { name: 'n' }, + }; + expect(buildEntitySearch('eid', input)).toEqual([ + { entity_id: 'eid', key: 'apiversion', value: 'a' }, + { entity_id: 'eid', key: 'kind', value: 'b' }, + { entity_id: 'eid', key: 'metadata.name', value: 'n' }, + { entity_id: 'eid', key: 'metadata.namespace', value: null }, + { entity_id: 'eid', key: 'metadata.uid', value: null }, + { + entity_id: 'eid', + key: 'metadata.namespace', + value: ENTITY_DEFAULT_NAMESPACE, + }, + ]); + }); + + it('adds relations', () => { + const input: Entity = { + relations: [ + { type: 't1', target: { kind: 'k', namespace: 'ns', name: 'a' } }, + { type: 't2', target: { kind: 'k', namespace: 'ns', name: 'b' } }, + ], + apiVersion: 'a', + kind: 'b', + metadata: { name: 'n' }, + }; + expect(buildEntitySearch('eid', input)).toEqual([ + { entity_id: 'eid', key: 'apiversion', value: 'a' }, + { entity_id: 'eid', key: 'kind', value: 'b' }, + { entity_id: 'eid', key: 'metadata.name', value: 'n' }, + { entity_id: 'eid', key: 'metadata.namespace', value: null }, + { entity_id: 'eid', key: 'metadata.uid', value: null }, + { + entity_id: 'eid', + key: 'metadata.namespace', + value: ENTITY_DEFAULT_NAMESPACE, + }, + { entity_id: 'eid', key: 'relations', value: 't1:k:ns/a' }, + { entity_id: 'eid', key: 'relations', value: 't2:k:ns/b' }, + ]); + }); + }); +}); diff --git a/plugins/catalog-backend/src/next/search.ts b/plugins/catalog-backend/src/next/search.ts new file mode 100644 index 0000000000..4aa8bae1a8 --- /dev/null +++ b/plugins/catalog-backend/src/next/search.ts @@ -0,0 +1,191 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Entity, + ENTITY_DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; + +export type DbSearchRow = { + entity_id: string; + key: string; + value: string | null; +}; + +// These are excluded in the generic loop, either because they do not make sense +// to index, or because they are special-case always inserted whether they are +// null or not +const SPECIAL_KEYS = [ + 'state', + 'relations', + 'metadata.name', + 'metadata.namespace', + 'metadata.uid', + 'metadata.etag', + 'metadata.generation', +]; + +// The maximum length allowed for search values. These columns are indexed, and +// database engines do not like to index on massive values. For example, +// postgres will balk after 8191 byte line sizes. +const MAX_VALUE_LENGTH = 200; + +type Kv = { + key: string; + value: unknown; +}; + +// Helper for traversing through a nested structure and outputting a list of +// path->value entries of the leaves. +// +// For example, this yaml structure +// +// a: 1 +// b: +// c: null +// e: [f, g] +// h: +// - i: 1 +// j: k +// - i: 2 +// j: l +// +// will result in +// +// "a", 1 +// "b.c", null +// "b.e": "f" +// "b.e.f": true +// "b.e": "g" +// "b.e.g": true +// "h.i": 1 +// "h.j": "k" +// "h.i": 2 +// "h.j": "l" +export function traverse(root: unknown): Kv[] { + const output: Kv[] = []; + + function visit(path: string, current: unknown) { + if (SPECIAL_KEYS.includes(path)) { + return; + } + + // empty or scalar + if ( + current === undefined || + current === null || + ['string', 'number', 'boolean'].includes(typeof current) + ) { + output.push({ key: path, value: current }); + return; + } + + // unknown + if (typeof current !== 'object') { + return; + } + + // array + if (Array.isArray(current)) { + for (const item of current) { + // NOTE(freben): The reason that these are output in two different ways, + // is to support use cases where you want to express that MORE than one + // tag is present in a list. Since the EntityFilters structure is a + // record, you can't have several entries of the same key. Therefore + // you will have to match on + // + // { "a.b": ["true"], "a.c": ["true"] } + // + // rather than + // + // { "a": ["b", "c"] } + // + // because the latter means EITHER b or c has to be present. + visit(path, item); + if (typeof item === 'string') { + output.push({ key: `${path}.${item}`, value: true }); + } + } + return; + } + + // object + for (const [key, value] of Object.entries(current!)) { + visit(path ? `${path}.${key}` : key, value); + } + } + + visit('', root); + + return output; +} + +// Translates a number of raw data rows to search table rows +export function mapToRows(input: Kv[], entityId: string): DbSearchRow[] { + const result: DbSearchRow[] = []; + + for (const { key: rawKey, value: rawValue } of input) { + const key = rawKey.toLocaleLowerCase('en-US'); + if (rawValue === undefined || rawValue === null) { + result.push({ entity_id: entityId, key, value: null }); + } else { + const value = String(rawValue).toLocaleLowerCase('en-US'); + if (value.length <= MAX_VALUE_LENGTH) { + result.push({ entity_id: entityId, key, value }); + } + } + } + + return result; +} + +/** + * Generates all of the search rows that are relevant for this entity. + * + * @param entityId The uid of the entity + * @param entity The entity + * @returns A list of entity search rows + */ +export function buildEntitySearch( + entityId: string, + entity: Entity, +): DbSearchRow[] { + // Visit the base structure recursively + const raw = traverse(entity); + + // Start with some special keys that are always present because you want to + // be able to easily search for null specifically + raw.push({ key: 'metadata.name', value: entity.metadata.name }); + raw.push({ key: 'metadata.namespace', value: entity.metadata.namespace }); + raw.push({ key: 'metadata.uid', value: entity.metadata.uid }); + + // Namespace not specified has the default value "default", so we want to + // match on that as well + if (!entity.metadata.namespace) { + raw.push({ key: 'metadata.namespace', value: ENTITY_DEFAULT_NAMESPACE }); + } + + // Visit relations + for (const relation of entity.relations ?? []) { + raw.push({ + key: 'relations', + value: `${relation.type}:${stringifyEntityRef(relation.target)}`, + }); + } + + return mapToRows(raw, entityId); +} diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index e0616fb336..cc9cc48ad6 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -120,6 +120,7 @@ export type ReplaceProcessingItemsRequest = removed: Entity[]; type: 'delta'; }; + export interface ProcessingStateManager { setProcessingItemResult(result: ProcessingItemResult): Promise<void>; getNextProcessingItem(): Promise<ProcessingItem>; From ec848a257d8ad6fb25b11c6e1329358c56492bf8 Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Wed, 28 Apr 2021 11:57:33 +0200 Subject: [PATCH 230/262] chore: disable tests for now Signed-off-by: blam <ben@blam.sh> --- plugins/catalog-backend/package.json | 1 - plugins/catalog-backend/src/next/DefaultLocationStore.test.ts | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 5f70ec60e1..a5bb9e00af 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -78,7 +78,6 @@ "files": [ "dist", "migrations/**/*.{js,d.ts}", - "migrationsv2/**/*.{js,d.ts}", "config.d.ts" ], "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts index be20179e9a..d30509eaec 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts @@ -17,7 +17,8 @@ import { DatabaseManager } from './database/DatabaseManager'; import { DefaultLocationStore } from './DefaultLocationStore'; import { v4 } from 'uuid'; -describe('Default Location Store', () => { +/* eslint-disable */ +xdescribe('Default Location Store', () => { const createLocationStore = async () => { const db = await DatabaseManager.createTestDatabase(); const connection = { applyMutation: jest.fn() }; From e2000428aec1302800520aa9a2ce2bfdc79a51cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 12:18:41 +0200 Subject: [PATCH 231/262] add forgotten index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../migrationsv2/20210302150147_refresh_state.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 4d2c30f194..7b0cf9b2a6 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -173,6 +173,7 @@ exports.up = async function up(knex) { .string('value') .nullable() .comment('The corresponding value to match on'); + table.index(['entity_id'], 'search_entity_id_idx'); table.index(['key'], 'search_key_idx'); table.index(['value'], 'search_value_idx'); }); @@ -201,6 +202,7 @@ exports.down = async function down(knex) { table.index('originating_entity_id', 'relations_source_entity_id_idx'); }); await knex.schema.alterTable('search', table => { + table.dropIndex([], 'search_entity_id_idx'); table.dropIndex([], 'search_key_idx'); table.dropIndex([], 'search_value_idx'); }); From 1ce80ff02230fba7afe6284425a15ff30112d981 Mon Sep 17 00:00:00 2001 From: Oliver Sand <oliver.sand@sda-se.com> Date: Wed, 28 Apr 2021 12:50:03 +0200 Subject: [PATCH 232/262] Resolve issues with AsyncAPI rendering by updating `@asyncapi/react-component` to `0.23.0` Signed-off-by: Oliver Sand <oliver.sand@sda-se.com> --- .changeset/calm-zebras-remain.md | 7 ++++ plugins/api-docs/package.json | 2 +- .../AsyncApiDefinitionWidget.tsx | 10 +---- yarn.lock | 38 +++++++++---------- 4 files changed, 28 insertions(+), 29 deletions(-) create mode 100644 .changeset/calm-zebras-remain.md diff --git a/.changeset/calm-zebras-remain.md b/.changeset/calm-zebras-remain.md new file mode 100644 index 0000000000..3b961ab3f2 --- /dev/null +++ b/.changeset/calm-zebras-remain.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Resolve issues with AsyncAPI rendering by updating `@asyncapi/react-component` +to `0.23.0`. The theming of the component is adjusted to the latest styling +changes. diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 51df09ba80..532dacf684 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@asyncapi/react-component": "^0.22.3", + "@asyncapi/react-component": "^0.23.0", "@backstage/catalog-model": "^0.7.7", "@backstage/core": "^0.7.6", "@backstage/plugin-catalog-react": "^0.1.4", diff --git a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx index a908a91b14..300c9d0c8a 100644 --- a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx @@ -88,18 +88,10 @@ const useStyles = makeStyles(theme => ({ '& .asyncapi__enum': { color: theme.palette.secondary.main, }, - '& .asyncapi__toggle-arrow:before': { - content: '">"', - 'font-family': 'inherit', - }, - '& .asyncapi__anchor-icon:before': { - content: '"🔗"', - 'font-family': 'inherit', - }, '& .asyncapi__info, .asyncapi__channel, .asyncapi__channels > div, .asyncapi__schema, .asyncapi__channel-operations-list .asyncapi__messages-list-item .asyncapi__message, .asyncapi__message, .asyncapi__server, .asyncapi__servers > div, .asyncapi__messages > div, .asyncapi__schemas > div': { 'background-color': 'inherit', }, - '& .asyncapi__channel-parameters-header, .asyncapi__channel-operations-header, .asyncapi__channel-operation-oneOf-subscribe-header, .asyncapi__channel-operation-oneOf-publish-header': { + '& .asyncapi__channel-parameters-header, .asyncapi__channel-operations-header, .asyncapi__channel-operation-oneOf-subscribe-header, .asyncapi__channel-operation-oneOf-publish-header, .asyncapi__channel-operation-message-header, .asyncapi__message-header, .asyncapi__message-header-title, .asyncapi__message-header-title > h3, .asyncapi__bindings, .asyncapi__bindings-header, .asyncapi__bindings-header > h4': { 'background-color': 'inherit', color: theme.palette.text.primary, }, diff --git a/yarn.lock b/yarn.lock index 80819e5307..66be73ae3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -69,22 +69,22 @@ dependencies: tslib "~2.0.1" -"@asyncapi/avro-schema-parser@^0.2.0": - version "0.2.0" - resolved "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-0.2.0.tgz#c9da2bb2858aca5a3b9e9a0e600084afd3765551" - integrity sha512-/oPDPudF82RGFXz5uhF77PSDZkAR+yHpdxUEbJ5jwk/X3RB74VRk8dqSgTqhUO+pLh+/Hut3x3VFacA8C9L2QA== +"@asyncapi/avro-schema-parser@^0.2.1": + version "0.2.1" + resolved "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-0.2.1.tgz#0b7d9953e12084e6f556db261ae08bd8f6690faa" + integrity sha512-RZJaHsdYM4dChYSrb/TWrVCn/r2qcus+9/8iLL8+SMINHb0ECgH8tFZFJpr3Tq+LV2SBFaRQ+9kuecjQ8BNDSA== -"@asyncapi/openapi-schema-parser@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-2.0.0.tgz#80e2f38e92b6635dde19aae07b92e3caa0effc58" - integrity sha512-XfDp3EIs6ptar3jARQZzi3ObmS44l6Qozc5GJmZJUQ6mHLTTqUGJ0nxcrXAW88vosjilgJVaQ63oGolA6smSHQ== +"@asyncapi/openapi-schema-parser@^2.0.1": + version "2.0.1" + resolved "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-2.0.1.tgz#4d6e82cced907b14e0ad6f98261ff2562d968d96" + integrity sha512-algbtdM1gcAOa8+V8kp7WeBhdaNac82jmZUXx8YjyNfRVo02N2juDrjeBAGJd+FNva9Mb4MM7qfkJoAFpTL5VQ== dependencies: "@openapi-contrib/openapi-schema-to-json-schema" "^3.0.0" -"@asyncapi/parser@^1.4.4": - version "1.4.4" - resolved "https://registry.npmjs.org/@asyncapi/parser/-/parser-1.4.4.tgz#66f2642e3f9ae4166cdea2480b665250b1edbd59" - integrity sha512-HEYEDM0BzfCxXNAv/pIS5yZWe11xB8fQo9G/SmsbpJavOpcF0sVZVIELva/NxHVz/ZUKPMKCa4Gqz7DF/lMqpw== +"@asyncapi/parser@^1.5.0": + version "1.5.0" + resolved "https://registry.npmjs.org/@asyncapi/parser/-/parser-1.5.0.tgz#d70616a1e6081c7dd86957befd5dccc46b9a77df" + integrity sha512-HzrehCcT6R+iqtktNmrUM9wRUEMBqnCeXIrGJT0txBMS1QduNRmXGjvuDpxqwyaATPH/xu1gSp2l6pFP/hyVbA== dependencies: "@apidevtools/json-schema-ref-parser" "^9.0.6" "@asyncapi/specs" "^2.7.7" @@ -96,14 +96,14 @@ node-fetch "^2.6.0" tiny-merge-patch "^0.1.2" -"@asyncapi/react-component@^0.22.3": - version "0.22.3" - resolved "https://registry.npmjs.org/@asyncapi/react-component/-/react-component-0.22.3.tgz#6ea7fb1044308e6d46f8455218920389becf2b22" - integrity sha512-f47sboqEQ0jNp0z2A+WGzBYYMS3ASmTwAXG/q6SwLuHBW15bSjaIYOVK3E8bmftBl+wVcEgAqUc6RKGtD9iVJg== +"@asyncapi/react-component@^0.23.0": + version "0.23.0" + resolved "https://registry.npmjs.org/@asyncapi/react-component/-/react-component-0.23.0.tgz#dce9a95cd0fb0d9f0364278088ad31194d411d52" + integrity sha512-mX70k3j5eSM7ets8BBZWnu6RsNXapLKD/7np+dMeXFk7KFbigVQXXr3hS0k2R+c8tRfkhlklicibq5ar1+fjDA== dependencies: - "@asyncapi/avro-schema-parser" "^0.2.0" - "@asyncapi/openapi-schema-parser" "^2.0.0" - "@asyncapi/parser" "^1.4.4" + "@asyncapi/avro-schema-parser" "^0.2.1" + "@asyncapi/openapi-schema-parser" "^2.0.1" + "@asyncapi/parser" "^1.5.0" constate "^1.2.0" dompurify "^2.1.1" markdown-it "^11.0.1" From 11461a20b304c47eae7581b9a77de5e033ab78e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 14:50:05 +0200 Subject: [PATCH 233/262] await the connection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../catalog-backend/src/next/DefaultCatalogProcessingEngine.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 1934b0aea7..9de9f0ffd5 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -68,7 +68,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async start() { for (const provider of this.entityProviders) { - provider.connect( + await provider.connect( new Connection({ stateManager: this.stateManager, id: provider.getProviderName(), From d1b1306d98a51f4a6e9814fb18a4abdb7179c2e8 Mon Sep 17 00:00:00 2001 From: Will <willsewell@monzo.com> Date: Tue, 27 Apr 2021 15:36:01 +0100 Subject: [PATCH 234/262] catalog-client: allow `filter` param to be specified multiple times This is possible on the backend, see: - https://github.com/backstage/backstage/blob/f9d077f5f6c3bf1e20255359798dd1febbeb3e27/plugins/catalog-backend/src/database/types.ts#L129-L131 - https://github.com/backstage/backstage/blob/f9d077f5f6c3bf1e20255359798dd1febbeb3e27/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts#L25-L42 Signed-off-by: Will Sewell <willsewell@monzo.com> --- .changeset/twenty-peas-deny.md | 5 +++ .../catalog-client/src/CatalogClient.test.ts | 32 +++++++++++++++++++ packages/catalog-client/src/CatalogClient.ts | 25 ++++++++++----- packages/catalog-client/src/types.ts | 5 ++- 4 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 .changeset/twenty-peas-deny.md diff --git a/.changeset/twenty-peas-deny.md b/.changeset/twenty-peas-deny.md new file mode 100644 index 0000000000..61c9cb3587 --- /dev/null +++ b/.changeset/twenty-peas-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': minor +--- + +Allow `filter` param to be specified multiple times diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 19da45e4ec..fefe670a55 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -79,6 +79,37 @@ describe('CatalogClient', () => { it('builds entity search filters properly', async () => { expect.assertions(2); + server.use( + rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => { + expect(req.url.search).toBe( + '?filter=a=1,b=2,b=3,%C3%B6=%3D&filter=a=2', + ); + return res(ctx.json([])); + }), + ); + + const response = await client.getEntities( + { + filter: [ + { + a: '1', + b: ['2', '3'], + ö: '=', + }, + { + a: '2', + }, + ], + }, + { token }, + ); + + expect(response.items).toEqual([]); + }); + + it('builds entity legacy search filters properly', async () => { + expect.assertions(2); + server.use( rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => { expect(req.url.search).toBe('?filter=a=1,b=2,b=3,%C3%B6=%3D'); @@ -88,6 +119,7 @@ describe('CatalogClient', () => { const response = await client.getEntities( { + // The legacy value of filter is not an array filter: { a: '1', b: ['2', '3'], diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 3de25e9808..a246b3abab 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -56,18 +56,27 @@ export class CatalogClient implements CatalogApi { request?: CatalogEntitiesRequest, options?: CatalogRequestOptions, ): Promise<CatalogListResponse<Entity>> { - const { filter = {}, fields = [] } = request ?? {}; + const { filter = [], fields = [] } = request ?? {}; + const filterItems = [filter].flat(); const params: string[] = []; - const filterParts: string[] = []; - for (const [key, value] of Object.entries(filter)) { - for (const v of [value].flat()) { - filterParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`); + // filter param can occur multiple times, for example + // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' + // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters + // the "inner array" defined within a `filter` param corresponds to "allOf" filters + for (const filterItem of filterItems) { + const filterParts: string[] = []; + for (const [key, value] of Object.entries(filterItem)) { + for (const v of [value].flat()) { + filterParts.push( + `${encodeURIComponent(key)}=${encodeURIComponent(v)}`, + ); + } } - } - if (filterParts.length) { - params.push(`filter=${filterParts.join(',')}`); + if (filterParts.length) { + params.push(`filter=${filterParts.join(',')}`); + } } if (fields.length) { diff --git a/packages/catalog-client/src/types.ts b/packages/catalog-client/src/types.ts index 0d25bf7483..9035657ddc 100644 --- a/packages/catalog-client/src/types.ts +++ b/packages/catalog-client/src/types.ts @@ -17,7 +17,10 @@ import { Entity, EntityName, Location } from '@backstage/catalog-model'; export type CatalogEntitiesRequest = { - filter?: Record<string, string | string[]> | undefined; + filter?: + | Record<string, string | string[]>[] + | Record<string, string | string[]> // Legacy type preserved for backwards compatibility + | undefined; fields?: string[] | undefined; }; From 17644ca68eb67dea67b1691f34181c61b811326a Mon Sep 17 00:00:00 2001 From: Will <willsewell@monzo.com> Date: Wed, 28 Apr 2021 14:23:10 +0100 Subject: [PATCH 235/262] Don't treat singuler `filter` type as legacy Instead it's a convenience type for when only a single instance of a param is required. Signed-off-by: Will Sewell <willsewell@monzo.com> --- packages/catalog-client/src/CatalogClient.test.ts | 5 ++--- packages/catalog-client/src/types.ts | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index fefe670a55..359e3a2c60 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -76,7 +76,7 @@ describe('CatalogClient', () => { expect(response).toEqual(defaultResponse); }); - it('builds entity search filters properly', async () => { + it('builds multiple entity search filters properly', async () => { expect.assertions(2); server.use( @@ -107,7 +107,7 @@ describe('CatalogClient', () => { expect(response.items).toEqual([]); }); - it('builds entity legacy search filters properly', async () => { + it('builds single entity search filter properly', async () => { expect.assertions(2); server.use( @@ -119,7 +119,6 @@ describe('CatalogClient', () => { const response = await client.getEntities( { - // The legacy value of filter is not an array filter: { a: '1', b: ['2', '3'], diff --git a/packages/catalog-client/src/types.ts b/packages/catalog-client/src/types.ts index 9035657ddc..ef907eafa9 100644 --- a/packages/catalog-client/src/types.ts +++ b/packages/catalog-client/src/types.ts @@ -19,7 +19,7 @@ import { Entity, EntityName, Location } from '@backstage/catalog-model'; export type CatalogEntitiesRequest = { filter?: | Record<string, string | string[]>[] - | Record<string, string | string[]> // Legacy type preserved for backwards compatibility + | Record<string, string | string[]> | undefined; fields?: string[] | undefined; }; From bd877d4518ec75be2ce9d63ad6cd26da93d1808c Mon Sep 17 00:00:00 2001 From: Will <willsewell@monzo.com> Date: Wed, 28 Apr 2021 14:25:05 +0100 Subject: [PATCH 236/262] Make "patch"-level change instead of "minor" Signed-off-by: Will Sewell <willsewell@monzo.com> --- .changeset/twenty-peas-deny.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/twenty-peas-deny.md b/.changeset/twenty-peas-deny.md index 61c9cb3587..df335ea95a 100644 --- a/.changeset/twenty-peas-deny.md +++ b/.changeset/twenty-peas-deny.md @@ -1,5 +1,5 @@ --- -'@backstage/catalog-client': minor +'@backstage/catalog-client': patch --- Allow `filter` param to be specified multiple times From d8b81fd28bf3cacf96cf62739e092f01568234fb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg <poldsberg@gmail.com> Date: Wed, 28 Apr 2021 16:11:29 +0200 Subject: [PATCH 237/262] changesets: add changeset for json-schema bump Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> --- .changeset/tough-walls-wash.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/tough-walls-wash.md diff --git a/.changeset/tough-walls-wash.md b/.changeset/tough-walls-wash.md new file mode 100644 index 0000000000..a45adcfbf6 --- /dev/null +++ b/.changeset/tough-walls-wash.md @@ -0,0 +1,9 @@ +--- +'@backstage/catalog-model': patch +'@backstage/cli': patch +'@backstage/config-loader': patch +'@backstage/config': patch +'@backstage/plugin-scaffolder': patch +--- + +Bump `json-schema` dependency from `0.2.5` to `0.3.0`. From 55e1d9f3a58696ad23e50e49a1a48a173aef10bb Mon Sep 17 00:00:00 2001 From: jrusso1020 <jrusso@brex.com> Date: Wed, 28 Apr 2021 08:45:35 -0600 Subject: [PATCH 238/262] update JSON Signed-off-by: jrusso1020 <jrusso@brex.com> --- docs/features/software-catalog/descriptor-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 0dba11fd62..eb087a9c5f 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -77,7 +77,7 @@ This is the same entity as returned in JSON from the software catalog API: "etag": "ZjU2MWRkZWUtMmMxZS00YTZiLWFmMWMtOTE1NGNiZDdlYzNk", "generation": 1, "labels": { - "backstage.io/custom": "ValueStuff" + "example.com/custom": "custom_label_value" }, "links": [{ "url": "https://admin.example-org.com", From d6cfbc797f768de5760eec9b93ade77ad9282597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 17:05:55 +0200 Subject: [PATCH 239/262] Tweaks to the v2 catalog ingestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../20210302150147_refresh_state.js | 14 ++++++-- .../src/next/NextEntitiesCatalog.ts | 2 +- .../catalog-backend/src/next/Stitcher.test.ts | 25 ++++++------- plugins/catalog-backend/src/next/Stitcher.ts | 36 +++++++++++-------- .../catalog-backend/src/next/search.test.ts | 4 +-- plugins/catalog-backend/src/next/search.ts | 4 +-- 6 files changed, 50 insertions(+), 35 deletions(-) diff --git a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js index 7b0cf9b2a6..4c03405910 100644 --- a/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrationsv2/20210302150147_refresh_state.js @@ -83,10 +83,18 @@ exports.up = async function up(knex) { .inTable('refresh_state') .onDelete('CASCADE') .comment( - 'Entity ID which correspond to the ID in the refresh_state table', + 'Entity ID which corresponds to the ID in the refresh_state table', ); - table.text('etag').notNullable().comment('Etag to be used for caching'); - table.text('finalized_entity').notNullable().comment('The final entity'); + table + .text('hash') + .notNullable() + .comment( + 'Stable hash of the entity data, to be used for caching and avoiding redundant work', + ); + table + .text('final_entity') + .notNullable() + .comment('The JSON encoded final entity'); table.index('entity_id', 'final_entities_entity_id_idx'); }); diff --git a/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts index 5bddd47f41..e87bb01e1f 100644 --- a/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts @@ -37,7 +37,7 @@ export class NextEntitiesCatalog implements EntitiesCatalog { 'final_entities', ).select(); - const entities = dbResponse.map(e => JSON.parse(e.finalized_entity)); + const entities = dbResponse.map(e => JSON.parse(e.final_entity)); return { entities, diff --git a/plugins/catalog-backend/src/next/Stitcher.test.ts b/plugins/catalog-backend/src/next/Stitcher.test.ts index 327d922c07..f38af384fa 100644 --- a/plugins/catalog-backend/src/next/Stitcher.test.ts +++ b/plugins/catalog-backend/src/next/Stitcher.test.ts @@ -74,12 +74,12 @@ describe('Stitcher', () => { await stitcher.stitch(new Set(['k:ns/n'])); - let firstEtag: string; + let firstHash: string; await db.transaction(async tx => { const entities = await tx<DbFinalEntitiesRow>('final_entities'); expect(entities.length).toBe(1); - const entity = JSON.parse(entities[0].finalized_entity); + const entity = JSON.parse(entities[0].final_entity); expect(entity).toEqual({ relations: [ { @@ -105,12 +105,13 @@ describe('Stitcher', () => { }, }); - firstEtag = entity.metadata.etag; + expect(entity.metadata.etag).toEqual(entities[0].hash); + firstHash = entities[0].hash; const search = await tx<DbSearchRow>('search'); expect(search).toEqual( expect.arrayContaining([ - { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/other' }, + { entity_id: 'my-id', key: 'relations.looksat', value: 'k:ns/other' }, { entity_id: 'my-id', key: 'apiversion', value: 'a' }, { entity_id: 'my-id', key: 'kind', value: 'k' }, { entity_id: 'my-id', key: 'metadata.name', value: 'n' }, @@ -127,9 +128,9 @@ describe('Stitcher', () => { await db.transaction(async tx => { const entities = await tx<DbFinalEntitiesRow>('final_entities'); expect(entities.length).toBe(1); - const entity = JSON.parse(entities[0].finalized_entity); - expect(entities[0].etag).toEqual(firstEtag); - expect(entity.metadata.etag).toEqual(firstEtag); + const entity = JSON.parse(entities[0].final_entity); + expect(entities[0].hash).toEqual(firstHash); + expect(entity.metadata.etag).toEqual(firstHash); }); // Now add one more relation and re-stitch @@ -150,7 +151,7 @@ describe('Stitcher', () => { const entities = await tx<DbFinalEntitiesRow>('final_entities'); expect(entities.length).toBe(1); - const entity = JSON.parse(entities[0].finalized_entity); + const entity = JSON.parse(entities[0].final_entity); expect(entity).toEqual({ relations: expect.arrayContaining([ { @@ -184,14 +185,14 @@ describe('Stitcher', () => { }, }); - expect(entities[0].etag).not.toEqual(firstEtag); - expect(entities[0].etag).toEqual(entity.metadata.etag); + expect(entities[0].hash).not.toEqual(firstHash); + expect(entities[0].hash).toEqual(entity.metadata.etag); const search = await tx<DbSearchRow>('search'); expect(search).toEqual( expect.arrayContaining([ - { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/other' }, - { entity_id: 'my-id', key: 'relations', value: 'looksat:k:ns/third' }, + { entity_id: 'my-id', key: 'relations.looksat', value: 'k:ns/other' }, + { entity_id: 'my-id', key: 'relations.looksat', value: 'k:ns/third' }, { entity_id: 'my-id', key: 'apiversion', value: 'a' }, { entity_id: 'my-id', key: 'kind', value: 'k' }, { entity_id: 'my-id', key: 'metadata.name', value: 'n' }, diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index cd9220e934..bdc028d923 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -31,11 +31,11 @@ const BATCH_SIZE = 50; export type DbFinalEntitiesRow = { entity_id: string; - etag: string; - finalized_entity: string; + hash: string; + final_entity: string; }; -function generateEntityEtag(entity: Entity) { +function generateStableHash(entity: Entity) { return createHash('sha1') .update(stableStringify({ ...entity })) .digest('hex'); @@ -64,7 +64,7 @@ export class Stitcher { processedEntity?: string; errors: string; incomingReferenceCount: string | number; - previousEtag?: string; + previousHash?: string; relationType?: string; relationTarget?: string; }> = await tx @@ -79,7 +79,7 @@ export class Stitcher { processedEntity: 'refresh_state.processed_entity', errors: 'refresh_state.errors', incomingReferenceCount: 'incoming_references.count', - previousEtag: 'final_entities.etag', + previousHash: 'final_entities.hash', relationType: 'relations.type', relationTarget: 'relations.target_entity_ref', }) @@ -111,7 +111,7 @@ export class Stitcher { processedEntity, // errors, incomingReferenceCount, - previousEtag, + previousHash, } = result[0]; // If there was no processed entity in place, the target hasn't been @@ -125,7 +125,8 @@ export class Stitcher { return; } - // Grab the processed entity and stitch all of the relevant data into it + // Grab the processed entity and stitch all of the relevant data into + // it const entity = JSON.parse(processedEntity) as Entity; const isOrphan = Number(incomingReferenceCount) === 0; @@ -137,33 +138,38 @@ export class Stitcher { }; } - // TODO: entityRef is lower case and should be uppercase in the final result + // TODO: entityRef is lower case and should be uppercase in the final + // result entity.relations = result - .filter(row => row.relationType) + .filter(row => row.relationType /* exclude null row, if relevant */) .map(row => ({ type: row.relationType!, target: parseEntityRef(row.relationTarget!), })); // If the output entity was actually not changed, just abort - const etag = generateEntityEtag(entity); - if (etag === previousEtag) { + const hash = generateStableHash(entity); + if (hash === previousHash) { this.logger.debug(`Skipped stitching of ${entityRef}, no changes`); return; } entity.metadata.uid = entityId; entity.metadata.generation = 1; - entity.metadata.etag = etag; + if (!entity.metadata.etag) { + // If the original data source did not have its own etag handling, + // use the hash as a good-quality etag + entity.metadata.etag = hash; + } await tx<DbFinalEntitiesRow>('final_entities') .insert({ entity_id: entityId, - finalized_entity: JSON.stringify(entity), - etag, + final_entity: JSON.stringify(entity), + hash, }) .onConflict('entity_id') - .merge(['finalized_entity', 'etag']); + .merge(['final_entity', 'hash']); const searchEntries = buildEntitySearch(entityId, entity); await tx<DbSearchRow>('search').where({ entity_id: entityId }).delete(); diff --git a/plugins/catalog-backend/src/next/search.test.ts b/plugins/catalog-backend/src/next/search.test.ts index be9a98fe69..ff1cba01b9 100644 --- a/plugins/catalog-backend/src/next/search.test.ts +++ b/plugins/catalog-backend/src/next/search.test.ts @@ -152,8 +152,8 @@ describe('search', () => { key: 'metadata.namespace', value: ENTITY_DEFAULT_NAMESPACE, }, - { entity_id: 'eid', key: 'relations', value: 't1:k:ns/a' }, - { entity_id: 'eid', key: 'relations', value: 't2:k:ns/b' }, + { entity_id: 'eid', key: 'relations.t1', value: 'k:ns/a' }, + { entity_id: 'eid', key: 'relations.t2', value: 'k:ns/b' }, ]); }); }); diff --git a/plugins/catalog-backend/src/next/search.ts b/plugins/catalog-backend/src/next/search.ts index 4aa8bae1a8..5ff0721f91 100644 --- a/plugins/catalog-backend/src/next/search.ts +++ b/plugins/catalog-backend/src/next/search.ts @@ -182,8 +182,8 @@ export function buildEntitySearch( // Visit relations for (const relation of entity.relations ?? []) { raw.push({ - key: 'relations', - value: `${relation.type}:${stringifyEntityRef(relation.target)}`, + key: `relations.${relation.type}`, + value: stringifyEntityRef(relation.target), }); } From a7a68535e161ade9970e396056c18857c45bafec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 18:31:26 +0200 Subject: [PATCH 240/262] Minor typo entites -> entities and remove unused type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../src/next/DefaultCatalogProcessingEngine.ts | 2 +- .../next/DefaultCatalogProcessingOrchestrator.ts | 10 +++++----- plugins/catalog-backend/src/next/types.ts | 14 +------------- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 9de9f0ffd5..1397d9038a 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -105,7 +105,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { state: result.state, errors: result.errors, relations: result.relations, - deferredEntities: result.deferredEntites, + deferredEntities: result.deferredEntities, }); const setOfThingsToStitch = new Set<string>([ diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts index 1880b5d17e..8fbb19e536 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts @@ -179,7 +179,7 @@ export class DefaultCatalogProcessingOrchestrator ); } - // Backwards compatible processing of location entites + // Backwards compatible processing of location entities if (isLocationEntity(entity)) { const { type = location.type } = entity.spec; const targets = new Array<string>(); @@ -268,7 +268,7 @@ function createEmitter(logger: Logger, parentEntity: Entity) { const errors = new Array<Error>(); const relations = new Array<EntityRelationSpec>(); - const deferredEntites = new Array<Entity>(); + const deferredEntities = new Array<Entity>(); const emit = (i: CatalogProcessorResult) => { if (done) { @@ -282,7 +282,7 @@ function createEmitter(logger: Logger, parentEntity: Entity) { if (i.type === 'entity') { const originLocation = getEntityOriginLocationRef(parentEntity); - deferredEntites.push({ + deferredEntities.push({ ...i.entity, metadata: { ...i.entity.metadata, @@ -294,7 +294,7 @@ function createEmitter(logger: Logger, parentEntity: Entity) { }, }); } else if (i.type === 'location') { - deferredEntites.push( + deferredEntities.push( locationSpecToLocationEntity(i.location, parentEntity), ); } else if (i.type === 'relation') { @@ -311,7 +311,7 @@ function createEmitter(logger: Logger, parentEntity: Entity) { return { errors, relations, - deferredEntites, + deferredEntities, }; }, }; diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index cc9cc48ad6..202576fddd 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -22,18 +22,6 @@ import { } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/config'; -export interface LocationEntity { - apiVersion: 'backstage.io/v1alpha1'; - kind: 'Location'; - metadata: { - name: string; // type:target - namespace: 'default'; - }; - spec: { - location: { type: string; target: string }; - }; -} - export interface LocationService { createLocation( spec: LocationSpec, @@ -80,7 +68,7 @@ export type EntityProcessingResult = ok: true; state: Map<string, JsonObject>; completedEntity: Entity; - deferredEntites: Entity[]; + deferredEntities: Entity[]; relations: EntityRelationSpec[]; errors: Error[]; } From 30821b2b413bf1a46daf09c0c5600864d6f962a1 Mon Sep 17 00:00:00 2001 From: Tim Hansen <timbonicus@gmail.com> Date: Wed, 28 Apr 2021 10:57:00 -0600 Subject: [PATCH 241/262] Update cost-insights and circleci logos Signed-off-by: Tim Hansen <timbonicus@gmail.com> --- microsite/data/plugins/circleci.yaml | 2 +- microsite/data/plugins/cost-insights.yaml | 2 +- microsite/static/img/circleci.png | Bin 0 -> 16688 bytes microsite/static/img/cost-insights.png | Bin 0 -> 105171 bytes 4 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 microsite/static/img/circleci.png create mode 100644 microsite/static/img/cost-insights.png diff --git a/microsite/data/plugins/circleci.yaml b/microsite/data/plugins/circleci.yaml index 0acad832fa..cffbedca37 100644 --- a/microsite/data/plugins/circleci.yaml +++ b/microsite/data/plugins/circleci.yaml @@ -5,7 +5,7 @@ authorUrl: https://github.com/spotify category: CI/CD description: Automate your development process with CI hosted in the cloud or on a private server. documentation: https://github.com/backstage/backstage/tree/master/plugins/circleci -iconUrl: https://www.saaves.com/storage/brochure/logo-circleci-icon1583764538.png +iconUrl: img/circleci.png npmPackageName: '@backstage/plugin-circleci' tags: - ci diff --git a/microsite/data/plugins/cost-insights.yaml b/microsite/data/plugins/cost-insights.yaml index daa4f55a02..ec2d162b9d 100644 --- a/microsite/data/plugins/cost-insights.yaml +++ b/microsite/data/plugins/cost-insights.yaml @@ -5,7 +5,7 @@ authorUrl: https://github.com/spotify category: Discovery description: Visualize, understand and optimize your team's cloud costs. documentation: https://github.com/backstage/backstage/tree/master/plugins/cost-insights -iconUrl: https://www.materialui.co/materialIcons/editor/monetization_on_white_192x192.png +iconUrl: img/cost-insights.png npmPackageName: '@backstage/plugin-cost-insights' tags: - web diff --git a/microsite/static/img/circleci.png b/microsite/static/img/circleci.png new file mode 100644 index 0000000000000000000000000000000000000000..3fc450d54d9afbea45c5717cd68f9315dce7fa01 GIT binary patch literal 16688 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 literal 0 HcmV?d00001 diff --git a/microsite/static/img/cost-insights.png b/microsite/static/img/cost-insights.png new file mode 100644 index 0000000000000000000000000000000000000000..768247cb19e8eca4abf4aad034e60304fc5110c8 GIT binary patch literal 105171 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 BKA8Xj literal 0 HcmV?d00001 From b98de52ae834349b5d23097f38dc2fb237c87246 Mon Sep 17 00:00:00 2001 From: Phil Kuang <pkuang@factset.com> Date: Tue, 27 Apr 2021 21:36:51 -0400 Subject: [PATCH 242/262] feat(CostInsights): support a display friendly name prop for projects Signed-off-by: Phil Kuang <pkuang@factset.com> --- .changeset/cost-insights-gorgeous-dancers-hope.md | 5 +++++ .../components/ProjectSelect/ProjectSelect.test.tsx | 6 ++++-- .../src/components/ProjectSelect/ProjectSelect.tsx | 11 +++++++---- plugins/cost-insights/src/types/Project.ts | 1 + 4 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 .changeset/cost-insights-gorgeous-dancers-hope.md diff --git a/.changeset/cost-insights-gorgeous-dancers-hope.md b/.changeset/cost-insights-gorgeous-dancers-hope.md new file mode 100644 index 0000000000..8e0abce57f --- /dev/null +++ b/.changeset/cost-insights-gorgeous-dancers-hope.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +Support a `name` prop for Projects for display purposes diff --git a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx index 1bd57a9eed..1820b9e35a 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx +++ b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx @@ -23,7 +23,7 @@ import { renderInTestApp } from '@backstage/test-utils'; const mockProjects = [ { id: 'project1' }, - { id: 'project2' }, + { id: 'project2', name: 'Project 2' }, { id: 'project3' }, ]; @@ -56,7 +56,9 @@ describe('<ProjectSelect />', () => { await waitFor(() => rendered.getByTestId('option-all')); mockProjects.forEach(project => - expect(rendered.getByText(project.id)).toBeInTheDocument(), + expect( + rendered.getByText(project.name ?? project.id), + ).toBeInTheDocument(), ); }); }); diff --git a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx index bc34eb9c8d..25fdc0c171 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx +++ b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx @@ -33,7 +33,9 @@ export const ProjectSelect = ({ const projectOptions = projects .filter(p => p.id) - .sort((a, b) => (a.id as string).localeCompare(b.id as string)); + .sort((a, b) => + ((a.name ?? a.id) as string).localeCompare((b.name ?? b.id) as string), + ); const handleOnChange = (e: React.ChangeEvent<{ value: unknown }>) => { onSelect(e.target.value as string); @@ -41,9 +43,10 @@ export const ProjectSelect = ({ const renderValue = (value: unknown) => { const proj = value as string; + const projectObj = projects.find(p => p.id === proj); return ( <b data-testid={`selected-${proj}`}> - {proj === 'all' ? 'All Projects' : proj} + {proj === 'all' ? 'All Projects' : projectObj?.name ?? proj} </b> ); }; @@ -52,7 +55,7 @@ export const ProjectSelect = ({ <Select className={classes.select} variant="outlined" - value={project || 'all'} + value={project ?? 'all'} renderValue={renderValue} onChange={handleOnChange} data-testid="project-filter-select" @@ -64,7 +67,7 @@ export const ProjectSelect = ({ value={proj.id} data-testid={`option-${proj.id}`} > - {proj.id === 'all' ? 'All Projects' : proj.id} + {proj.id === 'all' ? 'All Projects' : proj.name ?? proj.id} </MenuItem> ))} </Select> diff --git a/plugins/cost-insights/src/types/Project.ts b/plugins/cost-insights/src/types/Project.ts index 24259f6910..6ac61f1fb7 100644 --- a/plugins/cost-insights/src/types/Project.ts +++ b/plugins/cost-insights/src/types/Project.ts @@ -16,4 +16,5 @@ export interface Project { id: string; + name?: string; } From 410be7722c1541e4b5ff140b7ff75ef381829a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 19:25:24 +0200 Subject: [PATCH 243/262] exclude status instead of state, and also attachments while we're at it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/catalog-backend/src/next/search.test.ts | 5 +++-- plugins/catalog-backend/src/next/search.ts | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-backend/src/next/search.test.ts b/plugins/catalog-backend/src/next/search.test.ts index ff1cba01b9..2e0b07b4a9 100644 --- a/plugins/catalog-backend/src/next/search.test.ts +++ b/plugins/catalog-backend/src/next/search.test.ts @@ -52,8 +52,9 @@ describe('search', () => { it('skips over special keys', () => { const input = { - state: { x: 1 }, - relations: [{ y: 2 }], + status: { x: 1 }, + attachments: [{ y: 2 }], + relations: [{ z: 3 }], a: 'a', metadata: { b: 'b', diff --git a/plugins/catalog-backend/src/next/search.ts b/plugins/catalog-backend/src/next/search.ts index 5ff0721f91..383b29fd70 100644 --- a/plugins/catalog-backend/src/next/search.ts +++ b/plugins/catalog-backend/src/next/search.ts @@ -30,8 +30,9 @@ export type DbSearchRow = { // to index, or because they are special-case always inserted whether they are // null or not const SPECIAL_KEYS = [ - 'state', + 'attachments', 'relations', + 'status', 'metadata.name', 'metadata.namespace', 'metadata.uid', From 0f26d52325c62fc1e47ee03f5e2449e37665a13c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 19:25:56 +0200 Subject: [PATCH 244/262] remove unnecessary copying of migration files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../src/next/NextCatalogBuilder.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 24b763a098..7129809c71 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -243,19 +243,13 @@ export class NextCatalogBuilder { const parser = this.parser || defaultEntityDataParser; const dbClient = await database.getClient(); - const allMigrations = resolvePackagePath( - '@backstage/plugin-catalog-backend', - 'migrations', - ); - - const migrationsDir = resolvePackagePath( - '@backstage/plugin-catalog-backend', - 'migrationsv2', - ); - await fs.copy(allMigrations, migrationsDir); await dbClient.migrate.latest({ - directory: migrationsDir, + directory: resolvePackagePath( + '@backstage/plugin-catalog-backend', + 'migrationsv2', + ), }); + const db = new CommonDatabase(dbClient, logger); const processingDatabase = new DefaultProcessingDatabase(dbClient, logger); From f4009504d34e5259ff7f2ef31981e9c23138bab6 Mon Sep 17 00:00:00 2001 From: ImgBotApp <ImgBotHelp@gmail.com> Date: Wed, 28 Apr 2021 18:38:11 +0000 Subject: [PATCH 245/262] [ImgBot] Optimize images *Total -- 119.00kb -> 98.54kb (17.19%) /microsite/static/img/circleci.png -- 16.30kb -> 9.54kb (41.43%) /microsite/static/img/cost-insights.png -- 102.71kb -> 89.00kb (13.35%) Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com> --- microsite/static/img/circleci.png | Bin 16688 -> 9774 bytes microsite/static/img/cost-insights.png | Bin 105171 -> 91134 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/microsite/static/img/circleci.png b/microsite/static/img/circleci.png index 3fc450d54d9afbea45c5717cd68f9315dce7fa01..85f262e4b31af221482e868387c1a1a469cc6f8a 100644 GIT binary patch literal 9774 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 literal 16688 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 diff --git a/microsite/static/img/cost-insights.png b/microsite/static/img/cost-insights.png index 768247cb19e8eca4abf4aad034e60304fc5110c8..7296dd35240f8fd694b1cf40c2f853fc08699c16 100644 GIT binary patch literal 91134 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 Z^7w!MLFX&C81Mni;OcdqaxJ^a{{y<3k$3<A literal 105171 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 BKA8Xj From 0f2e4098f0a441cfa23039fc7127369dd885e727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Wed, 28 Apr 2021 21:07:21 +0200 Subject: [PATCH 246/262] some light renaming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- ...r.test.ts => ConfigLocationEntityProvider.test.ts} | 10 +++++----- ...ionProvider.ts => ConfigLocationEntityProvider.ts} | 6 +++--- .../src/next/DefaultCatalogProcessingEngine.ts | 9 ++++----- .../{DefaultService.ts => DefaultLocationService.ts} | 0 .../src/next/DefaultLocationStore.test.ts | 6 +++--- .../catalog-backend/src/next/DefaultLocationStore.ts | 4 ++-- .../catalog-backend/src/next/NextCatalogBuilder.ts | 11 +++++------ .../src/next/database/DatabaseManager.ts | 4 ++-- 8 files changed, 24 insertions(+), 26 deletions(-) rename plugins/catalog-backend/src/next/{ConfigLocationProvider.test.ts => ConfigLocationEntityProvider.test.ts} (90%) rename plugins/catalog-backend/src/next/{ConfigLocationProvider.ts => ConfigLocationEntityProvider.ts} (91%) rename plugins/catalog-backend/src/next/{DefaultService.ts => DefaultLocationService.ts} (100%) diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts similarity index 90% rename from plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts rename to plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts index 9aaba13c48..226e5c06a8 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationProvider.test.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import { ConfigLocationProvider } from './ConfigLocationProvider'; -import { EntityProviderConnection } from './types'; -import { ConfigReader } from '@backstage/config'; import { resolvePackagePath } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; import path from 'path'; +import { ConfigLocationEntityProvider } from './ConfigLocationEntityProvider'; +import { EntityProviderConnection } from './types'; -describe('Config Location Provider', () => { +describe('ConfigLocationEntityProvider', () => { it('should apply mutation with the correct paths in the config', async () => { const mockConfig = new ConfigReader({ catalog: { @@ -34,7 +34,7 @@ describe('Config Location Provider', () => { const mockConnection = ({ applyMutation: jest.fn(), } as unknown) as EntityProviderConnection; - const locationProvider = new ConfigLocationProvider(mockConfig); + const locationProvider = new ConfigLocationEntityProvider(mockConfig); await locationProvider.connect(mockConnection); diff --git a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts similarity index 91% rename from plugins/catalog-backend/src/next/ConfigLocationProvider.ts rename to plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts index 8a65487df1..bccbd0ba41 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationProvider.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import { EntityProviderConnection, EntityProvider } from './types'; -import path from 'path'; import { Config } from '@backstage/config'; +import path from 'path'; +import { EntityProvider, EntityProviderConnection } from './types'; import { locationSpecToLocationEntity } from './util'; -export class ConfigLocationProvider implements EntityProvider { +export class ConfigLocationEntityProvider implements EntityProvider { private connection: EntityProviderConnection | undefined; constructor(private readonly config: Config) {} diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 1397d9038a..e724fe79d8 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -14,19 +14,18 @@ * limitations under the License. */ +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { Logger } from 'winston'; +import { Stitcher } from './Stitcher'; import { CatalogProcessingEngine, + CatalogProcessingOrchestrator, EntityProvider, EntityProviderConnection, EntityProviderMutation, ProcessingStateManager, - CatalogProcessingOrchestrator, } from './types'; -import { Logger } from 'winston'; -import { stringifyEntityRef } from '@backstage/catalog-model'; -import { Stitcher } from './Stitcher'; - class Connection implements EntityProviderConnection { constructor( private readonly config: { diff --git a/plugins/catalog-backend/src/next/DefaultService.ts b/plugins/catalog-backend/src/next/DefaultLocationService.ts similarity index 100% rename from plugins/catalog-backend/src/next/DefaultService.ts rename to plugins/catalog-backend/src/next/DefaultLocationService.ts diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts index d30509eaec..f9bb97477c 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { v4 as uuid } from 'uuid'; import { DatabaseManager } from './database/DatabaseManager'; import { DefaultLocationStore } from './DefaultLocationStore'; -import { v4 } from 'uuid'; /* eslint-disable */ -xdescribe('Default Location Store', () => { +xdescribe('DefaultLocationStore', () => { const createLocationStore = async () => { const db = await DatabaseManager.createTestDatabase(); const connection = { applyMutation: jest.fn() }; @@ -111,7 +111,7 @@ xdescribe('Default Location Store', () => { it('throws if the location does not exist', async () => { const { store } = await createLocationStore(); - const id = v4(); + const id = uuid(); await expect(() => store.deleteLocation(id)).rejects.toThrow( new RegExp(`Found no location with ID ${id}`), diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index 28db3790b6..f6267df6a5 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -21,7 +21,7 @@ import { EntityProvider, EntityProviderConnection, } from './types'; -import { v4 as uuidv4 } from 'uuid'; +import { v4 as uuid } from 'uuid'; import { locationSpecToLocationEntity } from './util'; import { ConflictError } from '@backstage/errors'; @@ -50,7 +50,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { // TODO: id should really be type and target combined and not a uuid. const location = await this.db.addLocation(tx, { - id: uuidv4(), + id: uuid(), type: spec.type, target: spec.target, }); diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 7129809c71..10500fdc15 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -19,7 +19,6 @@ import { resolvePackagePath, UrlReader, } from '@backstage/backend-common'; -import fs from 'fs-extra'; import { DefaultNamespaceEntityPolicy, EntityPolicies, @@ -39,6 +38,7 @@ import { EntitiesCatalog, LocationsCatalog, } from '../catalog'; +import { CommonDatabase } from '../database/CommonDatabase'; import { AnnotateLocationEntityProcessor, BitbucketDiscoveryProcessor, @@ -63,16 +63,15 @@ import { } from '../ingestion/processors/PlaceholderProcessor'; import { defaultEntityDataParser } from '../ingestion/processors/util/parse'; import { LocationAnalyzer } from '../ingestion/types'; +import { CatalogProcessingEngine } from '../next/types'; +import { ConfigLocationEntityProvider } from './ConfigLocationEntityProvider'; +import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; import { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; -import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; import { DefaultLocationStore } from './DefaultLocationStore'; import { DefaultProcessingStateManager } from './DefaultProcessingStateManager'; -import { CatalogProcessingEngine } from '../next/types'; import { NextEntitiesCatalog } from './NextEntitiesCatalog'; import { Stitcher } from './Stitcher'; -import { CommonDatabase } from '../database/CommonDatabase'; -import { ConfigLocationProvider } from './ConfigLocationProvider'; export type CatalogEnvironment = { logger: Logger; @@ -266,7 +265,7 @@ export class NextCatalogBuilder { const locationStore = new DefaultLocationStore(db); const stitcher = new Stitcher(dbClient, logger); - const configLocationProvider = new ConfigLocationProvider(config); + const configLocationProvider = new ConfigLocationEntityProvider(config); const processingEngine = new DefaultCatalogProcessingEngine( logger, [locationStore, configLocationProvider], diff --git a/plugins/catalog-backend/src/next/database/DatabaseManager.ts b/plugins/catalog-backend/src/next/database/DatabaseManager.ts index f660f73ecb..22ae4e782f 100644 --- a/plugins/catalog-backend/src/next/database/DatabaseManager.ts +++ b/plugins/catalog-backend/src/next/database/DatabaseManager.ts @@ -16,7 +16,7 @@ import { getVoidLogger, resolvePackagePath } from '@backstage/backend-common'; import knexFactory, { Knex } from 'knex'; -import { v4 as uuidv4 } from 'uuid'; +import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; import { CommonDatabase } from '../../database/CommonDatabase'; import { Database } from '../../database/types'; @@ -79,7 +79,7 @@ export class DatabaseManager { let knex = knexFactory(config); if (typeof config.connection !== 'string') { - const tempDbName = `d${uuidv4().replace(/-/g, '')}`; + const tempDbName = `d${uuid().replace(/-/g, '')}`; await knex.raw(`CREATE DATABASE ${tempDbName};`); knex = knexFactory({ ...config, From 2a4ad54f77fd8e4dbaf03573ada95dba2689b707 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Apr 2021 23:17:43 +0000 Subject: [PATCH 247/262] chore(deps): bump y18n from 3.2.1 to 3.2.2 Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2. - [Release notes](https://github.com/yargs/y18n/releases) - [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md) - [Commits](https://github.com/yargs/y18n/commits) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 19aff83248..1e7d42537e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27074,9 +27074,9 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== y18n@^4.0.0: version "4.0.0" From c9307150662e018160c6948ca5c342e7c1787da8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 04:15:56 +0000 Subject: [PATCH 248/262] chore(deps): bump @kubernetes/client-node from 0.14.0 to 0.14.3 Bumps [@kubernetes/client-node](https://github.com/kubernetes-client/javascript) from 0.14.0 to 0.14.3. - [Release notes](https://github.com/kubernetes-client/javascript/releases) - [Changelog](https://github.com/kubernetes-client/javascript/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes-client/javascript/compare/0.14.0...0.14.3) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1e7d42537e..43e5c33ca5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2961,9 +2961,9 @@ integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== "@kubernetes/client-node@^0.14.0": - version "0.14.0" - resolved "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.14.0.tgz#a02806f3b6fdb68fb51d451ee8ff01faa446f557" - integrity sha512-/37JHuEUAQ5GQ4kLKBmCYvGgf5W1KZWKreKGWFYH8VvT2Hl/o0aJZasu2w0EHEfmE11JCn0X9arVmOTyVCYvww== + version "0.14.3" + resolved "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.14.3.tgz#5ed9b88873419080547f22cb74eb502bf6671fca" + integrity sha512-9hHGDNm2JEFQcRTpDxVoAVr0fowU+JH/l5atCXY9VXwvFM18pW5wr2LzLP+Q2Rh+uQv7Moz4gEjEKSCgVKykEQ== dependencies: "@types/js-yaml" "^3.12.1" "@types/node" "^10.12.0" From 08e32cf91327ac57628499c61524fc4e2dff3c46 Mon Sep 17 00:00:00 2001 From: Dominik Henneke <dominik.henneke@sda-se.com> Date: Thu, 29 Apr 2021 10:36:53 +0200 Subject: [PATCH 249/262] Add support for oneOf and allOf Signed-off-by: Dominik Henneke <dominik.henneke@sda-se.com> --- .changeset/tough-planes-jump.md | 2 +- .../MultistepJsonForm/schema.test.ts | 96 +++++++++++++++++++ .../components/MultistepJsonForm/schema.ts | 20 +++- 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/.changeset/tough-planes-jump.md b/.changeset/tough-planes-jump.md index a30315e9e4..ebbec65159 100644 --- a/.changeset/tough-planes-jump.md +++ b/.changeset/tough-planes-jump.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder': patch --- -Support anyOf schemas in the scaffolder template +Support `anyOf`, `oneOf` and `allOf` schemas in the scaffolder template. diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts index edfde0ea90..64dd705952 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts @@ -94,6 +94,28 @@ describe('transformSchemaToProps', () => { }, }, ], + oneOf: [ + { + properties: { + field4: { + type: 'string', + default: 'Value 1', + 'ui:readonly': true, + }, + }, + }, + ], + allOf: [ + { + properties: { + field5: { + type: 'string', + default: 'Value 1', + 'ui:readonly': true, + }, + }, + }, + ], properties: { field1: { type: 'object', @@ -117,6 +139,28 @@ describe('transformSchemaToProps', () => { }, }, ], + oneOf: [ + { + properties: { + field4: { + type: 'string', + default: 'Value 1', + 'ui:readonly': true, + }, + }, + }, + ], + allOf: [ + { + properties: { + field5: { + type: 'string', + default: 'Value 1', + 'ui:readonly': true, + }, + }, + }, + ], }, field2: { type: 'string', @@ -144,6 +188,26 @@ describe('transformSchemaToProps', () => { }, }, ], + oneOf: [ + { + properties: { + field4: { + type: 'string', + default: 'Value 1', + }, + }, + }, + ], + allOf: [ + { + properties: { + field5: { + type: 'string', + default: 'Value 1', + }, + }, + }, + ], properties: { field1: { type: 'object', @@ -165,6 +229,26 @@ describe('transformSchemaToProps', () => { }, }, ], + oneOf: [ + { + properties: { + field4: { + type: 'string', + default: 'Value 1', + }, + }, + }, + ], + allOf: [ + { + properties: { + field5: { + type: 'string', + default: 'Value 1', + }, + }, + }, + ], }, field2: { type: 'string', @@ -175,10 +259,22 @@ describe('transformSchemaToProps', () => { field3: { 'ui:readonly': true, }, + field4: { + 'ui:readonly': true, + }, + field5: { + 'ui:readonly': true, + }, field1: { field3: { 'ui:readonly': true, }, + field4: { + 'ui:readonly': true, + }, + field5: { + 'ui:readonly': true, + }, }, field2: { 'ui:derp': 'xerp', diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts index c189bbf1a7..b4aa3e309d 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts @@ -26,7 +26,7 @@ function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { return; } - const { properties, anyOf } = schema; + const { properties, anyOf, oneOf, allOf } = schema; for (const propName in schema) { if (!schema.hasOwnProperty(propName)) { @@ -63,6 +63,24 @@ function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { extractUiSchema(schemaNode, uiSchema); } } + + if (Array.isArray(oneOf)) { + for (const schemaNode of oneOf) { + if (!isObject(schemaNode)) { + continue; + } + extractUiSchema(schemaNode, uiSchema); + } + } + + if (Array.isArray(allOf)) { + for (const schemaNode of allOf) { + if (!isObject(schemaNode)) { + continue; + } + extractUiSchema(schemaNode, uiSchema); + } + } } export function transformSchemaToProps( From e9e56b01ac3d115c81fc511c8f82afa36ce9a9c8 Mon Sep 17 00:00:00 2001 From: Jussi Hallila <jussi@hallila.com> Date: Thu, 29 Apr 2021 09:43:10 +0200 Subject: [PATCH 250/262] Add possibility to use path style discovery on S3 tech docs. Enables the possibility to support S3-like buckets that rely on path style API like Localstack. Signed-off-by: Jussi Hallila <jussi@hallila.com> --- .changeset/tricky-yaks-melt.md | 6 ++++++ .github/styles/vocab.txt | 2 ++ docs/features/techdocs/configuration.md | 5 +++++ packages/techdocs-common/src/stages/publish/awsS3.ts | 7 +++++++ plugins/techdocs-backend/config.d.ts | 7 +++++++ 5 files changed, 27 insertions(+) create mode 100644 .changeset/tricky-yaks-melt.md diff --git a/.changeset/tricky-yaks-melt.md b/.changeset/tricky-yaks-melt.md new file mode 100644 index 0000000000..3679e6d1da --- /dev/null +++ b/.changeset/tricky-yaks-melt.md @@ -0,0 +1,6 @@ +--- +'@backstage/techdocs-common': patch +--- + +Adding optional config to enable S3-like API for tech-docs using s3ForcePathStyle option. +This allows providers like LocalStack, Minio and Wasabi (+possibly others) to be used to host tech docs. diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index a12f638a74..694226b8cc 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -41,8 +41,10 @@ Kaewkasi Knex Leasot Lerna +LocalStack Luxon Minikube +Minio Mkdocs Monorepo Namespaces diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index c7876f3874..aa38dd42b1 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -78,6 +78,11 @@ techdocs: # https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property endpoint: ${AWS_ENDPOINT} + # (Optional) Whether to use path style URLs when communicating with S3. + # Defaults to false. + # This allows providers like LocalStack, Minio and Wasabi (and possibly others) to be used to host tech docs. + s3ForcePathStyle: false + # Required when techdocs.publisher.type is set to 'azureBlobStorage'. Skip otherwise. azureBlobStorage: diff --git a/packages/techdocs-common/src/stages/publish/awsS3.ts b/packages/techdocs-common/src/stages/publish/awsS3.ts index 9c6684fdca..d628c860fd 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.ts @@ -80,10 +80,17 @@ export class AwsS3Publish implements PublisherBase { 'techdocs.publisher.awsS3.endpoint', ); + // AWS forcePathStyle is an optional config. If missing, it defaults to false. Needs to be enabled for cases + // where endpoint url points to locally hosted S3 compatible storage like Localstack + const s3ForcePathStyle = config.getOptionalBoolean( + 'techdocs.publisher.awsS3.s3ForcePathStyle', + ); + const storageClient = new aws.S3({ credentials, ...(region && { region }), ...(endpoint && { endpoint }), + ...(s3ForcePathStyle && { s3ForcePathStyle }), }); return new AwsS3Publish(storageClient, bucketName, logger); diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index 83b79f2f6c..57dbb5108e 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -90,6 +90,13 @@ export interface Config { * @visibility secret */ endpoint?: string; + /** + * (Optional) Whether to use path style URLs when communicating with S3. + * Defaults to false. + * This allows providers like LocalStack, Minio and Wasabi (and possibly others) to be used to host tech docs. + * @visibility backend + */ + endpoint?: string; }; } | { From c6367d81afe6475568a2447d3c2fa85534ea489f Mon Sep 17 00:00:00 2001 From: blam <ben@blam.sh> Date: Thu, 29 Apr 2021 10:58:33 +0200 Subject: [PATCH 251/262] chore: updating variable names in terraform doc Signed-off-by: blam <ben@blam.sh> --- .../techdocs-s3-storage/terraform.tf | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/terraform/techdocs-s3-storage/terraform.tf b/contrib/terraform/techdocs-s3-storage/terraform.tf index ca267f0f12..f256663f43 100644 --- a/contrib/terraform/techdocs-s3-storage/terraform.tf +++ b/contrib/terraform/techdocs-s3-storage/terraform.tf @@ -2,15 +2,15 @@ # Variables #========================== -variable "backstage-bucket" { +variable "backstage_bucket" { default = "backstage_bucket_for_my_corp" } -variable "backstage-iam" { +variable "backstage_iam" { default = "backstage" } -variable "shared-managed-tag-value" { +variable "shared_managed_tag" { default = "terraform_for_my_corp" } @@ -19,7 +19,7 @@ variable "shared-managed-tag-value" { #========================== resource "aws_s3_bucket" "backstage" { - bucket = var.backstage-bucket + bucket = var.backstage_bucket acl = "private" provider = aws @@ -36,8 +36,8 @@ resource "aws_s3_bucket" "backstage" { } tags = { - Name = var.backstage-bucket - "Managed By Terraform" = var.shared-managed-tag-value + Name = var.backstage_bucket + "Managed By Terraform" = var.shared_managed_tag } } @@ -56,16 +56,16 @@ resource "aws_s3_bucket_public_access_block" "backstage" { #========================== resource "aws_iam_user" "backstage" { - name = var.backstage-iam + name = var.backstage_iam } resource "aws_iam_user_policy" "backstage" { - name = var.backstage-iam + name = var.backstage_iam user = aws_iam_user.backstage.name - policy = data.aws_iam_policy_document.backstage-policy.json + policy = data.aws_iam_policy_document.backstage_policy.json } -data "aws_iam_policy_document" "backstage-policy" { +data "aws_iam_policy_document" "backstage_policy" { statement { actions = [ "s3:PutObject", From a99e0bc42c08d81a5a01794baca372f726082860 Mon Sep 17 00:00:00 2001 From: Eric Peterson <iamEAP@users.noreply.github.com> Date: Thu, 29 Apr 2021 11:38:21 +0200 Subject: [PATCH 252/262] [Search] Improvements to DefaultCatalogCollator (#5491) * Add owner/lifecycle to default catalog document and allow location to be configured by integrators. Signed-off-by: Eric Peterson <ericpeterson@spotify.com> * Test the DefaultCatalogCollator Signed-off-by: Eric Peterson <ericpeterson@spotify.com> * Changeset. Signed-off-by: Eric Peterson <ericpeterson@spotify.com> --- .changeset/search-moar-catalog-yo.md | 5 + packages/backend/src/plugins/search.ts | 2 +- .../src/search/DefaultCatalogCollator.test.ts | 91 +++++++++++++++++++ .../src/search/DefaultCatalogCollator.ts | 37 ++++++-- 4 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 .changeset/search-moar-catalog-yo.md create mode 100644 plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts diff --git a/.changeset/search-moar-catalog-yo.md b/.changeset/search-moar-catalog-yo.md new file mode 100644 index 0000000000..4e665157e1 --- /dev/null +++ b/.changeset/search-moar-catalog-yo.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Entity lifecycle and owner are now indexed by the `DefaultCatalogCollator`. A `locationTemplate` may now optionally be provided to its constructor to reflect a custom catalog entity path in the Backstage frontend. diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index dcd48aaf40..1691f53485 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -32,7 +32,7 @@ export default async function createPlugin({ indexBuilder.addCollator({ type: 'software-catalog', defaultRefreshIntervalSeconds: 600, - collator: new DefaultCatalogCollator(discovery), + collator: new DefaultCatalogCollator({ discovery }), }); const { scheduler } = await indexBuilder.build(); diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts new file mode 100644 index 0000000000..0764912f0f --- /dev/null +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts @@ -0,0 +1,91 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { Entity } from '@backstage/catalog-model'; +import { DefaultCatalogCollator } from './DefaultCatalogCollator'; + +const expectedEntities: Entity[] = [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test-entity', + description: 'The expected description', + }, + spec: { + type: 'some-type', + lifecycle: 'experimental', + owner: 'someone', + }, + }, +]; + +jest.mock('cross-fetch', () => ({ + __esModule: true, + default: async () => { + return { + json: async () => { + return expectedEntities; + }, + }; + }, +})); + +describe('DefaultCatalogCollator', () => { + let mockDiscoveryApi: jest.Mocked<PluginEndpointDiscovery>; + let collator: DefaultCatalogCollator; + + beforeEach(() => { + mockDiscoveryApi = { + getBaseUrl: jest.fn().mockResolvedValueOnce('http://localhost:7000'), + getExternalBaseUrl: jest.fn(), + }; + collator = new DefaultCatalogCollator({ discovery: mockDiscoveryApi }); + }); + + it('fetches from the configured catalog service', async () => { + const documents = await collator.execute(); + expect(mockDiscoveryApi.getBaseUrl).toHaveBeenCalledWith('catalog'); + expect(documents).toHaveLength(expectedEntities.length); + }); + + it('maps a returned entity to an expected CatalogEntityDocument', async () => { + const documents = await collator.execute(); + expect(documents[0]).toMatchObject({ + title: expectedEntities[0].metadata.name, + location: '/catalog/default/component/test-entity', + text: expectedEntities[0].metadata.description, + namespace: 'default', + componentType: expectedEntities[0]!.spec!.type, + lifecycle: expectedEntities[0]!.spec!.lifecycle, + owner: expectedEntities[0]!.spec!.owner, + }); + }); + + it('maps a returned entity with a custom locationTemplate', async () => { + // Provide an alternate location template. + collator = new DefaultCatalogCollator({ + discovery: mockDiscoveryApi, + locationTemplate: '/software/:name', + }); + + const documents = await collator.execute(); + expect(documents[0]).toMatchObject({ + location: '/software/test-entity', + }); + }); +}); diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 72bf43f8f9..068b9e36ae 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -23,13 +23,35 @@ export interface CatalogEntityDocument extends IndexableDocument { componentType: string; namespace: string; kind: string; + lifecycle: string; + owner: string; } export class DefaultCatalogCollator implements DocumentCollator { protected discovery: PluginEndpointDiscovery; + protected locationTemplate: string; - constructor(discovery: PluginEndpointDiscovery) { + constructor({ + discovery, + locationTemplate, + }: { + discovery: PluginEndpointDiscovery; + locationTemplate?: string; + }) { this.discovery = discovery; + this.locationTemplate = + locationTemplate || '/catalog/:namespace/:kind/:name'; + } + + protected applyArgsToFormat( + format: string, + args: Record<string, string>, + ): string { + let formatted = format; + for (const [key, value] of Object.entries(args)) { + formatted = formatted.replace(`:${key}`, value); + } + return formatted.toLowerCase(); } async execute() { @@ -37,17 +59,20 @@ export class DefaultCatalogCollator implements DocumentCollator { const res = await fetch(`${baseUrl}/entities`); const entities: Entity[] = await res.json(); return entities.map( - (entity): CatalogEntityDocument => { + (entity: Entity): CatalogEntityDocument => { return { title: entity.metadata.name, - // TODO: Use a config-based template approach for entity location. - location: `/catalog/${ - entity.metadata.namespace || 'default' - }/component/${entity.metadata.name}`, + location: this.applyArgsToFormat(this.locationTemplate, { + namespace: entity.metadata.namespace || 'default', + kind: entity.kind, + name: entity.metadata.name, + }), text: entity.metadata.description || '', componentType: entity.spec?.type?.toString() || 'other', namespace: entity.metadata.namespace || 'default', kind: entity.kind, + lifecycle: (entity.spec?.lifecycle as string) || '', + owner: (entity.spec?.owner as string) || '', }; }, ); From 4b1ce5edb03474a862de13f78f541ab011b13543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Thu, 29 Apr 2021 12:19:57 +0200 Subject: [PATCH 253/262] fix master lint errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .../src/stages/publish/awsS3.test.ts | 55 ++++++++---------- .../stages/publish/azureBlobStorage.test.ts | 32 +++++------ .../src/stages/publish/googleStorage.test.ts | 53 ++++++++--------- .../src/stages/publish/googleStorage.ts | 2 +- .../src/stages/publish/openStackSwift.test.ts | 57 +++++++++---------- 5 files changed, 90 insertions(+), 109 deletions(-) diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index 15da3b7cfc..f094457346 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { getVoidLogger } from '@backstage/backend-common'; import { Entity, - ENTITY_DEFAULT_NAMESPACE, EntityName, + ENTITY_DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import mockFs from 'mock-fs'; @@ -154,7 +155,6 @@ describe('AwsS3Publish', () => { }); it('should fail to publish a directory', async () => { - expect.assertions(3); const wrongPathToGeneratedDirectory = path.join( rootDir, 'wrong', @@ -171,23 +171,22 @@ describe('AwsS3Publish', () => { }), ).rejects.toThrowError(); - await publisher - .publish({ - entity, - directory: wrongPathToGeneratedDirectory, - }) - .catch(error => { - expect(error.message).toEqual( - // Can not do exact error message match due to mockFs adding unexpected characters in the path when throwing the error - // Issue reported https://github.com/tschaub/mock-fs/issues/118 - expect.stringContaining( - `Unable to upload file(s) to AWS S3. Error: Failed to read template directory: ENOENT, no such file or directory`, - ), - ); - expect(error.message).toEqual( - expect.stringContaining(wrongPathToGeneratedDirectory), - ); - }); + const fails = publisher.publish({ + entity, + directory: wrongPathToGeneratedDirectory, + }); + + // Can not do exact error message match due to mockFs adding unexpected characters in the path when throwing the error + // Issue reported https://github.com/tschaub/mock-fs/issues/118 + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining( + 'Unable to upload file(s) to AWS S3. Error: Failed to read template directory: ENOENT, no such file or directory', + ), + }); + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining(wrongPathToGeneratedDirectory), + }); + mockFs.restore(); }); }); @@ -265,18 +264,12 @@ describe('AwsS3Publish', () => { const entity = createMockEntity(); const entityRootDir = getEntityRootDir(entity); - await publisher - .fetchTechDocsMetadata(entityNameMock) - .catch(error => - expect(error).toEqual( - new Error( - `TechDocs metadata fetch failed, The file ${path.join( - entityRootDir, - 'techdocs_metadata.json', - )} does not exist !`, - ), - ), - ); + const fails = publisher.fetchTechDocsMetadata(entityNameMock); + + const errorPath = path.join(entityRootDir, 'techdocs_metadata.json'); + await expect(fails).rejects.toMatchObject({ + message: `TechDocs metadata fetch failed, The file ${errorPath} does not exist !`, + }); }); }); }); diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts index c431e924a8..1160ffe49d 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { getVoidLogger } from '@backstage/backend-common'; import { Entity, - ENTITY_DEFAULT_NAMESPACE, EntityName, + ENTITY_DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import mockFs from 'mock-fs'; @@ -157,7 +158,6 @@ describe('publishing with valid credentials', () => { }); it('should fail to publish a directory', async () => { - expect.assertions(1); const wrongPathToGeneratedDirectory = path.join( rootDir, 'wrong', @@ -168,22 +168,20 @@ describe('publishing with valid credentials', () => { const entity = createMockEntity(); - await publisher - .publish({ - entity, - directory: wrongPathToGeneratedDirectory, - }) - .catch(error => { - // Can not do exact error message match due to mockFs adding unexpected characters in the path when throwing the error - // Issue reported https://github.com/tschaub/mock-fs/issues/118 - expect.stringContaining( - `Unable to upload file(s) to Azure Blob Storage. Error: Failed to read template directory: ENOENT, no such file or directory`, - ); + const fails = publisher.publish({ + entity, + directory: wrongPathToGeneratedDirectory, + }); + + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining( + `Unable to upload file(s) to Azure Blob Storage. Error: Failed to read template directory: ENOENT, no such file or directory`, + ), + }); + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining(wrongPathToGeneratedDirectory), + }); - expect(error.message).toEqual( - expect.stringContaining(wrongPathToGeneratedDirectory), - ); - }); mockFs.restore(); }); diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index 7e580b16bc..19e4938763 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { getVoidLogger } from '@backstage/backend-common'; import { Entity, @@ -146,8 +147,6 @@ describe('GoogleGCSPublish', () => { }); it('should fail to publish a directory', async () => { - expect.assertions(3); - const wrongPathToGeneratedDirectory = path.join( rootDir, 'wrong', @@ -165,23 +164,21 @@ describe('GoogleGCSPublish', () => { }), ).rejects.toThrowError(); - await publisher - .publish({ - entity, - directory: wrongPathToGeneratedDirectory, - }) - .catch(error => { - expect(error.message).toEqual( - // Can not do exact error message match due to mockFs adding unexpected characters in the path when throwing the error - // Issue reported https://github.com/tschaub/mock-fs/issues/118 - expect.stringContaining( - `Unable to upload file(s) to Google Cloud Storage. Error: Failed to read template directory: ENOENT, no such file or directory`, - ), - ); - expect(error.message).toEqual( - expect.stringContaining(wrongPathToGeneratedDirectory), - ); - }); + const fails = publisher.publish({ + entity, + directory: wrongPathToGeneratedDirectory, + }); + + // Can not do exact error message match due to mockFs adding unexpected characters in the path when throwing the error + // Issue reported https://github.com/tschaub/mock-fs/issues/118 + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining( + `Unable to upload file(s) to Google Cloud Storage. Error: Failed to read template directory: ENOENT, no such file or directory`, + ), + }); + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining(wrongPathToGeneratedDirectory), + }); mockFs.restore(); }); @@ -264,16 +261,14 @@ describe('GoogleGCSPublish', () => { const entity = createMockEntity(); const entityRootDir = getEntityRootDir(entity); - await publisher - .fetchTechDocsMetadata(entityNameMock) - .catch(errorMessage => - expect(errorMessage).toEqual( - `The file ${path.join( - entityRootDir, - 'techdocs_metadata.json', - )} does not exist !`, - ), - ); + const fails = publisher.fetchTechDocsMetadata(entityNameMock); + + await expect(fails).rejects.toMatchObject({ + message: `The file ${path.join( + entityRootDir, + 'techdocs_metadata.json', + )} does not exist !`, + }); }); }); }); diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index 28fbb42ece..8adafc361a 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -168,7 +168,7 @@ export class GoogleGCSPublish implements PublisherBase { .createReadStream() .on('error', err => { this.logger.error(err.message); - reject(err.message); + reject(err); }) .on('data', chunk => { fileStreamChunks.push(chunk); diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts index 6f0aacede0..e179aeb9a7 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { getVoidLogger } from '@backstage/backend-common'; import { Entity, - ENTITY_DEFAULT_NAMESPACE, EntityName, + ENTITY_DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import mockFs from 'mock-fs'; @@ -157,7 +158,6 @@ describe('OpenStackSwiftPublish', () => { }); it('should fail to publish a directory', async () => { - expect.assertions(3); const wrongPathToGeneratedDirectory = path.join( rootDir, 'wrong', @@ -174,23 +174,22 @@ describe('OpenStackSwiftPublish', () => { }), ).rejects.toThrowError(); - await publisher - .publish({ - entity, - directory: wrongPathToGeneratedDirectory, - }) - .catch(error => { - expect(error.message).toEqual( - // Can not do exact error message match due to mockFs adding unexpected characters in the path when throwing the error - // Issue reported https://github.com/tschaub/mock-fs/issues/118 - expect.stringContaining( - `Unable to upload file(s) to OpenStack Swift. Error: Failed to read template directory: ENOENT, no such file or directory`, - ), - ); - expect(error.message).toEqual( - expect.stringContaining(wrongPathToGeneratedDirectory), - ); - }); + const fails = publisher.publish({ + entity, + directory: wrongPathToGeneratedDirectory, + }); + + // Can not do exact error message match due to mockFs adding unexpected characters in the path when throwing the error + // Issue reported https://github.com/tschaub/mock-fs/issues/118 + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining( + `Unable to upload file(s) to OpenStack Swift. Error: Failed to read template directory: ENOENT, no such file or directory`, + ), + }); + await expect(fails).rejects.toMatchObject({ + message: expect.stringContaining(wrongPathToGeneratedDirectory), + }); + mockFs.restore(); }); }); @@ -268,18 +267,14 @@ describe('OpenStackSwiftPublish', () => { const entity = createMockEntity(); const entityRootDir = getEntityRootDir(entity); - await publisher - .fetchTechDocsMetadata(entityNameMock) - .catch(error => - expect(error).toEqual( - new Error( - `TechDocs metadata fetch failed, The file ${path.join( - entityRootDir, - 'techdocs_metadata.json', - )} does not exist !`, - ), - ), - ); + const fails = publisher.fetchTechDocsMetadata(entityNameMock); + + await expect(fails).rejects.toMatchObject({ + message: `TechDocs metadata fetch failed, The file ${path.join( + entityRootDir, + 'techdocs_metadata.json', + )} does not exist !`, + }); }); }); }); From 6179bff5f08b71359f0deece5d2068f2ecc168bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Thu, 29 Apr 2021 12:59:42 +0200 Subject: [PATCH 254/262] depend on core, not core-api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- plugins/catalog/package.json | 1 - plugins/catalog/src/components/EntityLayout/EntityLayout.tsx | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index d87ca5b7d9..b6b306c260 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -33,7 +33,6 @@ "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", "@backstage/core": "^0.7.6", - "@backstage/core-api": "^0.2.17", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index e3a8a89b71..dfd27631f8 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -20,6 +20,7 @@ import { RELATION_OWNED_BY, } from '@backstage/catalog-model'; import { + attachComponentData, Content, Header, HeaderLabel, @@ -34,12 +35,11 @@ import { getEntityRelations, useEntityCompoundName, } from '@backstage/plugin-catalog-react'; -import { attachComponentData } from '@backstage/core-api'; import { Box, TabProps } from '@material-ui/core'; import { Alert } from '@material-ui/lab'; import { - default as React, Children, + default as React, Fragment, isValidElement, useContext, From 44abfaada67300d542caead0a505df4d664c074a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 11:32:12 +0000 Subject: [PATCH 255/262] Version Packages --- .changeset/calm-zebras-remain.md | 7 ---- .../cost-insights-gorgeous-dancers-hope.md | 5 --- .changeset/empty-lizards-doubt.md | 5 --- .changeset/gentle-days-return.md | 21 ---------- .changeset/healthy-phones-press.md | 5 --- .changeset/kind-suns-melt.md | 5 --- .changeset/little-trees-fold.md | 5 --- .changeset/long-ladybugs-promise.md | 5 --- .changeset/pink-islands-help.md | 5 --- .changeset/rare-parrots-share.md | 6 --- .changeset/search-moar-catalog-yo.md | 5 --- .changeset/search-odd-ads-invite.md | 5 --- .changeset/six-rocks-allow.md | 5 --- .changeset/sixty-dragons-retire.md | 5 --- .changeset/small-snakes-shake.md | 5 --- .changeset/small-ways-hunt.md | 6 --- .changeset/techdocs-lovely-wombats-relate.md | 6 --- .changeset/techdocs-mean-humans-hammer.md | 5 --- .changeset/techdocs-quiet-pens-prove.md | 5 --- .changeset/techdocs-red-donkeys-share.md | 5 --- .changeset/techdocs-swift-waves-sleep.md | 12 ------ .changeset/techdocs-young-walls-decide.md | 5 --- .changeset/thin-coins-compete.md | 5 --- .changeset/thirty-humans-knock.md | 5 --- .changeset/tough-planes-jump.md | 5 --- .changeset/witty-lies-shave.md | 5 --- packages/app/CHANGELOG.md | 42 +++++++++++++++++++ packages/app/package.json | 36 ++++++++-------- packages/core/CHANGELOG.md | 8 ++++ packages/core/package.json | 2 +- packages/create-app/CHANGELOG.md | 39 +++++++++++++++++ packages/create-app/package.json | 2 +- packages/techdocs-common/CHANGELOG.md | 6 +++ packages/techdocs-common/package.json | 2 +- plugins/api-docs/CHANGELOG.md | 14 +++++++ plugins/api-docs/package.json | 4 +- plugins/badges/package.json | 2 +- plugins/bitrise/CHANGELOG.md | 10 +++++ plugins/bitrise/package.json | 4 +- plugins/catalog-backend/CHANGELOG.md | 8 ++++ plugins/catalog-backend/package.json | 4 +- plugins/catalog-import/CHANGELOG.md | 10 +++++ plugins/catalog-import/package.json | 4 +- plugins/catalog/CHANGELOG.md | 13 ++++++ plugins/catalog/package.json | 4 +- plugins/circleci/CHANGELOG.md | 10 +++++ plugins/circleci/package.json | 4 +- plugins/cloudbuild/package.json | 2 +- plugins/code-coverage-backend/CHANGELOG.md | 6 +++ plugins/code-coverage-backend/package.json | 2 +- plugins/code-coverage/package.json | 2 +- plugins/config-schema/package.json | 2 +- plugins/cost-insights/CHANGELOG.md | 11 +++++ plugins/cost-insights/package.json | 4 +- plugins/explore/CHANGELOG.md | 10 +++++ plugins/explore/package.json | 4 +- plugins/fossa/CHANGELOG.md | 10 +++++ plugins/fossa/package.json | 4 +- plugins/gcp-projects/package.json | 2 +- plugins/github-actions/CHANGELOG.md | 11 +++++ plugins/github-actions/package.json | 4 +- plugins/github-deployments/CHANGELOG.md | 10 +++++ plugins/github-deployments/package.json | 4 +- plugins/gitops-profiles/package.json | 2 +- plugins/graphiql/CHANGELOG.md | 10 +++++ plugins/graphiql/package.json | 4 +- plugins/jenkins/CHANGELOG.md | 10 +++++ plugins/jenkins/package.json | 4 +- plugins/kafka/package.json | 2 +- plugins/kubernetes/package.json | 2 +- plugins/lighthouse/CHANGELOG.md | 10 +++++ plugins/lighthouse/package.json | 4 +- plugins/newrelic/package.json | 2 +- plugins/org/package.json | 2 +- plugins/pagerduty/CHANGELOG.md | 10 +++++ plugins/pagerduty/package.json | 4 +- plugins/register-component/CHANGELOG.md | 10 +++++ plugins/register-component/package.json | 4 +- plugins/rollbar/CHANGELOG.md | 10 +++++ plugins/rollbar/package.json | 4 +- plugins/scaffolder-backend/CHANGELOG.md | 6 +++ plugins/scaffolder-backend/package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 12 ++++++ plugins/scaffolder/package.json | 4 +- plugins/search-backend-node/CHANGELOG.md | 6 +++ plugins/search-backend-node/package.json | 2 +- plugins/search/CHANGELOG.md | 10 +++++ plugins/search/package.json | 4 +- plugins/sentry/CHANGELOG.md | 10 +++++ plugins/sentry/package.json | 4 +- plugins/sonarqube/CHANGELOG.md | 10 +++++ plugins/sonarqube/package.json | 4 +- plugins/splunk-on-call/package.json | 2 +- plugins/tech-radar/package.json | 2 +- plugins/techdocs/CHANGELOG.md | 26 ++++++++++++ plugins/techdocs/package.json | 4 +- plugins/todo/package.json | 2 +- plugins/user-settings/package.json | 2 +- plugins/welcome/package.json | 2 +- 99 files changed, 441 insertions(+), 241 deletions(-) delete mode 100644 .changeset/calm-zebras-remain.md delete mode 100644 .changeset/cost-insights-gorgeous-dancers-hope.md delete mode 100644 .changeset/empty-lizards-doubt.md delete mode 100644 .changeset/gentle-days-return.md delete mode 100644 .changeset/healthy-phones-press.md delete mode 100644 .changeset/kind-suns-melt.md delete mode 100644 .changeset/little-trees-fold.md delete mode 100644 .changeset/long-ladybugs-promise.md delete mode 100644 .changeset/pink-islands-help.md delete mode 100644 .changeset/rare-parrots-share.md delete mode 100644 .changeset/search-moar-catalog-yo.md delete mode 100644 .changeset/search-odd-ads-invite.md delete mode 100644 .changeset/six-rocks-allow.md delete mode 100644 .changeset/sixty-dragons-retire.md delete mode 100644 .changeset/small-snakes-shake.md delete mode 100644 .changeset/small-ways-hunt.md delete mode 100644 .changeset/techdocs-lovely-wombats-relate.md delete mode 100644 .changeset/techdocs-mean-humans-hammer.md delete mode 100644 .changeset/techdocs-quiet-pens-prove.md delete mode 100644 .changeset/techdocs-red-donkeys-share.md delete mode 100644 .changeset/techdocs-swift-waves-sleep.md delete mode 100644 .changeset/techdocs-young-walls-decide.md delete mode 100644 .changeset/thin-coins-compete.md delete mode 100644 .changeset/thirty-humans-knock.md delete mode 100644 .changeset/tough-planes-jump.md delete mode 100644 .changeset/witty-lies-shave.md diff --git a/.changeset/calm-zebras-remain.md b/.changeset/calm-zebras-remain.md deleted file mode 100644 index 3b961ab3f2..0000000000 --- a/.changeset/calm-zebras-remain.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Resolve issues with AsyncAPI rendering by updating `@asyncapi/react-component` -to `0.23.0`. The theming of the component is adjusted to the latest styling -changes. diff --git a/.changeset/cost-insights-gorgeous-dancers-hope.md b/.changeset/cost-insights-gorgeous-dancers-hope.md deleted file mode 100644 index 8e0abce57f..0000000000 --- a/.changeset/cost-insights-gorgeous-dancers-hope.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -Support a `name` prop for Projects for display purposes diff --git a/.changeset/empty-lizards-doubt.md b/.changeset/empty-lizards-doubt.md deleted file mode 100644 index cfe1e128fc..0000000000 --- a/.changeset/empty-lizards-doubt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-actions': patch ---- - -Wrap EmptyState in Card diff --git a/.changeset/gentle-days-return.md b/.changeset/gentle-days-return.md deleted file mode 100644 index 96552173bd..0000000000 --- a/.changeset/gentle-days-return.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch -'@backstage/plugin-bitrise': patch -'@backstage/plugin-catalog-import': patch -'@backstage/plugin-circleci': patch -'@backstage/plugin-cost-insights': patch -'@backstage/plugin-explore': patch -'@backstage/plugin-fossa': patch -'@backstage/plugin-github-actions': patch -'@backstage/plugin-github-deployments': patch -'@backstage/plugin-graphiql': patch -'@backstage/plugin-jenkins': patch -'@backstage/plugin-lighthouse': patch -'@backstage/plugin-pagerduty': patch -'@backstage/plugin-register-component': patch -'@backstage/plugin-rollbar': patch -'@backstage/plugin-sentry': patch -'@backstage/plugin-sonarqube': patch ---- - -Updated README to have up-to-date install instructions. diff --git a/.changeset/healthy-phones-press.md b/.changeset/healthy-phones-press.md deleted file mode 100644 index c771caefc5..0000000000 --- a/.changeset/healthy-phones-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Allow passing NavLinkProps to SidebarItem component to use in NavLink diff --git a/.changeset/kind-suns-melt.md b/.changeset/kind-suns-melt.md deleted file mode 100644 index 7cbec28fea..0000000000 --- a/.changeset/kind-suns-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Added fields filtering in get API entities to avoid the requesting of unused data diff --git a/.changeset/little-trees-fold.md b/.changeset/little-trees-fold.md deleted file mode 100644 index 4963dd5aa1..0000000000 --- a/.changeset/little-trees-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Updates the end to end test in the app to match the new catalog index page title. To apply this change to an existing app, update `packages/app/cypress/integration/app.js` to search for `"My Company Catalog"` instead of `"My Company Service Catalog"`. diff --git a/.changeset/long-ladybugs-promise.md b/.changeset/long-ladybugs-promise.md deleted file mode 100644 index 7d683650c3..0000000000 --- a/.changeset/long-ladybugs-promise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Enable starred templates on Scaffolder frontend diff --git a/.changeset/pink-islands-help.md b/.changeset/pink-islands-help.md deleted file mode 100644 index c7672f484f..0000000000 --- a/.changeset/pink-islands-help.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage-backend': patch ---- - -Include migrations diff --git a/.changeset/rare-parrots-share.md b/.changeset/rare-parrots-share.md deleted file mode 100644 index 917ec5a18e..0000000000 --- a/.changeset/rare-parrots-share.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog': patch -'@backstage/plugin-scaffolder': patch ---- - -Removed unused `swr` dependency. diff --git a/.changeset/search-moar-catalog-yo.md b/.changeset/search-moar-catalog-yo.md deleted file mode 100644 index 4e665157e1..0000000000 --- a/.changeset/search-moar-catalog-yo.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Entity lifecycle and owner are now indexed by the `DefaultCatalogCollator`. A `locationTemplate` may now optionally be provided to its constructor to reflect a custom catalog entity path in the Backstage frontend. diff --git a/.changeset/search-odd-ads-invite.md b/.changeset/search-odd-ads-invite.md deleted file mode 100644 index 0dde3d0c1f..0000000000 --- a/.changeset/search-odd-ads-invite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-node': patch ---- - -Introduced Scheduler which is responsible for adding new tasks to a schedule together with it's interval timer as well as starting and stopping the scheduler processes. diff --git a/.changeset/six-rocks-allow.md b/.changeset/six-rocks-allow.md deleted file mode 100644 index f207654f45..0000000000 --- a/.changeset/six-rocks-allow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/techdocs-common': patch ---- - -Gracefully handle HTTP request failures in download method of AzureBlobStorage publisher. diff --git a/.changeset/sixty-dragons-retire.md b/.changeset/sixty-dragons-retire.md deleted file mode 100644 index 62965c6e88..0000000000 --- a/.changeset/sixty-dragons-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Use `RouteRef` to generate path to search page. diff --git a/.changeset/small-snakes-shake.md b/.changeset/small-snakes-shake.md deleted file mode 100644 index 6db9db3754..0000000000 --- a/.changeset/small-snakes-shake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Support `gridItem` variant for `EntityLinksCard`. diff --git a/.changeset/small-ways-hunt.md b/.changeset/small-ways-hunt.md deleted file mode 100644 index f0b8dc88cc..0000000000 --- a/.changeset/small-ways-hunt.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core': patch -'@backstage/plugin-catalog': patch ---- - -Add `if` prop to `EntityLayout.Route` to conditionally render tabs diff --git a/.changeset/techdocs-lovely-wombats-relate.md b/.changeset/techdocs-lovely-wombats-relate.md deleted file mode 100644 index 33ed205c89..0000000000 --- a/.changeset/techdocs-lovely-wombats-relate.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Use `EntityRefLink` in header and use relations to reference the owner of the -document. diff --git a/.changeset/techdocs-mean-humans-hammer.md b/.changeset/techdocs-mean-humans-hammer.md deleted file mode 100644 index 7697650250..0000000000 --- a/.changeset/techdocs-mean-humans-hammer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Fix TechDocs landing page table wrong copied link diff --git a/.changeset/techdocs-quiet-pens-prove.md b/.changeset/techdocs-quiet-pens-prove.md deleted file mode 100644 index 379c20e72a..0000000000 --- a/.changeset/techdocs-quiet-pens-prove.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Add customization and exportable components for TechDocs landing page diff --git a/.changeset/techdocs-red-donkeys-share.md b/.changeset/techdocs-red-donkeys-share.md deleted file mode 100644 index 29d932d0b8..0000000000 --- a/.changeset/techdocs-red-donkeys-share.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Disable color transitions on links to avoid issues in dark mode. diff --git a/.changeset/techdocs-swift-waves-sleep.md b/.changeset/techdocs-swift-waves-sleep.md deleted file mode 100644 index 79d10931cd..0000000000 --- a/.changeset/techdocs-swift-waves-sleep.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-techdocs': minor ---- - -Make `techdocsStorageApiRef` and `techdocsApiRef` use interfaces instead of the -actual implementation classes. - -This renames the classes `TechDocsApi` to `TechDocsClient` and `TechDocsStorageApi` -to `TechDocsStorageClient` and renames the interfaces `TechDocs` to `TechDocsApi` -and `TechDocsStorage` to `TechDocsStorageApi` to comply the pattern elsewhere in -the project. This also fixes the types returned by some methods on those -interfaces. diff --git a/.changeset/techdocs-young-walls-decide.md b/.changeset/techdocs-young-walls-decide.md deleted file mode 100644 index 8dc0373234..0000000000 --- a/.changeset/techdocs-young-walls-decide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Rework state management to avoid rendering multiple while navigating between pages. diff --git a/.changeset/thin-coins-compete.md b/.changeset/thin-coins-compete.md deleted file mode 100644 index 36511ec1cb..0000000000 --- a/.changeset/thin-coins-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Added the `nebula-preview` preview to `Octokit` for repository visibility. diff --git a/.changeset/thirty-humans-knock.md b/.changeset/thirty-humans-knock.md deleted file mode 100644 index 47545af282..0000000000 --- a/.changeset/thirty-humans-knock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core': patch ---- - -Improve owner example value in `MissingAnnotationEmptyState`. diff --git a/.changeset/tough-planes-jump.md b/.changeset/tough-planes-jump.md deleted file mode 100644 index ebbec65159..0000000000 --- a/.changeset/tough-planes-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Support `anyOf`, `oneOf` and `allOf` schemas in the scaffolder template. diff --git a/.changeset/witty-lies-shave.md b/.changeset/witty-lies-shave.md deleted file mode 100644 index 68fd4b1137..0000000000 --- a/.changeset/witty-lies-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Switch out the time-based personal greeting for a plain title on the catalog index page, and remove the clocks for different timezones. diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 7262b2ae29..e9d3e63ad0 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,47 @@ # example-app +## 0.2.26 + +### Patch Changes + +- Updated dependencies [1ce80ff02] +- Updated dependencies [b98de52ae] +- Updated dependencies [4c42ecca2] +- Updated dependencies [c614ede9a] +- Updated dependencies [9afcac5af] +- Updated dependencies [07a7806c3] +- Updated dependencies [f6efa71ee] +- Updated dependencies [19a4dd710] +- Updated dependencies [dcd54c7cd] +- Updated dependencies [da546ce00] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6fbd7beca] +- Updated dependencies [15cbe6815] +- Updated dependencies [39bdaa004] +- Updated dependencies [cb8c848a3] +- Updated dependencies [21fddf452] +- Updated dependencies [17915e29b] +- Updated dependencies [6eaecbd81] +- Updated dependencies [23769512a] +- Updated dependencies [1a142ae8a] + - @backstage/plugin-api-docs@0.4.12 + - @backstage/plugin-cost-insights@0.8.5 + - @backstage/plugin-github-actions@0.4.4 + - @backstage/plugin-catalog-import@0.5.4 + - @backstage/plugin-circleci@0.2.13 + - @backstage/plugin-explore@0.3.4 + - @backstage/plugin-graphiql@0.2.10 + - @backstage/plugin-jenkins@0.4.2 + - @backstage/plugin-lighthouse@0.2.15 + - @backstage/plugin-pagerduty@0.3.3 + - @backstage/plugin-rollbar@0.3.4 + - @backstage/plugin-sentry@0.3.9 + - @backstage/core@0.7.7 + - @backstage/plugin-scaffolder@0.9.2 + - @backstage/plugin-catalog@0.5.6 + - @backstage/plugin-search@0.3.5 + - @backstage/plugin-techdocs@0.9.0 + ## 0.2.25 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index ba9af03310..402d09ade4 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,39 +1,39 @@ { "name": "example-app", - "version": "0.2.25", + "version": "0.2.26", "private": true, "bundled": true, "dependencies": { "@backstage/catalog-model": "^0.7.7", "@backstage/cli": "^0.6.9", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/integration-react": "^0.1.1", - "@backstage/plugin-api-docs": "^0.4.11", + "@backstage/plugin-api-docs": "^0.4.12", "@backstage/plugin-badges": "^0.2.0", - "@backstage/plugin-catalog": "^0.5.5", - "@backstage/plugin-catalog-import": "^0.5.3", + "@backstage/plugin-catalog": "^0.5.6", + "@backstage/plugin-catalog-import": "^0.5.4", "@backstage/plugin-catalog-react": "^0.1.3", - "@backstage/plugin-circleci": "^0.2.12", + "@backstage/plugin-circleci": "^0.2.13", "@backstage/plugin-cloudbuild": "^0.2.13", "@backstage/plugin-code-coverage": "^0.1.2", - "@backstage/plugin-cost-insights": "^0.8.4", - "@backstage/plugin-explore": "^0.3.2", + "@backstage/plugin-cost-insights": "^0.8.5", + "@backstage/plugin-explore": "^0.3.4", "@backstage/plugin-gcp-projects": "^0.2.5", - "@backstage/plugin-github-actions": "^0.4.2", - "@backstage/plugin-graphiql": "^0.2.9", - "@backstage/plugin-jenkins": "^0.4.1", + "@backstage/plugin-github-actions": "^0.4.4", + "@backstage/plugin-graphiql": "^0.2.10", + "@backstage/plugin-jenkins": "^0.4.2", "@backstage/plugin-kafka": "^0.2.6", "@backstage/plugin-kubernetes": "^0.4.2", - "@backstage/plugin-lighthouse": "^0.2.14", + "@backstage/plugin-lighthouse": "^0.2.15", "@backstage/plugin-newrelic": "^0.2.6", "@backstage/plugin-org": "^0.3.12", - "@backstage/plugin-pagerduty": "0.3.2", - "@backstage/plugin-rollbar": "^0.3.3", - "@backstage/plugin-scaffolder": "^0.9.1", - "@backstage/plugin-search": "^0.3.4", - "@backstage/plugin-sentry": "^0.3.8", + "@backstage/plugin-pagerduty": "0.3.3", + "@backstage/plugin-rollbar": "^0.3.4", + "@backstage/plugin-scaffolder": "^0.9.2", + "@backstage/plugin-search": "^0.3.5", + "@backstage/plugin-sentry": "^0.3.9", "@backstage/plugin-tech-radar": "^0.3.9", - "@backstage/plugin-techdocs": "^0.8.0", + "@backstage/plugin-techdocs": "^0.9.0", "@backstage/plugin-todo": "^0.1.0", "@backstage/plugin-user-settings": "^0.2.8", "@backstage/theme": "^0.2.6", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 1b556ac1c3..974dcd3b91 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/core +## 0.7.7 + +### Patch Changes + +- 9afcac5af: Allow passing NavLinkProps to SidebarItem component to use in NavLink +- e0c9ed759: Add `if` prop to `EntityLayout.Route` to conditionally render tabs +- 6eaecbd81: Improve owner example value in `MissingAnnotationEmptyState`. + ## 0.7.6 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 344ea10398..59391e122a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core", "description": "Core API used by Backstage plugins and apps", - "version": "0.7.6", + "version": "0.7.7", "private": false, "publishConfig": { "access": "public", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index c821a3ab81..430e7f003a 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/create-app +## 0.3.20 + +### Patch Changes + +- 73f3f5d78: Updates the end to end test in the app to match the new catalog index page title. To apply this change to an existing app, update `packages/app/cypress/integration/app.js` to search for `"My Company Catalog"` instead of `"My Company Service Catalog"`. +- Updated dependencies [1ce80ff02] +- Updated dependencies [4c42ecca2] +- Updated dependencies [c614ede9a] +- Updated dependencies [9afcac5af] +- Updated dependencies [07a7806c3] +- Updated dependencies [f6efa71ee] +- Updated dependencies [19a4dd710] +- Updated dependencies [a99e0bc42] +- Updated dependencies [dcd54c7cd] +- Updated dependencies [da546ce00] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6fbd7beca] +- Updated dependencies [15cbe6815] +- Updated dependencies [39bdaa004] +- Updated dependencies [cb8c848a3] +- Updated dependencies [21fddf452] +- Updated dependencies [17915e29b] +- Updated dependencies [a1783f306] +- Updated dependencies [6eaecbd81] +- Updated dependencies [23769512a] +- Updated dependencies [1a142ae8a] + - @backstage/plugin-api-docs@0.4.12 + - @backstage/plugin-github-actions@0.4.4 + - @backstage/plugin-catalog-import@0.5.4 + - @backstage/plugin-explore@0.3.4 + - @backstage/plugin-lighthouse@0.2.15 + - @backstage/core@0.7.7 + - @backstage/plugin-scaffolder@0.9.2 + - @backstage/plugin-catalog@0.5.6 + - @backstage/plugin-catalog-backend@0.8.1 + - @backstage/plugin-search@0.3.5 + - @backstage/plugin-techdocs@0.9.0 + - @backstage/plugin-scaffolder-backend@0.10.1 + ## 0.3.19 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 5cf6cdd78e..071a0a5ebd 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "Create app package for Backstage", - "version": "0.3.19", + "version": "0.3.20", "private": false, "publishConfig": { "access": "public" diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md index 9dd6447a14..1788502e45 100644 --- a/packages/techdocs-common/CHANGELOG.md +++ b/packages/techdocs-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/techdocs-common +## 0.5.1 + +### Patch Changes + +- f4af06ebe: Gracefully handle HTTP request failures in download method of AzureBlobStorage publisher. + ## 0.5.0 ### Minor Changes diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index c41dce72b1..e749b33919 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.5.0", + "version": "0.5.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index a2d5a28e41..f268ba1c4d 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-api-docs +## 0.4.12 + +### Patch Changes + +- 1ce80ff02: Resolve issues with AsyncAPI rendering by updating `@asyncapi/react-component` + to `0.23.0`. The theming of the component is adjusted to the latest styling + changes. +- c614ede9a: Updated README to have up-to-date install instructions. +- 07a7806c3: Added fields filtering in get API entities to avoid the requesting of unused data +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.4.11 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 532dacf684..5c9f9ca7ee 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.4.11", + "version": "0.4.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "dependencies": { "@asyncapi/react-component": "^0.23.0", "@backstage/catalog-model": "^0.7.7", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.6", "@material-icons/font": "^1.0.2", diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 9f0c49af7e..8f7b5865a1 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.6", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/theme": "^0.2.6", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 66314933bb..ecb26efd50 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-bitrise +## 0.1.2 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.1.1 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 83911cdfc4..950392f732 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bitrise", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.2", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 28efc1c5d3..ed87e4dbc5 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend +## 0.8.1 + +### Patch Changes + +- a99e0bc42: Entity lifecycle and owner are now indexed by the `DefaultCatalogCollator`. A `locationTemplate` may now optionally be provided to its constructor to reflect a custom catalog entity path in the Backstage frontend. +- Updated dependencies [e1e757569] + - @backstage/plugin-search-backend-node@0.1.4 + ## 0.8.0 ### Minor Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index a5bb9e00af..7649067a44 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.8.0", + "version": "0.8.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,7 +35,7 @@ "@backstage/config": "^0.1.4", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", - "@backstage/plugin-search-backend-node": "^0.1.3", + "@backstage/plugin-search-backend-node": "^0.1.4", "@backstage/search-common": "^0.1.1", "@octokit/graphql": "^4.5.8", "@types/express": "^4.17.6", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 8c189a5f9b..4b0d264a52 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-import +## 0.5.4 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.5.3 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 9ba32d830c..ca540fe8be 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.5.3", + "version": "0.5.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.6", "@backstage/catalog-client": "^0.3.9", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/integration": "^0.5.0", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 35e000f130..d6254a347a 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog +## 0.5.6 + +### Patch Changes + +- 19a4dd710: Removed unused `swr` dependency. +- da546ce00: Support `gridItem` variant for `EntityLinksCard`. +- e0c9ed759: Add `if` prop to `EntityLayout.Route` to conditionally render tabs +- 1a142ae8a: Switch out the time-based personal greeting for a plain title on the catalog index page, and remove the clocks for different timezones. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.5.5 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 965a0b327b..4f54735611 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.5.5", + "version": "0.5.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "dependencies": { "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index ff01f44258..8c6d6e094d 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-circleci +## 0.2.13 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.2.12 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 5c05c0ee6f..20c757eda0 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-circleci", - "version": "0.2.12", + "version": "0.2.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 6ad0b8bfa9..cb2a08fce1 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -32,7 +32,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/plugin-catalog-react": "^0.1.2", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index cfc08db5c4..d7a0f136f5 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-code-coverage-backend +## 0.1.3 + +### Patch Changes + +- d47c2628b: Include migrations + ## 0.1.2 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 3ae76e3fe0..c2bebbf293 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-coverage-backend", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 1adc94fff7..f5c36811cc 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -22,7 +22,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.6", diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 55f785a7a4..a017529400 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/errors": "^0.1.1", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 47fa9633bf..c86a71f8c9 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cost-insights +## 0.8.5 + +### Patch Changes + +- b98de52ae: Support a `name` prop for Projects for display purposes +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.8.4 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index c68fdde509..39e3fe1791 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.8.4", + "version": "0.8.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/config": "^0.1.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index bebf6a8c44..78275577f5 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-explore +## 0.3.4 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.3.3 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 7c2eb5c90d..be61bc1fd9 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/plugin-explore-react": "^0.0.4", "@backstage/theme": "^0.2.6", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index fe916804d2..bd7af91dca 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-fossa +## 0.2.6 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.2.5 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 23f9cfde74..ba7e1a381e 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-fossa", - "version": "0.2.5", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.6", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 509576cf2b..0930c791e4 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index a2c6e6bf1f..6896a7f877 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-github-actions +## 0.4.4 + +### Patch Changes + +- 4c42ecca2: Wrap EmptyState in Card +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.4.3 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 6a95803d6f..2c26061cf3 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-actions", - "version": "0.4.3", + "version": "0.4.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,7 +34,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.5", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/integration": "^0.5.1", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index e7f849ef2e..23c8943349 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-github-deployments +## 0.1.4 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.1.3 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 12a36c160e..049e02de4c 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-deployments", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.6", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index ae614fe504..d1897b018c 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 67e39d6600..681005b13f 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-graphiql +## 0.2.10 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.2.9 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 4aa26587ad..9ce1603b57 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.9", + "version": "0.2.10", "private": false, "publishConfig": { "access": "public", @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index ab57d71f61..ac734e9a95 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-jenkins +## 0.4.2 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.4.1 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index edee4bc2ee..d1cabd2143 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins", - "version": "0.4.1", + "version": "0.4.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index a7295469d6..0963d3178f 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 03013e1480..8d21c79a24 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -33,7 +33,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.4", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/plugin-kubernetes-backend": "^0.3.2", "@backstage/theme": "^0.2.6", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 26eb041442..cb2cb5b9d1 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-lighthouse +## 0.2.15 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.2.14 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 45980df00c..2fce507756 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-lighthouse", - "version": "0.2.14", + "version": "0.2.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 0951d972c2..2dbb2a7eb8 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/org/package.json b/plugins/org/package.json index 5bed02e9c8..9ad4704630 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.6", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/core-api": "^0.2.16", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.6", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 0cd9d0cfb8..b7fc7fec40 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-pagerduty +## 0.3.3 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.3.2 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index c0e3afec34..821b89a5b1 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-pagerduty", - "version": "0.3.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/register-component/CHANGELOG.md b/plugins/register-component/CHANGELOG.md index 424887263c..3634972e9a 100644 --- a/plugins/register-component/CHANGELOG.md +++ b/plugins/register-component/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-register-component +## 0.2.14 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.2.13 ### Patch Changes diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index 2870ef79f1..38d1e3202e 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-register-component", - "version": "0.2.13", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 2e9bc946a2..1d8c2c399e 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-rollbar +## 0.3.4 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.3.3 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 6d654866af..64ea010b54 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index cb1855e041..f591568d44 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-scaffolder-backend +## 0.10.1 + +### Patch Changes + +- a1783f306: Added the `nebula-preview` preview to `Octokit` for repository visibility. + ## 0.10.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 729ef58d99..355bed4de0 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.10.0", + "version": "0.10.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index fee76f8775..1d0bbcede9 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder +## 0.9.2 + +### Patch Changes + +- f6efa71ee: Enable starred templates on Scaffolder frontend +- 19a4dd710: Removed unused `swr` dependency. +- 23769512a: Support `anyOf`, `oneOf` and `allOf` schemas in the scaffolder template. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.9.1 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 2b4feecb7b..3c2c308c24 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.9.1", + "version": "0.9.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "@backstage/catalog-client": "^0.3.10", "@backstage/catalog-model": "^0.7.7", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index e7a9d9aa0a..da49bd0726 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-search-backend-node +## 0.1.4 + +### Patch Changes + +- e1e757569: Introduced Scheduler which is responsible for adding new tasks to a schedule together with it's interval timer as well as starting and stopping the scheduler processes. + ## 0.1.3 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index b5d13af01c..e39fbb5579 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-node", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 35f3ee97c1..b4bcd1f855 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search +## 0.3.5 + +### Patch Changes + +- dcd54c7cd: Use `RouteRef` to generate path to search page. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.3.4 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index c7ab201efe..2b9db3444e 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "0.3.4", + "version": "0.3.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/catalog-model": "^0.7.3", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/search-common": "^0.1.1", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index dc45bcae60..261972384a 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sentry +## 0.3.9 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.3.8 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 9908af2e24..e34d8bcef9 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry", - "version": "0.3.8", + "version": "0.3.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 0ed86737dd..48b9292791 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sonarqube +## 0.1.17 + +### Patch Changes + +- c614ede9a: Updated README to have up-to-date install instructions. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.1.16 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 97243bb930..c31b99bac8 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube", - "version": "0.1.16", + "version": "0.1.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,7 +34,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index ecaf21f8eb..9e93004bf5 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.4", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 5a1c2e2095..37ad7d8211 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 4f89cd9844..847121c0cf 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-techdocs +## 0.9.0 + +### Minor Changes + +- 21fddf452: Make `techdocsStorageApiRef` and `techdocsApiRef` use interfaces instead of the + actual implementation classes. + + This renames the classes `TechDocsApi` to `TechDocsClient` and `TechDocsStorageApi` + to `TechDocsStorageClient` and renames the interfaces `TechDocs` to `TechDocsApi` + and `TechDocsStorage` to `TechDocsStorageApi` to comply the pattern elsewhere in + the project. This also fixes the types returned by some methods on those + interfaces. + +### Patch Changes + +- 6fbd7beca: Use `EntityRefLink` in header and use relations to reference the owner of the + document. +- 15cbe6815: Fix TechDocs landing page table wrong copied link +- 39bdaa004: Add customization and exportable components for TechDocs landing page +- cb8c848a3: Disable color transitions on links to avoid issues in dark mode. +- 17915e29b: Rework state management to avoid rendering multiple while navigating between pages. +- Updated dependencies [9afcac5af] +- Updated dependencies [e0c9ed759] +- Updated dependencies [6eaecbd81] + - @backstage/core@0.7.7 + ## 0.8.0 ### Minor Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 7bde151663..632feac3c1 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "0.8.0", + "version": "0.9.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "dependencies": { "@backstage/config": "^0.1.4", "@backstage/catalog-model": "^0.7.7", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.6", "@backstage/errors": "^0.1.1", diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 7339e568c3..92390857ef 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.6", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index d410dc103e..08ae87d3ec 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json index b276b86835..189b6eeb59 100644 --- a/plugins/welcome/package.json +++ b/plugins/welcome/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.7.6", + "@backstage/core": "^0.7.7", "@backstage/theme": "^0.2.6", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", From 86891fd2742b8b7624cb80619781aff0383b3385 Mon Sep 17 00:00:00 2001 From: Will Sewell <willsewell@monzo.com> Date: Thu, 29 Apr 2021 12:36:41 +0100 Subject: [PATCH 256/262] Rename 'param' -> 'parameter' in changeset Signed-off-by: Will Sewell <willsewell@monzo.com> --- .changeset/twenty-peas-deny.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/twenty-peas-deny.md b/.changeset/twenty-peas-deny.md index df335ea95a..d149a9337c 100644 --- a/.changeset/twenty-peas-deny.md +++ b/.changeset/twenty-peas-deny.md @@ -2,4 +2,4 @@ '@backstage/catalog-client': patch --- -Allow `filter` param to be specified multiple times +Allow `filter` parameter to be specified multiple times From b2e2ec75337768330b277365bfc689cbc77188b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= <freben@gmail.com> Date: Thu, 29 Apr 2021 15:43:53 +0200 Subject: [PATCH 257/262] Update tech radar README for composability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw <freben@gmail.com> --- .changeset/spotty-pigs-bathe.md | 5 +++++ plugins/tech-radar/README.md | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 .changeset/spotty-pigs-bathe.md diff --git a/.changeset/spotty-pigs-bathe.md b/.changeset/spotty-pigs-bathe.md new file mode 100644 index 0000000000..0585f335dc --- /dev/null +++ b/.changeset/spotty-pigs-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-radar': patch +--- + +Update README for composability diff --git a/plugins/tech-radar/README.md b/plugins/tech-radar/README.md index 21f90ec432..7f97f88ed4 100644 --- a/plugins/tech-radar/README.md +++ b/plugins/tech-radar/README.md @@ -18,7 +18,7 @@ It serves and scales well for teams and companies of all sizes that want to have The Tech Radar can be used in two ways: -- **Simple (Recommended)** - This gives you an out-of-the-box Tech Radar experience. It lives on the `/tech-radar` URL of your Backstage installation, and you can set a variety of configuration directly in your `apis.ts`. +- **Simple (Recommended)** - This gives you an out-of-the-box Tech Radar experience. It lives on the `/tech-radar` URL of your Backstage installation. - **Advanced** - This gives you the React UI component directly. It enables you to insert the Radar on your own layout or page for a more customized feel. ### Install @@ -26,6 +26,7 @@ The Tech Radar can be used in two ways: For either simple or advanced installations, you'll need to add the dependency using Yarn: ```sh +cd packages/app yarn add @backstage/plugin-tech-radar ``` @@ -34,17 +35,16 @@ yarn add @backstage/plugin-tech-radar Modify your app routes to include the Router component exported from the tech radar, for example: ```tsx -import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; +// in packages/app/src/App.tsx +import { TechRadarPage } from '@backstage/plugin-tech-radar'; -// Inside App component -<Routes> - {/* other routes ... */} - <Route - path="/tech-radar" - element={<TechRadarRouter width={1500} height={800} />} - /> - {/* other routes ... */} -</Routes>; +const routes = ( + <FlatRoutes> + {/* ... */} + <Route + path="/tech-radar" + element={<TechRadarPage width={1500} height={800} />} + /> ``` If you'd like to configure it more, see the `TechRadarPageProps` and `TechRadarComponentProps` types for options: From 4e6168da41070c0f58d2f7bf95ed7a433a6e5f52 Mon Sep 17 00:00:00 2001 From: Will Sewell <willsewell@monzo.com> Date: Thu, 29 Apr 2021 16:16:24 +0100 Subject: [PATCH 258/262] Update public API docs Result of running `yarn build:api-reports`. Signed-off-by: Will Sewell <willsewell@monzo.com> --- packages/catalog-client/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index a17a6cdc10..4b489ff2e4 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -67,7 +67,7 @@ export class CatalogClient implements CatalogApi { // @public (undocumented) export type CatalogEntitiesRequest = { - filter?: Record<string, string | string[]> | undefined; + filter?: Record<string, string | string[]>[] | Record<string, string | string[]> | undefined; fields?: string[] | undefined; }; From 7c8a0c1b09a2d8319a7d5daad63b80d6eb2bea3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Apr 2021 04:08:24 +0000 Subject: [PATCH 259/262] chore(deps-dev): bump @types/luxon from 1.26.0 to 1.26.5 Bumps [@types/luxon](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/luxon) from 1.26.0 to 1.26.5. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/luxon) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e5bbc026c6..6d1cabbc22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6295,9 +6295,9 @@ integrity sha512-09sXZZVsB3Ib41U0fC+O1O+4UOZT1bl/e+/QubPxpqDWHNEchvx/DEb1KJMOwq6K3MTNzZFoNSzVdR++o1DVnw== "@types/luxon@^1.25.0": - version "1.26.0" - resolved "https://registry.npmjs.org/@types/luxon/-/luxon-1.26.0.tgz#8e783986370ad3bb9f885d93eb1a91caeecaed36" - integrity sha512-zYmLYGczqBaOFaFjR1giG1QCbGMlXWOJcYgH9Mnk0MGcZHq1aer3ZwGXX8vd9NOfai6mAI/mVU6jD9hK0Wys7Q== + version "1.26.5" + resolved "https://registry.npmjs.org/@types/luxon/-/luxon-1.26.5.tgz#843fb705e16e4d2a90847a351b799ea9d879859e" + integrity sha512-XeQxxRMyJi1znfzHw4CGDLyup/raj84SnjjkI2fDootZPGlB0yqtvlvEIAmzHDa5wiEI5JJevZOWxpcofsaV+A== "@types/markdown-to-jsx@^6.11.0": version "6.11.2" From 799c1d69cf4e009e603c215cf788553e7c927508 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Apr 2021 04:11:42 +0000 Subject: [PATCH 260/262] chore(deps-dev): bump start-server-and-test from 1.12.0 to 1.12.1 Bumps [start-server-and-test](https://github.com/bahmutov/start-server-and-test) from 1.12.0 to 1.12.1. - [Release notes](https://github.com/bahmutov/start-server-and-test/releases) - [Commits](https://github.com/bahmutov/start-server-and-test/compare/v1.12.0...v1.12.1) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index e5bbc026c6..0fd3ad76c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24297,9 +24297,9 @@ stacktrace-js@^2.0.0, stacktrace-js@^2.0.2: stacktrace-gps "^3.0.4" start-server-and-test@^1.10.11: - version "1.12.0" - resolved "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.12.0.tgz#e836553c928a13026f79c740757d378b92bee8d6" - integrity sha512-y3M/PLUPkPBsgKoengMIMQeceT8uOnOc4bkdor/RSCK9Ih/j8z4WthSCrAboXLjgtJJWOporAiEQsnYox+THXg== + version "1.12.1" + resolved "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.12.1.tgz#bf84eb5c5a4c8a98b93ed36519035b3f76179f0e" + integrity sha512-qGQ2HQiF2yDIfyaHsXkHfoE5UOl4zJUbJ/gx2xOkfX7iPMXW9qHmoFyaMfIDJVLNkxCK7RxSrvWEI9hNVKQluw== dependencies: bluebird "3.7.2" check-more-types "2.24.0" @@ -24307,7 +24307,7 @@ start-server-and-test@^1.10.11: execa "3.4.0" lazy-ass "1.6.0" ps-tree "1.2.0" - wait-on "5.2.1" + wait-on "5.3.0" start-server-webpack-plugin@^2.2.5: version "2.2.5" @@ -26420,14 +26420,14 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -wait-on@5.2.1: - version "5.2.1" - resolved "https://registry.npmjs.org/wait-on/-/wait-on-5.2.1.tgz#05b66fcb4d7f5da01537f03e7cf96e8836422996" - integrity sha512-H2F986kNWMU9hKlI9l/ppO6tN8ZSJd35yBljMLa1/vjzWP++Qh6aXyt77/u7ySJFZQqBtQxnvm/xgG48AObXcw== +wait-on@5.3.0: + version "5.3.0" + resolved "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz#584e17d4b3fe7b46ac2b9f8e5e102c005c2776c7" + integrity sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg== dependencies: axios "^0.21.1" joi "^17.3.0" - lodash "^4.17.20" + lodash "^4.17.21" minimist "^1.2.5" rxjs "^6.6.3" From d8d22dd9332ba4cbfd413e199526580a398c2418 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Apr 2021 04:14:12 +0000 Subject: [PATCH 261/262] chore(deps-dev): bump @types/passport-google-oauth20 from 2.0.3 to 2.0.7 Bumps [@types/passport-google-oauth20](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/passport-google-oauth20) from 2.0.3 to 2.0.7. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/passport-google-oauth20) Signed-off-by: dependabot[bot] <support@github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e5bbc026c6..3723040450 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6453,9 +6453,9 @@ "@types/passport-oauth2" "*" "@types/passport-google-oauth20@^2.0.3": - version "2.0.3" - resolved "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.3.tgz#f554ff6d39f395acff3f1d762e54462194dac8da" - integrity sha512-6EUEGzEg4acwowvgR/yVZIj8S2Kkwc6JmlY2/wnM1wJHNz20o7s1TIGrxnah8ymLgJasYDpy95P3TMMqlmetPw== + version "2.0.7" + resolved "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.7.tgz#0d97b7a886a0c0d2158682145cd949b29f8efe86" + integrity sha512-0HPVSqDmOWk5fRLb+bqGal+6iWsERiEco/Mli77yy5NEy22IfkoRoqZTSZ8UtXDWY9DCZlpS1Jqq56iWx2torw== dependencies: "@types/express" "*" "@types/passport" "*" From a1351acc87647697b59604d7f34832af2c3140d8 Mon Sep 17 00:00:00 2001 From: Raghunandan <soapraj@gmail.com> Date: Fri, 30 Apr 2021 13:46:35 +0200 Subject: [PATCH 262/262] awsS3 option endpoint -> s3ForcePathStyle Signed-off-by: Raghunandan <soapraj@gmail.com> --- plugins/techdocs-backend/config.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index 57dbb5108e..6a76172638 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -96,7 +96,7 @@ export interface Config { * This allows providers like LocalStack, Minio and Wasabi (and possibly others) to be used to host tech docs. * @visibility backend */ - endpoint?: string; + s3ForcePathStyle?: boolean; }; } | {