From 0b793b6717a631fa2bd7650b670834e5268e8ae6 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Date: Thu, 11 Mar 2021 11:53:13 +0100 Subject: [PATCH 001/395] 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/395] 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/395] 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/395] 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/395] 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/395] 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/395] 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/395] 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/395] 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/395] 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 958d97c4dd6b66590372d5175e353fe2600409d6 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 26 Mar 2021 23:21:12 -0400 Subject: [PATCH 011/395] Added catalog-model support for dependsOn to Component and dependencyOf to Resource. Updated relevant relationship generator entity processors, and system diagram support. Signed-off-by: Jonah Grimes --- .../components/artist-lookup-component.yaml | 2 + .../src/kinds/ComponentEntityV1alpha1.test.ts | 21 ++++++++++ .../src/kinds/ComponentEntityV1alpha1.ts | 1 + .../src/kinds/ResourceEntityV1alpha1.test.ts | 21 ++++++++++ .../src/kinds/ResourceEntityV1alpha1.ts | 1 + .../kinds/Component.v1alpha1.schema.json | 8 ++++ .../kinds/Resource.v1alpha1.schema.json | 8 ++++ .../BuiltinKindsEntityProcessor.test.ts | 38 ++++++++++++++++++- .../processors/BuiltinKindsEntityProcessor.ts | 14 +++++++ .../SystemDiagramCard/SystemDiagramCard.tsx | 14 ++++++- 10 files changed, 125 insertions(+), 3 deletions(-) diff --git a/packages/catalog-model/examples/components/artist-lookup-component.yaml b/packages/catalog-model/examples/components/artist-lookup-component.yaml index edd9b8fcf9..713fd8fadb 100644 --- a/packages/catalog-model/examples/components/artist-lookup-component.yaml +++ b/packages/catalog-model/examples/components/artist-lookup-component.yaml @@ -32,4 +32,6 @@ spec: type: service lifecycle: experimental owner: team-a + dependsOn: + - artists-db system: artist-engagement-portal diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts index 9284a5d5b1..19bc168223 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts @@ -36,6 +36,7 @@ describe('ComponentV1alpha1Validator', () => { subcomponentOf: 'monolith', providesApis: ['api-0'], consumesApis: ['api-0'], + dependsOn: ['resource-0'], system: 'system', }, }; @@ -160,6 +161,26 @@ describe('ComponentV1alpha1Validator', () => { await expect(validator.check(entity)).resolves.toBe(true); }); + it('accepts missing dependsOn', async () => { + delete (entity as any).spec.dependsOn; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('rejects empty dependsOn', async () => { + (entity as any).spec.dependsOn = ['']; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); + }); + + it('rejects undefined dependsOn', async () => { + (entity as any).spec.dependsOn = [undefined]; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); + }); + + it('accepts no dependsOn', async () => { + (entity as any).spec.dependsOn = []; + await expect(validator.check(entity)).resolves.toBe(true); + }); + it('accepts missing system', async () => { delete (entity as any).spec.system; await expect(validator.check(entity)).resolves.toBe(true); diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts index 3006a4288c..489aa8b1bd 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts @@ -34,6 +34,7 @@ export interface ComponentEntityV1alpha1 extends Entity { subcomponentOf?: string; providesApis?: string[]; consumesApis?: string[]; + dependsOn?: string[]; system?: string; }; } diff --git a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts index ad8ea5cdf3..076288628a 100644 --- a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts @@ -32,6 +32,7 @@ describe('ResourceV1alpha1Validator', () => { spec: { type: 'database', owner: 'me', + dependencyOf: ['component-0'], system: 'system', }, }; @@ -86,6 +87,26 @@ describe('ResourceV1alpha1Validator', () => { await expect(validator.check(entity)).rejects.toThrow(/owner/); }); + it('accepts missing dependencyOf', async () => { + delete (entity as any).spec.dependencyOf; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('rejects empty dependencyOf', async () => { + (entity as any).spec.dependencyOf = ['']; + await expect(validator.check(entity)).rejects.toThrow(/dependencyOf/); + }); + + it('rejects undefined dependencyOf', async () => { + (entity as any).spec.dependencyOf = [undefined]; + await expect(validator.check(entity)).rejects.toThrow(/dependencyOf/); + }); + + it('accepts no dependencyOf', async () => { + (entity as any).spec.dependencyOf = []; + await expect(validator.check(entity)).resolves.toBe(true); + }); + it('accepts missing system', async () => { delete (entity as any).spec.system; await expect(validator.check(entity)).resolves.toBe(true); diff --git a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts index 520a39f02c..0b3662b91f 100644 --- a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts @@ -30,6 +30,7 @@ export interface ResourceEntityV1alpha1 extends Entity { spec: { type: string; owner: string; + dependencyOf?: string[]; system?: string; }; } diff --git a/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json index 822059a0ea..e2b98d5c3b 100644 --- a/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json @@ -84,6 +84,14 @@ "type": "string", "minLength": 1 } + }, + "dependsOn": { + "type": "array", + "description": "An array of entity references to the resources that the component depends on.", + "items": { + "type": "string", + "minLength": 1 + } } } } diff --git a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json index b426dd7f94..dbe9c969f3 100644 --- a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json @@ -47,6 +47,14 @@ "examples": ["artist-relations-team", "user:john.johnson"], "minLength": 1 }, + "dependencyOf": { + "type": "array", + "description": "An array of entity references to the components that the resource is a dependency of.", + "items": { + "type": "string", + "minLength": 1 + } + }, "system": { "type": "string", "description": "An entity reference to the system that the resource belongs to.", diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts index feb4791477..2d61191aa8 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts @@ -45,13 +45,14 @@ describe('BuiltinKindsEntityProcessor', () => { lifecycle: 'l', providesApis: ['b'], consumesApis: ['c'], + dependsOn: ['r'], system: 's', }, }; await processor.postProcessEntity(entity, location, emit); - expect(emit).toBeCalledTimes(10); + expect(emit).toBeCalledTimes(12); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -100,6 +101,22 @@ describe('BuiltinKindsEntityProcessor', () => { target: { kind: 'API', namespace: 'default', name: 'c' }, }, }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'r' }, + type: 'dependencyOf', + target: { kind: 'Component', namespace: 'default', name: 'n' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'n' }, + type: 'dependsOn', + target: { kind: 'Resource', namespace: 'default', name: 'r' }, + }, + }); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -193,13 +210,14 @@ describe('BuiltinKindsEntityProcessor', () => { spec: { type: 'database', owner: 'o', + dependencyOf: ['c'], system: 's', }, }; await processor.postProcessEntity(entity, location, emit); - expect(emit).toBeCalledTimes(4); + expect(emit).toBeCalledTimes(6); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -216,6 +234,22 @@ describe('BuiltinKindsEntityProcessor', () => { target: { kind: 'Group', namespace: 'default', name: 'o' }, }, }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'n' }, + type: 'dependencyOf', + target: { kind: 'Component', namespace: 'default', name: 'c' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'c' }, + type: 'dependsOn', + target: { kind: 'Resource', namespace: 'default', name: 'n' }, + }, + }); expect(emit).toBeCalledWith({ type: 'relation', relation: { diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts index 26a8538707..d1de992a81 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts @@ -32,6 +32,8 @@ import { RELATION_API_PROVIDED_BY, RELATION_CHILD_OF, RELATION_CONSUMES_API, + RELATION_DEPENDENCY_OF, + RELATION_DEPENDS_ON, RELATION_HAS_MEMBER, RELATION_HAS_PART, RELATION_MEMBER_OF, @@ -146,6 +148,12 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { RELATION_CONSUMES_API, RELATION_API_CONSUMED_BY, ); + doEmit( + component.spec.dependsOn, + { defaultKind: 'Resource', defaultNamespace: selfRef.namespace }, + RELATION_DEPENDS_ON, + RELATION_DEPENDENCY_OF, + ); doEmit( component.spec.system, { defaultKind: 'System', defaultNamespace: selfRef.namespace }, @@ -186,6 +194,12 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { RELATION_OWNED_BY, RELATION_OWNER_OF, ); + doEmit( + resource.spec.dependencyOf, + { defaultKind: 'Component', defaultNamespace: selfRef.namespace }, + RELATION_DEPENDENCY_OF, + RELATION_DEPENDS_ON, + ); doEmit( resource.spec.system, { defaultKind: 'System', defaultNamespace: selfRef.namespace }, diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index df20e910aa..78288c46e9 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -16,6 +16,7 @@ import { Entity, + RELATION_DEPENDS_ON, RELATION_PROVIDES_API, RELATION_PART_OF, serializeEntityRef, @@ -124,7 +125,6 @@ export function SystemDiagramCard() { catalogItem, RELATION_PROVIDES_API, ); - catalogItemRelations_providesApi.forEach(foundRelation => systemEdges.push({ from: simplifiedEntityName(catalogItem), @@ -132,6 +132,18 @@ export function SystemDiagramCard() { label: 'provides API', }), ); + + const catalogItemRelations_dependsOn = getEntityRelations( + catalogItem, + RELATION_DEPENDS_ON, + ); + catalogItemRelations_dependsOn.forEach(foundRelation => + systemEdges.push({ + from: simplifiedEntityName(catalogItem), + to: simplifiedEntityName(foundRelation), + label: 'depends on', + }), + ); } } From 372f9e80c6f6d742c4125d3a0fbc218ecbf35bdc Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 26 Mar 2021 23:47:01 -0400 Subject: [PATCH 012/395] Rolled back changes to examples in catalog-model to maintain compatibility with demo Signed-off-by: Jonah Grimes --- .../examples/components/artist-lookup-component.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/catalog-model/examples/components/artist-lookup-component.yaml b/packages/catalog-model/examples/components/artist-lookup-component.yaml index 713fd8fadb..edd9b8fcf9 100644 --- a/packages/catalog-model/examples/components/artist-lookup-component.yaml +++ b/packages/catalog-model/examples/components/artist-lookup-component.yaml @@ -32,6 +32,4 @@ spec: type: service lifecycle: experimental owner: team-a - dependsOn: - - artists-db system: artist-engagement-portal From ba4beaca821de91e89807ffae76c6377ca892f0b Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 26 Mar 2021 23:21:12 -0400 Subject: [PATCH 013/395] Added catalog-model support for dependsOn to Component and dependencyOf to Resource. Updated relevant relationship generator entity processors, and system diagram support. Signed-off-by: Jonah Grimes --- .../examples/components/artist-lookup-component.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/catalog-model/examples/components/artist-lookup-component.yaml b/packages/catalog-model/examples/components/artist-lookup-component.yaml index edd9b8fcf9..713fd8fadb 100644 --- a/packages/catalog-model/examples/components/artist-lookup-component.yaml +++ b/packages/catalog-model/examples/components/artist-lookup-component.yaml @@ -32,4 +32,6 @@ spec: type: service lifecycle: experimental owner: team-a + dependsOn: + - artists-db system: artist-engagement-portal From 9b18984cab80bb5b4cbecc6a8b526fae501d3aa6 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 26 Mar 2021 23:47:01 -0400 Subject: [PATCH 014/395] Rolled back changes to examples in catalog-model to maintain compatibility with demo Signed-off-by: Jonah Grimes --- .../examples/components/artist-lookup-component.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/catalog-model/examples/components/artist-lookup-component.yaml b/packages/catalog-model/examples/components/artist-lookup-component.yaml index 713fd8fadb..edd9b8fcf9 100644 --- a/packages/catalog-model/examples/components/artist-lookup-component.yaml +++ b/packages/catalog-model/examples/components/artist-lookup-component.yaml @@ -32,6 +32,4 @@ spec: type: service lifecycle: experimental owner: team-a - dependsOn: - - artists-db system: artist-engagement-portal From 5d074056394413a9976a55d4f4ea4e35fa272e17 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Sat, 27 Mar 2021 00:06:27 -0400 Subject: [PATCH 015/395] added changeset for dependsOn/dependencyOf Signed-off-by: Jonah Grimes --- .changeset/red-planets-hammer.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/red-planets-hammer.md diff --git a/.changeset/red-planets-hammer.md b/.changeset/red-planets-hammer.md new file mode 100644 index 0000000000..19938e0d3d --- /dev/null +++ b/.changeset/red-planets-hammer.md @@ -0,0 +1,7 @@ +--- +'@backstage/catalog-model': minor +'@backstage/plugin-catalog-backend': minor +'@backstage/plugin-catalog': patch +--- + +Implemented missing support for the dependsOn/dependencyOf relationships between Component and Resource catalog model objects. Added support for generating the relevant relationships to the BuiltinKindsEntityProcessor, and added simple support for fetching relationships between Components and Resources for rendering in the system diagram. All catalog-model changes backwards compatible. From 098cfb74b97961b9a953b84703b02b364d8afc95 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Sat, 27 Mar 2021 00:25:06 -0400 Subject: [PATCH 016/395] updated documentation to account for new relationship specifications in the catalog model Signed-off-by: Jonah Grimes --- .../software-catalog/descriptor-format.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index e4b046d76f..668b139d6a 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -519,6 +519,15 @@ consumed by the component, e.g. `artist-api`. This field is optional. | --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------- | | [`API`](#kind-api) (default) | Same as this entity, typically `default` | [`consumesApi`, and reverse `apiConsumedBy`](well-known-relations.md#consumesapi-and-apiconsumedby) | +### `spec.dependsOn` [optional] + +An array of [entity references](#string-references) to the Resources that the +component depends on, e.g. `artists-db`. This field is optional. + +| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | +| --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | +| [`Resource`](#kind-resource) (default) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | + ## Kind: Template The following describes the following entity kind: @@ -1001,6 +1010,15 @@ belongs to, e.g. `artist-engagement-portal`. This field is optional. | --------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------- | | [`System`](#kind-system) (default) | Same as this entity, typically `default` | [`partOf`, and reverse `hasPart`](well-known-relations.md#partof-and-haspart) | +### `spec.dependencyOf` [optional] + +An array of [entity references](#string-references) to the Components that the +resource is a dependency of, e.g. `artist-lookup`. This field is optional. + +| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | +| ---------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | +| [`Component`](#kind-component) (default) | Same as this entity, typically `default` | [`dependencyOf`, and reverse `dependsOn`](well-known-relations.md#dependson-and-dependencyof) | + ## Kind: System Describes the following entity kind: From b886314e2897bcf4e3a33e2eee7c805bd70eee2f Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Sat, 27 Mar 2021 09:05:08 -0400 Subject: [PATCH 017/395] updated changeset to patch for all affected packages/plugins Signed-off-by: Jonah Grimes --- .changeset/red-planets-hammer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/red-planets-hammer.md b/.changeset/red-planets-hammer.md index 19938e0d3d..780ef533f1 100644 --- a/.changeset/red-planets-hammer.md +++ b/.changeset/red-planets-hammer.md @@ -1,6 +1,6 @@ --- -'@backstage/catalog-model': minor -'@backstage/plugin-catalog-backend': minor +'@backstage/catalog-model': patch +'@backstage/plugin-catalog-backend': patch '@backstage/plugin-catalog': patch --- From c8b60c4b4d39df860b429a08d0454912ff029772 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Mon, 29 Mar 2021 12:57:53 -0400 Subject: [PATCH 018/395] reformatted changeset Signed-off-by: Jonah Grimes --- .changeset/red-planets-hammer.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.changeset/red-planets-hammer.md b/.changeset/red-planets-hammer.md index 780ef533f1..eb72314556 100644 --- a/.changeset/red-planets-hammer.md +++ b/.changeset/red-planets-hammer.md @@ -4,4 +4,10 @@ '@backstage/plugin-catalog': patch --- -Implemented missing support for the dependsOn/dependencyOf relationships between Component and Resource catalog model objects. Added support for generating the relevant relationships to the BuiltinKindsEntityProcessor, and added simple support for fetching relationships between Components and Resources for rendering in the system diagram. All catalog-model changes backwards compatible. +Implemented missing support for the dependsOn/dependencyOf relationships +between `Component` and `Resource` catalog model objects. + +Added support for generating the relevant relationships to the +`BuiltinKindsEntityProcessor`, and added simple support for fetching +relationships between `Components` and `Resources` for rendering in the +system diagram. All catalog-model changes backwards compatible. From d5e059a3c89ee5a43987717cd29cdc6ca5723784 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Wed, 31 Mar 2021 10:01:39 -0400 Subject: [PATCH 019/395] removed dependencyOf reverse specification of dependencies, added dependsOn support at the Resource entity level, removed default entity reference kind for dependsOn, updated documentation Signed-off-by: Jonah Grimes --- .../software-catalog/descriptor-format.md | 22 +++-- .../src/kinds/ComponentEntityV1alpha1.test.ts | 2 +- .../src/kinds/ResourceEntityV1alpha1.test.ts | 22 ++--- .../src/kinds/ResourceEntityV1alpha1.ts | 2 +- .../kinds/Resource.v1alpha1.schema.json | 2 +- .../BuiltinKindsEntityProcessor.test.ts | 91 +++++++++++++++++-- .../processors/BuiltinKindsEntityProcessor.ts | 27 ++++-- 7 files changed, 131 insertions(+), 37 deletions(-) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 668b139d6a..16829b6716 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -521,12 +521,14 @@ consumed by the component, e.g. `artist-api`. This field is optional. ### `spec.dependsOn` [optional] -An array of [entity references](#string-references) to the Resources that the -component depends on, e.g. `artists-db`. This field is optional. +An array of [entity references](#string-references) to the components and +resources that the component depends on, e.g. `artists-db`. This field is +optional. | [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | | --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | -| [`Resource`](#kind-resource) (default) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | +| [`Component`](#kind-component) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | +| [`Resource`](#kind-resource) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | ## Kind: Template @@ -1010,14 +1012,16 @@ belongs to, e.g. `artist-engagement-portal`. This field is optional. | --------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------- | | [`System`](#kind-system) (default) | Same as this entity, typically `default` | [`partOf`, and reverse `hasPart`](well-known-relations.md#partof-and-haspart) | -### `spec.dependencyOf` [optional] +### `spec.dependsOn` [optional] -An array of [entity references](#string-references) to the Components that the -resource is a dependency of, e.g. `artist-lookup`. This field is optional. +An array of [entity references](#string-references) to the components and +resources that the resource depends on, e.g. `artist-lookup`. This field is +optional. -| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | -| ---------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | -| [`Component`](#kind-component) (default) | Same as this entity, typically `default` | [`dependencyOf`, and reverse `dependsOn`](well-known-relations.md#dependson-and-dependencyof) | +| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | +| --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | +| [`Component`](#kind-component) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | +| [`Resource`](#kind-resource) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | ## Kind: System diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts index 19bc168223..358e7b6526 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts @@ -36,7 +36,7 @@ describe('ComponentV1alpha1Validator', () => { subcomponentOf: 'monolith', providesApis: ['api-0'], consumesApis: ['api-0'], - dependsOn: ['resource-0'], + dependsOn: ['resource:resource-0', 'component:component-0'], system: 'system', }, }; diff --git a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts index 076288628a..953ec5889a 100644 --- a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts @@ -32,7 +32,7 @@ describe('ResourceV1alpha1Validator', () => { spec: { type: 'database', owner: 'me', - dependencyOf: ['component-0'], + dependsOn: ['component:component-0', 'resource:resource-0'], system: 'system', }, }; @@ -87,23 +87,23 @@ describe('ResourceV1alpha1Validator', () => { await expect(validator.check(entity)).rejects.toThrow(/owner/); }); - it('accepts missing dependencyOf', async () => { - delete (entity as any).spec.dependencyOf; + it('accepts missing dependsOn', async () => { + delete (entity as any).spec.dependsOn; await expect(validator.check(entity)).resolves.toBe(true); }); - it('rejects empty dependencyOf', async () => { - (entity as any).spec.dependencyOf = ['']; - await expect(validator.check(entity)).rejects.toThrow(/dependencyOf/); + it('rejects empty dependsOn', async () => { + (entity as any).spec.dependsOn = ['']; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); }); - it('rejects undefined dependencyOf', async () => { - (entity as any).spec.dependencyOf = [undefined]; - await expect(validator.check(entity)).rejects.toThrow(/dependencyOf/); + it('rejects undefined dependsOn', async () => { + (entity as any).spec.dependsOn = [undefined]; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); }); - it('accepts no dependencyOf', async () => { - (entity as any).spec.dependencyOf = []; + it('accepts no dependsOn', async () => { + (entity as any).spec.dependsOn = []; await expect(validator.check(entity)).resolves.toBe(true); }); diff --git a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts index 0b3662b91f..fd71500f40 100644 --- a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts @@ -30,7 +30,7 @@ export interface ResourceEntityV1alpha1 extends Entity { spec: { type: string; owner: string; - dependencyOf?: string[]; + dependsOn?: string[]; system?: string; }; } diff --git a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json index dbe9c969f3..2dcf6f4eb2 100644 --- a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json @@ -47,7 +47,7 @@ "examples": ["artist-relations-team", "user:john.johnson"], "minLength": 1 }, - "dependencyOf": { + "dependsOn": { "type": "array", "description": "An array of entity references to the components that the resource is a dependency of.", "items": { diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts index 2d61191aa8..ad446c6a7a 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts @@ -45,14 +45,14 @@ describe('BuiltinKindsEntityProcessor', () => { lifecycle: 'l', providesApis: ['b'], consumesApis: ['c'], - dependsOn: ['r'], + dependsOn: ['Resource:r', 'Component:d'], system: 's', }, }; await processor.postProcessEntity(entity, location, emit); - expect(emit).toBeCalledTimes(12); + expect(emit).toBeCalledTimes(14); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -101,6 +101,14 @@ describe('BuiltinKindsEntityProcessor', () => { target: { kind: 'API', namespace: 'default', name: 'c' }, }, }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'n' }, + type: 'dependsOn', + target: { kind: 'Resource', namespace: 'default', name: 'r' }, + }, + }); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -114,7 +122,15 @@ describe('BuiltinKindsEntityProcessor', () => { relation: { source: { kind: 'Component', namespace: 'default', name: 'n' }, type: 'dependsOn', - target: { kind: 'Resource', namespace: 'default', name: 'r' }, + target: { kind: 'Component', namespace: 'default', name: 'd' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'd' }, + type: 'dependencyOf', + target: { kind: 'Component', namespace: 'default', name: 'n' }, }, }); expect(emit).toBeCalledWith({ @@ -151,6 +167,29 @@ describe('BuiltinKindsEntityProcessor', () => { }); }); + it('generates an error for component entities with unspecified dependsOn entity reference kinds', async () => { + const entity: ComponentEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { name: 'n' }, + spec: { + type: 'service', + owner: 'o', + subcomponentOf: 's', + lifecycle: 'l', + providesApis: ['b'], + consumesApis: ['c'], + dependsOn: ['r'], + system: 's', + }, + }; + await expect( + processor.postProcessEntity(entity, location, emit), + ).rejects.toThrowError( + 'Entity reference kind is undefined and has no default', + ); + }); + it('generates relations for api entities', async () => { const entity: ApiEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -210,14 +249,14 @@ describe('BuiltinKindsEntityProcessor', () => { spec: { type: 'database', owner: 'o', - dependencyOf: ['c'], + dependsOn: ['Component:c', 'Resource:r'], system: 's', }, }; await processor.postProcessEntity(entity, location, emit); - expect(emit).toBeCalledTimes(6); + expect(emit).toBeCalledTimes(8); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -234,11 +273,12 @@ describe('BuiltinKindsEntityProcessor', () => { target: { kind: 'Group', namespace: 'default', name: 'o' }, }, }); + expect(emit).toBeCalledWith({ type: 'relation', relation: { source: { kind: 'Resource', namespace: 'default', name: 'n' }, - type: 'dependencyOf', + type: 'dependsOn', target: { kind: 'Component', namespace: 'default', name: 'c' }, }, }); @@ -246,10 +286,28 @@ describe('BuiltinKindsEntityProcessor', () => { type: 'relation', relation: { source: { kind: 'Component', namespace: 'default', name: 'c' }, - type: 'dependsOn', + type: 'dependencyOf', target: { kind: 'Resource', namespace: 'default', name: 'n' }, }, }); + + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'n' }, + type: 'dependsOn', + target: { kind: 'Resource', namespace: 'default', name: 'r' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'r' }, + type: 'dependencyOf', + target: { kind: 'Resource', namespace: 'default', name: 'n' }, + }, + }); + expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -268,6 +326,25 @@ describe('BuiltinKindsEntityProcessor', () => { }); }); + it('generates an error for resource entities with unspecified dependsOn entity reference kinds', async () => { + const entity: ResourceEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { name: 'n' }, + spec: { + type: 'database', + owner: 'o', + dependsOn: ['r'], + system: 's', + }, + }; + await expect( + processor.postProcessEntity(entity, location, emit), + ).rejects.toThrowError( + 'Entity reference kind is undefined and has no default', + ); + }); + it('generates relations for system entities', async () => { const entity: SystemEntity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts index d1de992a81..27313ba014 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts @@ -92,7 +92,7 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { function doEmit( targets: string | string[] | undefined, - context: { defaultKind: string; defaultNamespace: string }, + context: { defaultKind?: string; defaultNamespace: string }, outgoingRelation: string, incomingRelation: string, ): void { @@ -101,16 +101,29 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { } for (const target of [targets].flat()) { const targetRef = parseEntityRef(target, context); + if (targetRef.kind === undefined) { + throw new Error( + 'Entity reference kind is undefined and has no default', + ); + } emit( result.relation({ source: selfRef, type: outgoingRelation, - target: targetRef, + target: { + kind: targetRef.kind, + namespace: targetRef.namespace, + name: targetRef.name, + }, }), ); emit( result.relation({ - source: targetRef, + source: { + kind: targetRef.kind, + namespace: targetRef.namespace, + name: targetRef.name, + }, type: incomingRelation, target: selfRef, }), @@ -150,7 +163,7 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { ); doEmit( component.spec.dependsOn, - { defaultKind: 'Resource', defaultNamespace: selfRef.namespace }, + { defaultNamespace: selfRef.namespace }, RELATION_DEPENDS_ON, RELATION_DEPENDENCY_OF, ); @@ -195,10 +208,10 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { RELATION_OWNER_OF, ); doEmit( - resource.spec.dependencyOf, - { defaultKind: 'Component', defaultNamespace: selfRef.namespace }, - RELATION_DEPENDENCY_OF, + resource.spec.dependsOn, + { defaultNamespace: selfRef.namespace }, RELATION_DEPENDS_ON, + RELATION_DEPENDENCY_OF, ); doEmit( resource.spec.system, From 8c999911279599aa8b069e16e515a84ecfe7f8a6 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Wed, 31 Mar 2021 13:46:07 -0400 Subject: [PATCH 020/395] Update packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Jonah Grimes --- .../src/schema/kinds/Component.v1alpha1.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json index e2b98d5c3b..34fc48d285 100644 --- a/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json @@ -87,7 +87,7 @@ }, "dependsOn": { "type": "array", - "description": "An array of entity references to the resources that the component depends on.", + "description": "An array of references to other entities that the component depends on to function.", "items": { "type": "string", "minLength": 1 From 3b0c1338f6a39292cec57f6f57cd9d8a40d2d1ab Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Wed, 31 Mar 2021 13:46:19 -0400 Subject: [PATCH 021/395] Update packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Jonah Grimes --- .../src/schema/kinds/Resource.v1alpha1.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json index 2dcf6f4eb2..4958afc18c 100644 --- a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json @@ -49,7 +49,7 @@ }, "dependsOn": { "type": "array", - "description": "An array of entity references to the components that the resource is a dependency of.", + "description": "An array of references to other entities that the resource depends on to function.", "items": { "type": "string", "minLength": 1 From 6e936c417c707618ac2cb0b94b69642cc23dec62 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Wed, 31 Mar 2021 13:46:39 -0400 Subject: [PATCH 022/395] Update plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Jonah Grimes --- .../src/ingestion/processors/BuiltinKindsEntityProcessor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts index 27313ba014..0f9522ca27 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts @@ -103,7 +103,7 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { const targetRef = parseEntityRef(target, context); if (targetRef.kind === undefined) { throw new Error( - 'Entity reference kind is undefined and has no default', + `Entity reference "${target}" did not specify a kind (e.g. starting with "Component:"), and has no default`, ); } emit( From a9eff0c1b4b63ceff04769d965e0d0df6816442a Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Wed, 31 Mar 2021 15:42:01 -0400 Subject: [PATCH 023/395] fixed failing tests Signed-off-by: Jonah Grimes --- .../processors/BuiltinKindsEntityProcessor.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts index ad446c6a7a..a86acc3138 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts @@ -186,7 +186,7 @@ describe('BuiltinKindsEntityProcessor', () => { await expect( processor.postProcessEntity(entity, location, emit), ).rejects.toThrowError( - 'Entity reference kind is undefined and has no default', + 'Entity reference "r" did not specify a kind (e.g. starting with "Component:"), and has no default', ); }); @@ -334,14 +334,14 @@ describe('BuiltinKindsEntityProcessor', () => { spec: { type: 'database', owner: 'o', - dependsOn: ['r'], + dependsOn: ['c'], system: 's', }, }; await expect( processor.postProcessEntity(entity, location, emit), ).rejects.toThrowError( - 'Entity reference kind is undefined and has no default', + 'Entity reference "c" did not specify a kind (e.g. starting with "Component:"), and has no default', ); }); From 60d0a1a2edbcb298a0d12d843ad896ae71b27f47 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 22 Mar 2021 18:24:15 +0000 Subject: [PATCH 024/395] github collaborators field Signed-off-by: Andrew Johnson --- .changeset/dry-elephants-doubt.md | 5 +++ plugins/github-deployments/src/api/index.ts | 8 +++++ .../components/GithubDeploymentsCard.test.tsx | 36 +++++++++++++++---- .../src/components/GithubDeploymentsCard.tsx | 15 ++++++-- .../GithubDeploymentsTable.tsx | 4 ++- plugins/github-deployments/src/mocks/mocks.ts | 16 +++++++++ 6 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 .changeset/dry-elephants-doubt.md diff --git a/.changeset/dry-elephants-doubt.md b/.changeset/dry-elephants-doubt.md new file mode 100644 index 0000000000..7a9ccc9892 --- /dev/null +++ b/.changeset/dry-elephants-doubt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-deployments': patch +--- + +Adds extraColumns field to GitHub Deployments card diff --git a/plugins/github-deployments/src/api/index.ts b/plugins/github-deployments/src/api/index.ts index ca69ac3853..7496370bc9 100644 --- a/plugins/github-deployments/src/api/index.ts +++ b/plugins/github-deployments/src/api/index.ts @@ -24,6 +24,10 @@ export type GithubDeployment = { abbreviatedOid: string; commitUrl: string; }; + creator: { + login: string; + }; + payload: string; }; export interface GithubDeploymentsApi { @@ -55,6 +59,10 @@ query deployments($owner: String!, $repo: String!, $last: Int) { abbreviatedOid commitUrl } + creator { + login + } + payload } } } diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx index e20183f1d6..0eca749788 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx @@ -22,11 +22,16 @@ import { ConfigReader, ConfigApi, OAuthApi, + TableColumn, } from '@backstage/core'; import { fireEvent } from '@testing-library/react'; import { msw, renderInTestApp } from '@backstage/test-utils'; -import { GithubDeploymentsApiClient, githubDeploymentsApiRef } from '../api'; +import { + GithubDeployment, + GithubDeploymentsApiClient, + githubDeploymentsApiRef, +} from '../api'; import { githubDeploymentsPlugin } from '../plugin'; import { GithubDeploymentsCard } from './GithubDeploymentsCard'; @@ -127,12 +132,6 @@ describe('github-deployments', () => { }); it('should shows new data on reload', async () => { - worker.use( - graphql.query('deployments', (_, res, ctx) => - res(ctx.data(responseStub)), - ), - ); - const rendered = await renderInTestApp( @@ -160,4 +159,27 @@ describe('github-deployments', () => { expect(await rendered.findByText('failure')).toBeInTheDocument(); }); }); + + it('should display extra columns', async () => { + worker.use( + graphql.query('deployments', (_, res, ctx) => + res(ctx.data(responseStub)), + ), + ); + + const extraColumns: TableColumn[] = [ + { + title: 'Creator', + field: 'creator.login', + }, + ]; + + const rendered = await renderInTestApp( + + + , + ); + + expect(await rendered.findByText('robot-user-001')).toBeInTheDocument(); + }); }); diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx index 99dfba560a..2a887047a1 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx @@ -17,10 +17,11 @@ import React from 'react'; import { MissingAnnotationEmptyState, ResponseErrorPanel, + TableColumn, useApi, } from '@backstage/core'; import { useAsyncRetry } from 'react-use'; -import { githubDeploymentsApiRef } from '../api'; +import { GithubDeployment, githubDeploymentsApiRef } from '../api'; import { useEntity } from '@backstage/plugin-catalog-react'; import { GITHUB_PROJECT_SLUG_ANNOTATION, @@ -31,9 +32,11 @@ import GithubDeploymentsTable from './GithubDeploymentsTable/GithubDeploymentsTa const GithubDeploymentsComponent = ({ projectSlug, last, + extraColumns, }: { projectSlug: string; last: number; + extraColumns: TableColumn[]; }) => { const api = useApi(githubDeploymentsApiRef); const [owner, repo] = projectSlug.split('/'); @@ -51,11 +54,18 @@ const GithubDeploymentsComponent = ({ deployments={value || []} isLoading={loading} reload={reload} + extraColumns={extraColumns} /> ); }; -export const GithubDeploymentsCard = ({ last }: { last?: number }) => { +export const GithubDeploymentsCard = ({ + last, + extraColumns, +}: { + last?: number; + extraColumns?: TableColumn[]; +}) => { const { entity } = useEntity(); return !isGithubDeploymentsAvailable(entity) ? ( @@ -66,6 +76,7 @@ export const GithubDeploymentsCard = ({ last }: { last?: number }) => { entity?.metadata.annotations?.[GITHUB_PROJECT_SLUG_ANNOTATION] || '' } last={last || 10} + extraColumns={extraColumns || []} /> ); }; diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx b/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx index 91f91b919e..44ed1fbcdd 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx @@ -86,18 +86,20 @@ type GithubDeploymentsTableProps = { deployments: GithubDeployment[]; isLoading: boolean; reload: () => void; + extraColumns: TableColumn[]; }; const GithubDeploymentsTable = ({ deployments, isLoading, reload, + extraColumns, }: GithubDeploymentsTableProps) => { const classes = useStyles(); return ( Date: Tue, 6 Apr 2021 14:29:59 +0100 Subject: [PATCH 025/395] fix test Signed-off-by: Andrew Johnson --- .../src/components/GithubDeploymentsCard.test.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx index 0eca749788..a1c2230d0d 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx @@ -132,6 +132,12 @@ describe('github-deployments', () => { }); it('should shows new data on reload', async () => { + worker.use( + graphql.query('deployments', (_, res, ctx) => + res(ctx.data(responseStub)), + ), + ); + const rendered = await renderInTestApp( From 7b30d0cdcf33429bc49654b8ca0f64cc33c8563b Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 6 Apr 2021 14:38:56 +0100 Subject: [PATCH 026/395] prettier Signed-off-by: Andrew Johnson --- .../src/components/GithubDeploymentsCard.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx index a1c2230d0d..a3bdd2cb9c 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx @@ -137,7 +137,7 @@ describe('github-deployments', () => { res(ctx.data(responseStub)), ), ); - + const rendered = await renderInTestApp( From a1c46265e9396e411a01efeebe40d6368ed41183 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 6 Apr 2021 15:34:31 +0100 Subject: [PATCH 027/395] fix test Signed-off-by: Andrew Johnson --- plugins/github-deployments/src/mocks/mocks.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/github-deployments/src/mocks/mocks.ts b/plugins/github-deployments/src/mocks/mocks.ts index 1edbbc9b00..a84d684661 100644 --- a/plugins/github-deployments/src/mocks/mocks.ts +++ b/plugins/github-deployments/src/mocks/mocks.ts @@ -63,7 +63,7 @@ export const responseStub: QueryResponse = { abbreviatedOid: '54321', }, creator: { - login: 'robot-user-001', + login: 'robot-user-002', }, payload: '', }, @@ -98,7 +98,7 @@ export const refreshedResponseStub: QueryResponse = { abbreviatedOid: '54321', }, creator: { - login: 'robot-user-001', + login: 'robot-user-002', }, payload: '', }, From 4438b0f6e8a257ad2694abef52dfd380b6ab1b0c Mon Sep 17 00:00:00 2001 From: Remi Kristelijn Date: Wed, 7 Apr 2021 08:43:29 +0200 Subject: [PATCH 028/395] fix adds pagetheme colors closes #5235 Signed-off-by: Remi Kristelijn --- docs/getting-started/app-custom-theme.md | 65 +++++++++++++++++++ .../core/src/layout/Header/Header.stories.tsx | 40 ++++++++++++ packages/theme/src/pageTheme.ts | 5 ++ .../ApiExplorerPage/ApiExplorerLayout.tsx | 2 +- 4 files changed, 111 insertions(+), 1 deletion(-) diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index 345b7ad969..0470f2d71d 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -74,3 +74,68 @@ Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `lightTheme` and `darkTheme` from [@backstage/theme](https://www.npmjs.com/package/@backstage/theme). + +## Example of a custom theme + +```ts +const themeOptions = createThemeOptions({ + palette: { + ...lightTheme.palette, + primary: { + main: '#123456', + }, + secondary: { + main: '#123456', + }, + error: { + main: '#123456' + }, + warning: { + main: '#123456', + }, + info: { + main: '#123456', + }, + success: { + main: '#123456', + }, + background: { + default: '#123456', + paper: '#123456', + }, + banner: { + info: '#123456', + error: '#123456' + text: '#123456' + link: '#123456', + }, + errorBackground: '#123456' + warningBackground: '#123456' + infoBackground: '#123456' + navigation: { + background: '#123456', + indicator: '#123456' + color: '#123456' + selectedColor: '#123456', + }, + }, + defaultPageTheme: 'home', + fontFamily: 'Comic Sans', + /* below drives the header colors */ + pageTheme: { + home: genPageTheme(['#123456','#123456'], shapes.wave), + documentation: genPageTheme(['#123456','#123456'], shapes.wave2), + tool: genPageTheme(['#123456','#123456'], shapes.round), + service: genPageTheme(['#123456','#123456'], shapes.wave), + website: genPageTheme(['#123456','#123456'], shapes.wave), + library: genPageTheme(['#123456','#123456'] shapes.wave), + other: genPageTheme(['#123456','#123456'], shapes.wave), + app: genPageTheme(['#123456','#123456'], shapes.wave), + apis: genPageTheme(['#123456','#123456'], shapes.wave), + grpc: genPageTheme(['#123456','#123456'], shapes.wave2), + asyncapi: genPageTheme(['#123456','#123456'], shapes.wave2), + graphql: genPageTheme(['#123456','#123456'], shapes.wave2), + openapi: genPageTheme(['#123456','#123456'], shapes.wave2), + }, +}); +``` diff --git a/packages/core/src/layout/Header/Header.stories.tsx b/packages/core/src/layout/Header/Header.stories.tsx index badd63a5ad..3deb980dfd 100644 --- a/packages/core/src/layout/Header/Header.stories.tsx +++ b/packages/core/src/layout/Header/Header.stories.tsx @@ -45,6 +45,46 @@ export const HomeWithSubtitle = () => ( ); +export const Apis = () => ( + +
+ {labels} +
+
+); + +export const Grpc = () => ( + +
+ {labels} +
+
+); + +export const AsyncApi = () => ( + +
+ {labels} +
+
+); + +export const Graphql = () => ( + +
+ {labels} +
+
+); + +export const OpenApi = () => ( + +
+ {labels} +
+
+); + export const Tool = () => (
diff --git a/packages/theme/src/pageTheme.ts b/packages/theme/src/pageTheme.ts index f86f3a6449..6d364ea351 100644 --- a/packages/theme/src/pageTheme.ts +++ b/packages/theme/src/pageTheme.ts @@ -63,4 +63,9 @@ export const pageTheme: Record = { library: genPageTheme(colorVariants.rubyRed, shapes.wave), other: genPageTheme(colorVariants.darkGrey, shapes.wave), app: genPageTheme(colorVariants.toastyOrange, shapes.wave), + apis: genPageTheme(colorVariants.eveningSea, shapes.wave2), + grpc: genPageTheme(colorVariants.marineBlue, shapes.wave2), + asyncapi: genPageTheme(colorVariants.rubyRed, shapes.wave2), + graphql: genPageTheme(colorVariants.purpleSky, shapes.wave2), + openapi: genPageTheme(colorVariants.toastyOrange, shapes.wave2), }; diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx index add886fead..fb94df8528 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx @@ -26,7 +26,7 @@ export const ApiExplorerLayout = ({ children }: Props) => { configApi.getOptionalString('organization.name') ?? 'Backstage' } API Explorer`; return ( - +
Date: Wed, 7 Apr 2021 08:52:50 +0200 Subject: [PATCH 029/395] adds changeset closes #5235 Signed-off-by: Remi Kristelijn --- .changeset/thirty-owls-lay.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/thirty-owls-lay.md diff --git a/.changeset/thirty-owls-lay.md b/.changeset/thirty-owls-lay.md new file mode 100644 index 0000000000..ebdd3ba82d --- /dev/null +++ b/.changeset/thirty-owls-lay.md @@ -0,0 +1,6 @@ +--- +'@backstage/core': patch +'storybook': patch +--- + +exposes undocumented pagetheme From 91bef20239519a374d8a1fe2e654bd34aca43765 Mon Sep 17 00:00:00 2001 From: Remi Kristelijn Date: Wed, 7 Apr 2021 09:00:32 +0200 Subject: [PATCH 030/395] fix typo in vocab Signed-off-by: Remi Kristelijn --- .changeset/thirty-owls-lay.md | 2 +- .github/styles/vocab.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.changeset/thirty-owls-lay.md b/.changeset/thirty-owls-lay.md index ebdd3ba82d..2837496d76 100644 --- a/.changeset/thirty-owls-lay.md +++ b/.changeset/thirty-owls-lay.md @@ -3,4 +3,4 @@ 'storybook': patch --- -exposes undocumented pagetheme +exposes undocumented PageTheme diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index b0bcf9c9f7..f62f8c80b8 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -43,6 +43,7 @@ Namespaces OAuth Okta Onboarding +PageTheme Platformize Podman Preprarer From c65a85afb691700ddb795f2a4b9d9dc0b2648a13 Mon Sep 17 00:00:00 2001 From: Jacob Valdemar Andreasen Date: Wed, 7 Apr 2021 12:32:43 +0200 Subject: [PATCH 031/395] 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 cc9132f8c3dccf47b8111a11cd9ce2021168da40 Mon Sep 17 00:00:00 2001 From: Victor Morfin Date: Wed, 7 Apr 2021 13:16:36 -0600 Subject: [PATCH 032/395] Adding close button to Support menu Signed-off-by: Victor Morfin --- .../core/src/components/SupportButton/SupportButton.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/core/src/components/SupportButton/SupportButton.tsx b/packages/core/src/components/SupportButton/SupportButton.tsx index eea2b000ca..5bbde953b0 100644 --- a/packages/core/src/components/SupportButton/SupportButton.tsx +++ b/packages/core/src/components/SupportButton/SupportButton.tsx @@ -16,6 +16,7 @@ import { HelpIcon, useApp } from '@backstage/core-api'; import { + Box, Button, List, ListItem, @@ -127,6 +128,11 @@ export const SupportButton = ({ children }: PropsWithChildren) => { {items && items.map((item, i) => )} + + + ); From 9a9e7a42f440742121207d3dd7107df3367396f5 Mon Sep 17 00:00:00 2001 From: Victor Morfin Date: Wed, 7 Apr 2021 14:30:22 -0600 Subject: [PATCH 033/395] Adding changeset Signed-off-by: Victor Morfin --- .changeset/stale-chefs-retire.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/stale-chefs-retire.md diff --git a/.changeset/stale-chefs-retire.md b/.changeset/stale-chefs-retire.md new file mode 100644 index 0000000000..579f5c3042 --- /dev/null +++ b/.changeset/stale-chefs-retire.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': minor +--- + +Adding close button on support menu From d0e2116c448e47087566de0be290f62efb821fee Mon Sep 17 00:00:00 2001 From: Efrain Gutierrez Date: Wed, 7 Apr 2021 11:49:02 -0500 Subject: [PATCH 034/395] Adjusting Heading for Scaffolding Template Page Signed-off-by: Efrain Gutierrez --- packages/core/src/layout/Header/Header.tsx | 8 ++++++-- packages/core/src/layout/InfoCard/InfoCard.tsx | 3 +++ .../components/MultistepJsonForm/MultistepJsonForm.tsx | 4 +++- .../src/components/TemplatePage/TemplatePage.tsx | 6 +++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/core/src/layout/Header/Header.tsx b/packages/core/src/layout/Header/Header.tsx index efa7502723..1ad7b91687 100644 --- a/packages/core/src/layout/Header/Header.tsx +++ b/packages/core/src/layout/Header/Header.tsx @@ -140,7 +140,7 @@ const TypeFragment = ({ const TitleFragment = ({ pageTitle, classes, tooltip }: TitleFragmentProps) => { const FinalTitle = ( - + {pageTitle} ); @@ -166,7 +166,11 @@ const SubtitleFragment = ({ classes, subtitle }: SubtitleFragmentProps) => { } return ( - + {subtitle} ); diff --git a/packages/core/src/layout/InfoCard/InfoCard.tsx b/packages/core/src/layout/InfoCard/InfoCard.tsx index cf06a5f0a1..5bb3e19362 100644 --- a/packages/core/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core/src/layout/InfoCard/InfoCard.tsx @@ -125,6 +125,7 @@ type Props = { actionsTopRight?: ReactNode; className?: string; noPadding?: boolean; + titleTypographyProps?: object; }; export const InfoCard = ({ @@ -143,6 +144,7 @@ export const InfoCard = ({ actionsTopRight, className, noPadding, + titleTypographyProps, }: Props): JSX.Element => { const classes = useStyles(); /** @@ -183,6 +185,7 @@ export const InfoCard = ({ title={title} subheader={subheader} style={{ ...headerStyle }} + titleTypographyProps={titleTypographyProps} {...headerProps} /> )} diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 876d6dfa66..5354216bd9 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -75,7 +75,9 @@ export const MultistepJsonForm = ({ return ( - {title} + + {title} +
{ {loading && } {schema && ( - + Date: Wed, 7 Apr 2021 17:52:41 -0500 Subject: [PATCH 035/395] add accessibility for sighted users Signed-off-by: miguelrambalt --- .../components/MultistepJsonForm/MultistepJsonForm.tsx | 8 ++++++-- .../src/components/TemplateCard/TemplateCard.tsx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 5354216bd9..58f5f5cd11 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -71,10 +71,14 @@ export const MultistepJsonForm = ({ return ( <> - {steps.map(({ title, schema, ...formProps }) => { + {steps.map(({ title, schema, ...formProps }, index) => { return ( - + {title} diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index 25f89f20ab..2ba83fdaae 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -85,7 +85,7 @@ export const TemplateCard = ({ {description} - From 24aed6be9416dfc0daf2d3975b27e7f791b9bfc9 Mon Sep 17 00:00:00 2001 From: Remi Kristelijn Date: Thu, 8 Apr 2021 06:25:57 +0200 Subject: [PATCH 036/395] fix: feedback Signed-off-by: Remi Kristelijn --- .changeset/thirty-owls-lay.md | 3 +-- docs/getting-started/app-custom-theme.md | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.changeset/thirty-owls-lay.md b/.changeset/thirty-owls-lay.md index 2837496d76..ce08042276 100644 --- a/.changeset/thirty-owls-lay.md +++ b/.changeset/thirty-owls-lay.md @@ -1,6 +1,5 @@ --- '@backstage/core': patch -'storybook': patch --- -exposes undocumented PageTheme +# exposes undocumented `PageTheme` diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index 0470f2d71d..473da02670 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -131,11 +131,7 @@ const themeOptions = createThemeOptions({ library: genPageTheme(['#123456','#123456'] shapes.wave), other: genPageTheme(['#123456','#123456'], shapes.wave), app: genPageTheme(['#123456','#123456'], shapes.wave), - apis: genPageTheme(['#123456','#123456'], shapes.wave), - grpc: genPageTheme(['#123456','#123456'], shapes.wave2), - asyncapi: genPageTheme(['#123456','#123456'], shapes.wave2), - graphql: genPageTheme(['#123456','#123456'], shapes.wave2), - openapi: genPageTheme(['#123456','#123456'], shapes.wave2), + apis: genPageTheme(['#123456','#123456'], }, }); ``` From 2d9050a2e90a8813312d5f2af40da3dcfb684884 Mon Sep 17 00:00:00 2001 From: Remi Kristelijn Date: Thu, 8 Apr 2021 06:33:18 +0200 Subject: [PATCH 037/395] revert vocab Signed-off-by: Remi Kristelijn --- .github/styles/vocab.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index f62f8c80b8..b0bcf9c9f7 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -43,7 +43,6 @@ Namespaces OAuth Okta Onboarding -PageTheme Platformize Podman Preprarer From 50449fc512e755a54eda8cf7acbdede5281b235a Mon Sep 17 00:00:00 2001 From: Konstantin Dichev Date: Thu, 8 Apr 2021 12:47:02 +0200 Subject: [PATCH 038/395] Fix Broken Link on home page --- microsite/pages/en/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/pages/en/index.js b/microsite/pages/en/index.js index 47f9568d9b..a761d6b6e2 100644 --- a/microsite/pages/en/index.js +++ b/microsite/pages/en/index.js @@ -292,7 +292,7 @@ class Index extends React.Component { Build your own software templates Contribute From 4a41e6e1632cbb9008e845dabc2f157aaed418fd Mon Sep 17 00:00:00 2001 From: Konstantin Dichev Date: Thu, 8 Apr 2021 12:47:02 +0200 Subject: [PATCH 039/395] Fix Broken Link on home page Signed-off-by: kdichev --- microsite/pages/en/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/pages/en/index.js b/microsite/pages/en/index.js index 47f9568d9b..a761d6b6e2 100644 --- a/microsite/pages/en/index.js +++ b/microsite/pages/en/index.js @@ -292,7 +292,7 @@ class Index extends React.Component { Build your own software templates Contribute From 1229d8377fbbc40a1e54297b0d4c3599e1a28a1a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 8 Apr 2021 14:22:10 +0100 Subject: [PATCH 040/395] use custom columns Signed-off-by: Andrew Johnson --- .../components/GithubDeploymentsCard.test.tsx | 53 +++++----- .../src/components/GithubDeploymentsCard.tsx | 14 +-- .../GithubDeploymentsTable.tsx | 77 +++------------ .../GithubDeploymentsTable/columns.tsx | 99 +++++++++++++++++++ .../GithubDeploymentsTable/index.ts | 16 +++ .../GithubDeploymentsTable/presets.ts | 32 ++++++ plugins/github-deployments/src/mocks/mocks.ts | 4 +- 7 files changed, 197 insertions(+), 98 deletions(-) create mode 100644 plugins/github-deployments/src/components/GithubDeploymentsTable/columns.tsx create mode 100644 plugins/github-deployments/src/components/GithubDeploymentsTable/index.ts create mode 100644 plugins/github-deployments/src/components/GithubDeploymentsTable/presets.ts diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx index a3bdd2cb9c..52c84d657b 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx @@ -22,16 +22,11 @@ import { ConfigReader, ConfigApi, OAuthApi, - TableColumn, } from '@backstage/core'; import { fireEvent } from '@testing-library/react'; import { msw, renderInTestApp } from '@backstage/test-utils'; -import { - GithubDeployment, - GithubDeploymentsApiClient, - githubDeploymentsApiRef, -} from '../api'; +import { GithubDeploymentsApiClient, githubDeploymentsApiRef } from '../api'; import { githubDeploymentsPlugin } from '../plugin'; import { GithubDeploymentsCard } from './GithubDeploymentsCard'; @@ -44,6 +39,7 @@ import { import { setupServer } from 'msw/node'; import { graphql } from 'msw'; +import { GithubDeploymentsTable } from './GithubDeploymentsTable'; jest.mock('@backstage/plugin-catalog-react', () => ({ useEntity: () => { @@ -164,28 +160,35 @@ describe('github-deployments', () => { ).toBeInTheDocument(); expect(await rendered.findByText('failure')).toBeInTheDocument(); }); - }); - it('should display extra columns', async () => { - worker.use( - graphql.query('deployments', (_, res, ctx) => - res(ctx.data(responseStub)), - ), - ); + it('should display extra columns', async () => { + worker.use( + graphql.query('deployments', (_, res, ctx) => + res(ctx.data(responseStub)), + ), + ); - const extraColumns: TableColumn[] = [ - { - title: 'Creator', - field: 'creator.login', - }, - ]; + const renderTargetFromPayload = (payload: string) => { + const parsedPayload = JSON.parse(payload); + return parsedPayload?.target || 'unknown'; + }; - const rendered = await renderInTestApp( - - - , - ); + const columns = [ + ...GithubDeploymentsTable.defaultDeploymentColumns, + GithubDeploymentsTable.columns.createPayloadColumn( + 'Target', + renderTargetFromPayload, + ), + ]; - expect(await rendered.findByText('robot-user-001')).toBeInTheDocument(); + const rendered = await renderInTestApp( + + + , + ); + + expect(await rendered.findByText('moon')).toBeInTheDocument(); + expect(await rendered.findByText('sun')).toBeInTheDocument(); + }); }); }); diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx index 2a887047a1..073f78af2e 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx @@ -27,16 +27,16 @@ import { GITHUB_PROJECT_SLUG_ANNOTATION, isGithubDeploymentsAvailable, } from '../Router'; -import GithubDeploymentsTable from './GithubDeploymentsTable/GithubDeploymentsTable'; +import { GithubDeploymentsTable } from './GithubDeploymentsTable/GithubDeploymentsTable'; const GithubDeploymentsComponent = ({ projectSlug, last, - extraColumns, + columns, }: { projectSlug: string; last: number; - extraColumns: TableColumn[]; + columns: TableColumn[]; }) => { const api = useApi(githubDeploymentsApiRef); const [owner, repo] = projectSlug.split('/'); @@ -54,17 +54,17 @@ const GithubDeploymentsComponent = ({ deployments={value || []} isLoading={loading} reload={reload} - extraColumns={extraColumns} + columns={columns} /> ); }; export const GithubDeploymentsCard = ({ last, - extraColumns, + columns, }: { last?: number; - extraColumns?: TableColumn[]; + columns?: TableColumn[]; }) => { const { entity } = useEntity(); @@ -76,7 +76,7 @@ export const GithubDeploymentsCard = ({ entity?.metadata.annotations?.[GITHUB_PROJECT_SLUG_ANNOTATION] || '' } last={last || 10} - extraColumns={extraColumns || []} + columns={columns || GithubDeploymentsTable.defaultDeploymentColumns} /> ); }; diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx b/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx index 44ed1fbcdd..e13b8aeb18 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx @@ -14,19 +14,12 @@ * limitations under the License. */ import React from 'react'; -import { - StatusPending, - StatusRunning, - StatusOK, - Table, - TableColumn, - StatusAborted, - StatusError, -} from '@backstage/core'; +import { Table, TableColumn } from '@backstage/core'; import { GithubDeployment } from '../../api'; -import { DateTime } from 'luxon'; -import { Box, Typography, Link, makeStyles } from '@material-ui/core'; +import { Typography, makeStyles } from '@material-ui/core'; import SyncIcon from '@material-ui/icons/Sync'; +import * as columnFactories from './columns'; +import { defaultDeploymentColumns } from './presets'; const useStyles = makeStyles(theme => ({ empty: { @@ -36,70 +29,24 @@ const useStyles = makeStyles(theme => ({ }, })); -const statusIndicator = (value: string): React.ReactNode => { - switch (value) { - case 'PENDING': - return ; - case 'IN_PROGRESS': - return ; - case 'ACTIVE': - return ; - case 'ERROR': - case 'FAILURE': - return ; - default: - return ; - } -}; - -const columns: TableColumn[] = [ - { - title: 'Environment', - field: 'environment', - highlight: true, - }, - { - title: 'Status', - render: (row: GithubDeployment): React.ReactNode => ( - - {statusIndicator(row.state)} - {row.state} - - ), - }, - { - title: 'Commit', - render: (row: GithubDeployment): React.ReactNode => ( - - {row.commit.abbreviatedOid} - - ), - }, - { - title: 'Last Updated', - render: (row: GithubDeployment): React.ReactNode => - DateTime.fromISO(row.updatedAt).toRelative({ locale: 'en' }), - }, -]; - type GithubDeploymentsTableProps = { deployments: GithubDeployment[]; isLoading: boolean; reload: () => void; - extraColumns: TableColumn[]; + columns: TableColumn[]; }; -const GithubDeploymentsTable = ({ +export function GithubDeploymentsTable({ deployments, isLoading, reload, - extraColumns, -}: GithubDeploymentsTableProps) => { + columns, +}: GithubDeploymentsTableProps) { const classes = useStyles(); return (
); -}; +} -export default GithubDeploymentsTable; +GithubDeploymentsTable.columns = columnFactories; + +GithubDeploymentsTable.defaultDeploymentColumns = defaultDeploymentColumns; diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/columns.tsx b/plugins/github-deployments/src/components/GithubDeploymentsTable/columns.tsx new file mode 100644 index 0000000000..fe166be6e0 --- /dev/null +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/columns.tsx @@ -0,0 +1,99 @@ +/* + * 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 { + StatusPending, + StatusRunning, + StatusOK, + TableColumn, + StatusAborted, + StatusError, +} from '@backstage/core'; +import { GithubDeployment } from '../../api'; +import { DateTime } from 'luxon'; +import { Box, Typography, Link } from '@material-ui/core'; + +const statusIndicator = (value: string): React.ReactNode => { + switch (value) { + case 'PENDING': + return ; + case 'IN_PROGRESS': + return ; + case 'ACTIVE': + return ; + case 'ERROR': + case 'FAILURE': + return ; + default: + return ; + } +}; + +export function createEnvironmentColumn(): TableColumn { + return { + title: 'Environment', + field: 'environment', + highlight: true, + }; +} + +export function createStatusColumn(): TableColumn { + return { + title: 'Status', + render: (row: GithubDeployment): React.ReactNode => ( + + {statusIndicator(row.state)} + {row.state} + + ), + }; +} + +export function createCommitColumn(): TableColumn { + return { + title: 'Commit', + render: (row: GithubDeployment): React.ReactNode => ( + + {row.commit.abbreviatedOid} + + ), + }; +} + +export function createCreatorColumn(): TableColumn { + return { + title: 'Creator', + field: 'creator.login', + }; +} + +export function createLastUpdatedColumn(): TableColumn { + return { + title: 'Last Updated', + render: (row: GithubDeployment): React.ReactNode => + DateTime.fromISO(row.updatedAt).toRelative({ locale: 'en' }), + }; +} + +export function createPayloadColumn( + title: string, + render: (payload: string) => React.ReactNode, +): TableColumn { + return { + title: title, + render: (deployment: GithubDeployment) => render(deployment.payload), + }; +} diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/index.ts b/plugins/github-deployments/src/components/GithubDeploymentsTable/index.ts new file mode 100644 index 0000000000..e622d559cb --- /dev/null +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { GithubDeploymentsTable } from './GithubDeploymentsTable'; diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/presets.ts b/plugins/github-deployments/src/components/GithubDeploymentsTable/presets.ts new file mode 100644 index 0000000000..b50e11dcb6 --- /dev/null +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/presets.ts @@ -0,0 +1,32 @@ +/* + * 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 { TableColumn } from '@backstage/core'; +import { GithubDeployment } from '../../api'; +import { + createEnvironmentColumn, + createStatusColumn, + createCommitColumn, + createLastUpdatedColumn, + createCreatorColumn, +} from './columns'; + +export const defaultDeploymentColumns: TableColumn[] = [ + createEnvironmentColumn(), + createStatusColumn(), + createCommitColumn(), + createCreatorColumn(), + createLastUpdatedColumn(), +]; diff --git a/plugins/github-deployments/src/mocks/mocks.ts b/plugins/github-deployments/src/mocks/mocks.ts index a84d684661..c0afb325db 100644 --- a/plugins/github-deployments/src/mocks/mocks.ts +++ b/plugins/github-deployments/src/mocks/mocks.ts @@ -52,7 +52,7 @@ export const responseStub: QueryResponse = { creator: { login: 'robot-user-001', }, - payload: '', + payload: '{"target":"moon"}', }, { state: 'pending', @@ -65,7 +65,7 @@ export const responseStub: QueryResponse = { creator: { login: 'robot-user-002', }, - payload: '', + payload: '{"target":"sun"}', }, ], }, From 932293a0785e52c542967ac70a55c99d5b84b16a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 8 Apr 2021 14:26:37 +0100 Subject: [PATCH 041/395] export Signed-off-by: Andrew Johnson --- plugins/github-deployments/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/github-deployments/src/index.ts b/plugins/github-deployments/src/index.ts index 2ee681332a..06eed2a2a2 100644 --- a/plugins/github-deployments/src/index.ts +++ b/plugins/github-deployments/src/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ export { githubDeploymentsPlugin, EntityGithubDeploymentsCard } from './plugin'; +export { GithubDeploymentsTable } from './components/GithubDeploymentsTable'; export { isGithubDeploymentsAvailable } from './Router'; From 7c5784e3f4745ea83eb5ff795d638460ecc807fe Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 8 Apr 2021 14:38:58 +0100 Subject: [PATCH 042/395] add @types/react Signed-off-by: Andrew Johnson --- plugins/github-deployments/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index b8761c1385..2cbc63255a 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -42,6 +42,7 @@ "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", + "@types/react": "^16.9", "cross-fetch": "^3.0.6", "msw": "^0.21.2" }, From 8ced77687892c761eab45eef86d84e6acb7f7ee6 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 8 Apr 2021 14:52:17 +0100 Subject: [PATCH 043/395] move Signed-off-by: Andrew Johnson --- plugins/github-deployments/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 2cbc63255a..6d4e61d4eb 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -31,7 +31,8 @@ "luxon": "^1.26.0", "react": "^16.13.1", "react-dom": "^16.13.1", - "react-use": "^15.3.3" + "react-use": "^15.3.3", + "@types/react": "^16.9" }, "devDependencies": { "@backstage/cli": "^0.6.6", @@ -42,7 +43,6 @@ "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", - "@types/react": "^16.9", "cross-fetch": "^3.0.6", "msw": "^0.21.2" }, From aec9ca24b11bb2a6cb01aa0bcea8e2d0ce24230b Mon Sep 17 00:00:00 2001 From: Victor Morfin Date: Thu, 8 Apr 2021 10:31:24 -0600 Subject: [PATCH 044/395] Changing changeset minor to patch Signed-off-by: Victor Morfin --- .changeset/stale-chefs-retire.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/stale-chefs-retire.md b/.changeset/stale-chefs-retire.md index 579f5c3042..e43c20062a 100644 --- a/.changeset/stale-chefs-retire.md +++ b/.changeset/stale-chefs-retire.md @@ -1,5 +1,5 @@ --- -'@backstage/core': minor +'@backstage/core': patch --- Adding close button on support menu From ea677c0361a44e6ac76b93ad34c676bc58f9c72e Mon Sep 17 00:00:00 2001 From: miguelrambalt Date: Thu, 8 Apr 2021 11:47:54 -0500 Subject: [PATCH 045/395] add header accessibility in create Signed-off-by: miguelrambalt --- .../core/src/layout/ContentHeader/ContentHeader.tsx | 7 ++++++- packages/core/src/layout/ItemCard/ItemCardHeader.tsx | 12 ++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/core/src/layout/ContentHeader/ContentHeader.tsx b/packages/core/src/layout/ContentHeader/ContentHeader.tsx index e9fba56358..3ccf8f894c 100644 --- a/packages/core/src/layout/ContentHeader/ContentHeader.tsx +++ b/packages/core/src/layout/ContentHeader/ContentHeader.tsx @@ -66,7 +66,12 @@ const DefaultTitle = ({ title = 'Unknown page', className, }: DefaultTitleProps) => ( - + {title} ); diff --git a/packages/core/src/layout/ItemCard/ItemCardHeader.tsx b/packages/core/src/layout/ItemCard/ItemCardHeader.tsx index 17c4a19e58..ebf419cba0 100644 --- a/packages/core/src/layout/ItemCard/ItemCardHeader.tsx +++ b/packages/core/src/layout/ItemCard/ItemCardHeader.tsx @@ -77,8 +77,16 @@ export const ItemCardHeader = (props: ItemCardHeaderProps) => { const classes = useStyles(props); return (
- {subtitle && {subtitle}} - {title && {title}} + {subtitle && ( + + {subtitle} + + )} + {title && ( + + {title} + + )} {children}
); From 875614c9b629508043bb944db1abdd61b0edb20a Mon Sep 17 00:00:00 2001 From: miguelrambalt Date: Thu, 8 Apr 2021 12:04:44 -0500 Subject: [PATCH 046/395] add color for accessibility in Lifecycle for headers Signed-off-by: miguelrambalt --- packages/core/src/components/Lifecycle/Lifecycle.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/components/Lifecycle/Lifecycle.tsx b/packages/core/src/components/Lifecycle/Lifecycle.tsx index d388452cdc..585f7a5c18 100644 --- a/packages/core/src/components/Lifecycle/Lifecycle.tsx +++ b/packages/core/src/components/Lifecycle/Lifecycle.tsx @@ -25,7 +25,7 @@ type Props = CSS.Properties & { const useStyles = makeStyles({ alpha: { - color: '#d00150', + color: '#ffffff', fontFamily: 'serif', fontWeight: 'normal', fontStyle: 'italic', From 72de2a1428535d7a74ed7ef9e38eb4d966515eb7 Mon Sep 17 00:00:00 2001 From: Victor Morfin Date: Thu, 8 Apr 2021 11:28:24 -0600 Subject: [PATCH 047/395] Changing box component to DialogActions component Signed-off-by: Victor Morfin --- .../core/src/components/SupportButton/SupportButton.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/components/SupportButton/SupportButton.tsx b/packages/core/src/components/SupportButton/SupportButton.tsx index 5bbde953b0..d0c2412dad 100644 --- a/packages/core/src/components/SupportButton/SupportButton.tsx +++ b/packages/core/src/components/SupportButton/SupportButton.tsx @@ -16,8 +16,8 @@ import { HelpIcon, useApp } from '@backstage/core-api'; import { - Box, Button, + DialogActions, List, ListItem, ListItemIcon, @@ -128,11 +128,11 @@ export const SupportButton = ({ children }: PropsWithChildren) => { {items && items.map((item, i) => )} - + - + ); From 3d9de0164c2c93ddef1576dca0c4e59500902783 Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Sun, 4 Apr 2021 16:35:05 +0100 Subject: [PATCH 048/395] tutorial: Using AWS Application Load Balancer with Azure Active Directory to authenticate requests Signed-off-by: Marco Crivellaro --- .../docs/tutorials/aws-alb-aad-oidc-auth.md | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 contrib/docs/tutorials/aws-alb-aad-oidc-auth.md diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md new file mode 100644 index 0000000000..9dab72fe66 --- /dev/null +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -0,0 +1,179 @@ +# Using AWS Application Load Balancer with Azure Active Directory to authenticate requests + +Backstage allows to offload the responsibility of authenticating users to AWS Application Loadbalancer (**ALB**), leveraging the authentication support on ALB. +This tutorial shows how to use authentication on an ALB sitting in front of Backstage. +Azure Active Directory (**AAD**) is used as identity provider but any identity provider supporting OpenID Connect (OIDC) can be used. + +It is assumed an ALB is already serving traffic in front of a Backstage instance configured to serve the frontend app from the backend. + +## Infrastructure setup + +### AAD App + +The AAD App is used to execute the authentication flow, serve and refresh the identity token. + +Create the AAD App following the steps outlined in `Create a Microsoft App Registration in Microsoft Portal` section from the tutorial [Monorepo App Setup With Authentication][monorepo-app-setup-with-auth]. + +Instead of `localhost` addresses, use the following values. + +- Identifier URI: `https://backstage.yourdomain.com` +- Redirect URI: `https://backstage.yourdomain.com/oauth2/idpresponse` + +`Application (client) Id`, `Directory (tenant) ID` and `client secret`values will be used while configuring the ALB. + +### ALB + +In AWS console configure ALB Authentication as described below: + +- Edit the ALB rule used to forward the traffic to Backstage and add a new `Authenticate` action. The action will have higher priority compared to the existing `Forward to`. +- Select `OIDC` under `Authenticate` +- Set `Issuer` to `https://login.microsoftonline.com/{TENANT_ID}/v2.0`, replacing `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App. +- Set `Authorization endpoint` to `https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/authorize`, replacing `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App. +- Set `Token endpoint` to `https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/authorize`, replacing `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App. +- Set `User info endpoint` to `https://graph.microsoft.com/oidc/userinfo` +- Set `Client ID` to the AAD App `Application (client) Id` +- Set `Client secret` to the AAD APP `client secret` + +Use the following advanced settings: + +- `Session cookie name` = `AWSELBAuthSessionCookie` +- `Session timeout` = `604800` seconds +- `Scope` = `openid profile offline_access` +- `Action on unauthenticated request` = `Autenticate (client reattempt)` + +Once you've saved the action, you should see an authentication flow be triggered against AAD when visiting Backstage address at `https://backstage.yourdomain.com`. The flow will not complete successfully as Backstage app isn't yet configured properly. + +## Backstage changes + +### Frontend + +The Backstage App needs a SingInPage when authentication is required. +When using ALB authentication Backstage will only be loaded once the user has successfully authenticated; we won't need to display a SignIn page, however we will need to create a dummy SignIn component that can refresh the token. + +- edit `packages/app/src/App.tsx` +- import the following two additional definitions from `@backstage/core`: `useApi`, `configApiRef`; these will be used to check wether backstage is running locally or behind an ALB +- add the following definition just before the app is created (`const app = createApp`): + +```ts +const DummySignInComponent: any = (props: any) => { + const config = useApi(configApiRef); + const shouldAuth = !!config.getOptionalConfig('auth.providers.awsalb'); + if (shouldAuth) { + fetch(`${window.location.origin}/api/auth/awsalb/refresh`) + .then(data => data.json()) + .then(data => { + props.onResult({ + userId: data.backstageIdentity.id, + profile: data.profile, + }); + }); + } else { + // when running locally we default user identity to `Local User` + props.onResult({ + userId: 'local user', + profile: { + email: 'local.user@yourdomain.com', + displayName: 'Local User', + picture: '', + }, + }); + } + + return
; +}; +``` + +- use `DummySingInComponent` as `SignInPage` by changing `createApp` statement as follow: + +```ts +const app = createApp({ + apis, + plugins: Object.values(plugins), + components: { + SignInPage: DummySignInComponent, + }, + bindRoutes({ bind }) { + bind(catalogPlugin.externalRoutes, { + createComponent: scaffolderPlugin.routes.root, + }); + bind(apiDocsPlugin.externalRoutes, { + createComponent: scaffolderPlugin.routes.root, + }); + }, +}); +``` + +### Backend + +When using ALB auth it is not possible to leverage the built-in auth config discovery mechanism implemented in the app created by default: a bespoke logic needs to be implemented. + +- replace the content of `packages/backend/plugin/auth.ts` with the below + +```ts +import { + createRouter, + AuthResponse, + AuthProviderFactoryOptions, + defaultAuthProviderFactories, +} from '@backstage/plugin-auth-backend'; +import { PluginEnvironment } from '../types'; + +export default async function createPlugin({ + logger, + database, + config, + discovery, +}: PluginEnvironment) { + const identityResolver = (payload: any): Promise> => { + return Promise.resolve({ + providerInfo: {}, + profile: { + email: payload.email, + displayName: payload.name, + picture: payload.picture, + }, + backstageIdentity: { + id: payload.email, + }, + }); + }; + const providerFactories = { + awsalb: (options: AuthProviderFactoryOptions) => + defaultAuthProviderFactories.awsalb({ ...options, identityResolver }), + }; + return await createRouter({ + logger, + config, + database, + discovery, + providerFactories, + }); +} +``` + +### Configuration + +Use the following `auth` configuration when running Backstage on AWS: + +```yaml +auth: + providers: + awsalb: + issuer: + issuer: https://login.microsoftonline.com/{TENANT_ID}/v2.0 + region: { AWS_REGION } +``` + +Replace `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App and `{AWS_REGION}` with the AWS region identifier where the ALB is deployed (for example: `eu-central-1`). + +## Conclusion + +Once it's deployed, after going through the AAD authentication flow, Backstage should display the AAD user details. + +Special thanks to [@backjo][gh-backjo] for implementing the `auth-backend` provider for AWS ALB on [#4047][pr-4047] + + + +[monorepo-app-setup-with-auth-ms]: https://backstage.io/docs/tutorials/quickstart-app-auth#the-auth-configuration +[gh-backjo]: https://github.com/backjo +[pr-4047]: https://github.com/backstage/backstage/pull/4047 From 3074cfc0403d27fceb6904cc2e3610ff3c2e2e73 Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Mon, 5 Apr 2021 09:05:44 +0100 Subject: [PATCH 049/395] fix syntax, remove conclusion thanking (everybody should be thanked) Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 9dab72fe66..5041e60149 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -1,6 +1,6 @@ # Using AWS Application Load Balancer with Azure Active Directory to authenticate requests -Backstage allows to offload the responsibility of authenticating users to AWS Application Loadbalancer (**ALB**), leveraging the authentication support on ALB. +Backstage allows to offload the responsibility of authenticating users to AWS Application Load Balancer (**ALB**), leveraging the authentication support on ALB. This tutorial shows how to use authentication on an ALB sitting in front of Backstage. Azure Active Directory (**AAD**) is used as identity provider but any identity provider supporting OpenID Connect (OIDC) can be used. @@ -170,10 +170,6 @@ Replace `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App a Once it's deployed, after going through the AAD authentication flow, Backstage should display the AAD user details. -Special thanks to [@backjo][gh-backjo] for implementing the `auth-backend` provider for AWS ALB on [#4047][pr-4047] - [monorepo-app-setup-with-auth-ms]: https://backstage.io/docs/tutorials/quickstart-app-auth#the-auth-configuration -[gh-backjo]: https://github.com/backjo -[pr-4047]: https://github.com/backstage/backstage/pull/4047 From ffc6b81ffa50cff0034b155d1c584237c8b5797e Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:44:57 +0200 Subject: [PATCH 050/395] Update contrib/docs/tutorials/aws-alb-aad-oidc-auth.md Co-authored-by: Tim Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 5041e60149..4a29ce6758 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -47,7 +47,7 @@ Once you've saved the action, you should see an authentication flow be triggered ### Frontend -The Backstage App needs a SingInPage when authentication is required. +The Backstage App needs a SignInPage when authentication is required. When using ALB authentication Backstage will only be loaded once the user has successfully authenticated; we won't need to display a SignIn page, however we will need to create a dummy SignIn component that can refresh the token. - edit `packages/app/src/App.tsx` From ee9ecc99b4eb7096de97e1a693f626984852b2f6 Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:45:09 +0200 Subject: [PATCH 051/395] Update contrib/docs/tutorials/aws-alb-aad-oidc-auth.md Co-authored-by: Tim Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 4a29ce6758..7af2a12f5f 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -1,6 +1,6 @@ # Using AWS Application Load Balancer with Azure Active Directory to authenticate requests -Backstage allows to offload the responsibility of authenticating users to AWS Application Load Balancer (**ALB**), leveraging the authentication support on ALB. +Backstage allows offloading the responsibility of authenticating users to an AWS Application Load Balancer (**ALB**), leveraging the authentication support on ALB. This tutorial shows how to use authentication on an ALB sitting in front of Backstage. Azure Active Directory (**AAD**) is used as identity provider but any identity provider supporting OpenID Connect (OIDC) can be used. From 529c968413a16528b97571a4a580e2726c7cb4ed Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:45:23 +0200 Subject: [PATCH 052/395] Update contrib/docs/tutorials/aws-alb-aad-oidc-auth.md Co-authored-by: Tim Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 7af2a12f5f..6c1436cf09 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -23,7 +23,7 @@ Instead of `localhost` addresses, use the following values. ### ALB -In AWS console configure ALB Authentication as described below: +In the AWS console, configure ALB Authentication: - Edit the ALB rule used to forward the traffic to Backstage and add a new `Authenticate` action. The action will have higher priority compared to the existing `Forward to`. - Select `OIDC` under `Authenticate` From c3a659599917f9b7b6812e850ff865fa424d7e0e Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:46:06 +0200 Subject: [PATCH 053/395] Update contrib/docs/tutorials/aws-alb-aad-oidc-auth.md Co-authored-by: Tim Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 6c1436cf09..158368f72a 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -41,7 +41,7 @@ Use the following advanced settings: - `Scope` = `openid profile offline_access` - `Action on unauthenticated request` = `Autenticate (client reattempt)` -Once you've saved the action, you should see an authentication flow be triggered against AAD when visiting Backstage address at `https://backstage.yourdomain.com`. The flow will not complete successfully as Backstage app isn't yet configured properly. +Once you've saved the action, you should see an authentication flow be triggered against AAD when visiting Backstage address at `https://backstage.yourdomain.com`. The flow will not complete successfully as the Backstage app isn't yet configured properly. ## Backstage changes From 68717560ba2ce103c76340e6235e8d6f99d35298 Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:46:19 +0200 Subject: [PATCH 054/395] Update contrib/docs/tutorials/aws-alb-aad-oidc-auth.md Co-authored-by: Tim Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 158368f72a..ebaf8cb3ba 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -51,7 +51,7 @@ The Backstage App needs a SignInPage when authentication is required. When using ALB authentication Backstage will only be loaded once the user has successfully authenticated; we won't need to display a SignIn page, however we will need to create a dummy SignIn component that can refresh the token. - edit `packages/app/src/App.tsx` -- import the following two additional definitions from `@backstage/core`: `useApi`, `configApiRef`; these will be used to check wether backstage is running locally or behind an ALB +- import the following two additional definitions from `@backstage/core`: `useApi`, `configApiRef`; these will be used to check whether Backstage is running locally or behind an ALB - add the following definition just before the app is created (`const app = createApp`): ```ts From c59c13190561385326971962b41a878ee171430b Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:46:28 +0200 Subject: [PATCH 055/395] Update contrib/docs/tutorials/aws-alb-aad-oidc-auth.md Co-authored-by: Tim Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index ebaf8cb3ba..a36eb18833 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -83,7 +83,7 @@ const DummySignInComponent: any = (props: any) => { }; ``` -- use `DummySingInComponent` as `SignInPage` by changing `createApp` statement as follow: +- use `DummySignInComponent` as `SignInPage` by changing the `createApp` call: ```ts const app = createApp({ From 3eb5825045472f5e98a8825620a192e37800e035 Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:46:44 +0200 Subject: [PATCH 056/395] Update contrib/docs/tutorials/aws-alb-aad-oidc-auth.md Co-authored-by: Tim Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index a36eb18833..4eb52aa53c 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -105,7 +105,7 @@ const app = createApp({ ### Backend -When using ALB auth it is not possible to leverage the built-in auth config discovery mechanism implemented in the app created by default: a bespoke logic needs to be implemented. +When using ALB auth it is not possible to leverage the built-in auth config discovery mechanism implemented in the app created by default; bespoke logic needs to be implemented. - replace the content of `packages/backend/plugin/auth.ts` with the below From 0a0e1481500b66dd1f69a1266a37fdeb900c3f2d Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 22:51:36 +0100 Subject: [PATCH 057/395] using guest user convention Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 4eb52aa53c..4d90079046 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -70,10 +70,10 @@ const DummySignInComponent: any = (props: any) => { } else { // when running locally we default user identity to `Local User` props.onResult({ - userId: 'local user', + userId: 'guest', profile: { - email: 'local.user@yourdomain.com', - displayName: 'Local User', + email: 'guest@example.com', + displayName: 'Guest', picture: '', }, }); From b76b5ef9873cad5c2dfefdbcd3beeafc7a3f57be Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 22:55:44 +0100 Subject: [PATCH 058/395] remove details of createApp call Signed-off-by: Marco Crivellaro --- contrib/docs/tutorials/aws-alb-aad-oidc-auth.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 4d90079046..2503c31756 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -68,7 +68,6 @@ const DummySignInComponent: any = (props: any) => { }); }); } else { - // when running locally we default user identity to `Local User` props.onResult({ userId: 'guest', profile: { @@ -83,23 +82,16 @@ const DummySignInComponent: any = (props: any) => { }; ``` -- use `DummySignInComponent` as `SignInPage` by changing the `createApp` call: +- add `DummySignInComponent` as `SignInPage`: ```ts const app = createApp({ - apis, - plugins: Object.values(plugins), + ... components: { SignInPage: DummySignInComponent, + ... }, - bindRoutes({ bind }) { - bind(catalogPlugin.externalRoutes, { - createComponent: scaffolderPlugin.routes.root, - }); - bind(apiDocsPlugin.externalRoutes, { - createComponent: scaffolderPlugin.routes.root, - }); - }, + ... }); ``` From 703f47042a6bd24f7dc44796e4b30da4f06246ae Mon Sep 17 00:00:00 2001 From: Marco Crivellaro Date: Thu, 8 Apr 2021 23:15:05 +0100 Subject: [PATCH 059/395] handling error by outputing the message to the div Signed-off-by: Marco Crivellaro --- .../docs/tutorials/aws-alb-aad-oidc-auth.md | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 2503c31756..ba0aef89ea 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -56,29 +56,32 @@ When using ALB authentication Backstage will only be loaded once the user has su ```ts const DummySignInComponent: any = (props: any) => { - const config = useApi(configApiRef); - const shouldAuth = !!config.getOptionalConfig('auth.providers.awsalb'); - if (shouldAuth) { - fetch(`${window.location.origin}/api/auth/awsalb/refresh`) - .then(data => data.json()) - .then(data => { - props.onResult({ - userId: data.backstageIdentity.id, - profile: data.profile, + try { + const config = useApi(configApiRef); + const shouldAuth = !!config.getOptionalConfig('auth.providers.awsalb'); + if (shouldAuth) { + fetch(`${window.location.origin}/api/auth/awsalb/refresh`) + .then(data => data.json()) + .then(data => { + props.onResult({ + userId: data.backstageIdentity.id, + profile: data.profile, + }); }); + } else { + props.onResult({ + userId: 'guest', + profile: { + email: 'guest@example.com', + displayName: 'Guest', + picture: '', + }, }); - } else { - props.onResult({ - userId: 'guest', - profile: { - email: 'guest@example.com', - displayName: 'Guest', - picture: '', - }, - }); + } + return
; + } catch (err) { + return
{err.message}
; } - - return
; }; ``` From 3ecc89665f3e8e512036c52382d08fb289fa174b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Apr 2021 04:19:46 +0000 Subject: [PATCH 060/395] chore(deps): bump @asyncapi/react-component from 0.19.2 to 0.22.3 Bumps [@asyncapi/react-component](https://github.com/asyncapi/asyncapi-react) from 0.19.2 to 0.22.3. - [Release notes](https://github.com/asyncapi/asyncapi-react/releases) - [Commits](https://github.com/asyncapi/asyncapi-react/compare/v0.19.2...v0.22.3) Signed-off-by: dependabot[bot] --- plugins/api-docs/package.json | 2 +- yarn.lock | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index d7f5f3754b..5f56c32f23 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.19.2", + "@asyncapi/react-component": "^0.22.3", "@backstage/catalog-model": "^0.7.5", "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.4", diff --git a/yarn.lock b/yarn.lock index 0b74a64a59..6a44b598d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -81,28 +81,29 @@ dependencies: "@openapi-contrib/openapi-schema-to-json-schema" "^3.0.0" -"@asyncapi/parser@^1.4.0": - version "1.4.0" - resolved "https://registry.npmjs.org/@asyncapi/parser/-/parser-1.4.0.tgz#a0b0e3cb1803400d93b15f7c354fe95824a36e2c" - integrity sha512-rI0UF9niaqUxZqFS2+iBvkekxhI3cXOv/O+i+w/1EhpPppLicPVnazQbBqQ1iO37sio+CPejJbeoBgj8m+ylPw== +"@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== dependencies: "@apidevtools/json-schema-ref-parser" "^9.0.6" - "@asyncapi/specs" "^2.7.6" + "@asyncapi/specs" "^2.7.7" "@fmvilas/pseudo-yaml-ast" "^0.3.1" ajv "^6.10.1" js-yaml "^3.13.1" json-to-ast "^2.1.0" + lodash.clonedeep "^4.5.0" node-fetch "^2.6.0" tiny-merge-patch "^0.1.2" -"@asyncapi/react-component@^0.19.2": - version "0.19.2" - resolved "https://registry.npmjs.org/@asyncapi/react-component/-/react-component-0.19.2.tgz#364a1d839e6f49a454fcb44b544f9496d1501b93" - integrity sha512-NXLBVaJdXqsIX98tF8fKxjTDf6cE+ym3Fkp3IQhMQh/6o1X2y/YVp+XkjfLO2C/Ccb/Cys1C5OnqipfwEY1oqA== +"@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== dependencies: "@asyncapi/avro-schema-parser" "^0.2.0" "@asyncapi/openapi-schema-parser" "^2.0.0" - "@asyncapi/parser" "^1.4.0" + "@asyncapi/parser" "^1.4.4" constate "^1.2.0" dompurify "^2.1.1" markdown-it "^11.0.1" @@ -110,10 +111,10 @@ openapi-sampler "^1.0.0-beta.15" react-use "^12.2.0" -"@asyncapi/specs@^2.7.6": - version "2.7.6" - resolved "https://registry.npmjs.org/@asyncapi/specs/-/specs-2.7.6.tgz#d04ad015a148cd222f7939b9561360ab903de632" - integrity sha512-2IYlLA02beYQKVJVCAqV+G5tXRI4s8yeKYiszuoxS178psdAMKxgXtng8hUYPOqSvU6X4lc+Jabk1zSQFHifVg== +"@asyncapi/specs@^2.7.7": + version "2.7.7" + resolved "https://registry.npmjs.org/@asyncapi/specs/-/specs-2.7.7.tgz#10f72c95153a3cc10039f6ba9c3a6f7c3b7fecfc" + integrity sha512-z8kj4GDJ640DU4msRsWprvmuC9n7vIeJW+D7Tp1xdefoLX5ZJrK7+4Xruna513wV0fSLpFzCmGz7McEP6CtKDg== "@azure/abort-controller@^1.0.0": version "1.0.2" @@ -4236,7 +4237,7 @@ dependencies: "@octokit/openapi-types" "^5.3.2" -"@octokit/types@^6.13.0": +"@octokit/types@^6.13.0", "@octokit/types@^6.8.2": version "6.13.0" resolved "https://registry.npmjs.org/@octokit/types/-/types-6.13.0.tgz#779e5b7566c8dde68f2f6273861dd2f0409480d0" integrity sha512-W2J9qlVIU11jMwKHUp5/rbVUeErqelCsO5vW5PKNb7wAXQVUz87Rc+imjlEvpvbH8yUb+KHmv8NEjVZdsdpyxA== From 017192ee84850454325e205e138d554b533ef8e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20A=CC=8Ahsberg?= Date: Thu, 8 Apr 2021 18:47:02 +0000 Subject: [PATCH 061/395] Support multiline LDAP filter queries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathias Åhsberg --- .changeset/green-otters-grin.md | 5 +++ .../ingestion/processors/ldap/config.test.ts | 31 +++++++++++++++++++ .../src/ingestion/processors/ldap/config.ts | 7 ++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 .changeset/green-otters-grin.md diff --git a/.changeset/green-otters-grin.md b/.changeset/green-otters-grin.md new file mode 100644 index 0000000000..abfd332a2b --- /dev/null +++ b/.changeset/green-otters-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Add support for configure an LDAP query filter on multiple lines. 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 5e293766aa..aac9a091b8 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts @@ -172,4 +172,35 @@ describe('readLdapConfig', () => { ]; expect(actual).toEqual(expected); }); + + it('supports multiline ldap query filter', () => { + const config = { + providers: [ + { + target: 'target', + users: { + dn: 'udn', + options: { + filter: ` + (| + (cn=foo bar) + (cn=bar) + ) + `, + }, + }, + groups: { + dn: 'gdn', + options: { + filter: 'f', + }, + }, + }, + ], + }; + const actual = readLdapConfig(new ConfigReader(config)); + + const expected = '(|(cn=foo bar)(cn=bar))'; + expect(actual[0].users.options.filter).toEqual(expected); + }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts index 7608f247d4..625282ca05 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts @@ -182,7 +182,7 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { } return { scope: c.getOptionalString('scope') as SearchOptions['scope'], - filter: c.getOptionalString('filter'), + filter: formatFilter(c.getOptionalString('filter')), attributes: c.getOptionalStringArray('attributes'), paged: c.getOptionalBoolean('paged'), }; @@ -260,6 +260,11 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { }; } + function formatFilter(filter?: string): string | undefined { + // Remove extra whitespaces between blocks to support multiline filters from the configuration + return filter?.replace(/\s*(\(|\))/g, '$1')?.trim(); + } + const providerConfigs = config.getOptionalConfigArray('providers') ?? []; return providerConfigs.map(c => { const newConfig = { From 484899f6df15e3d9fc73926acd4986abed4f6adf Mon Sep 17 00:00:00 2001 From: Remi Kristelijn Date: Fri, 9 Apr 2021 09:11:02 +0200 Subject: [PATCH 062/395] fix: removes alternative colors Signed-off-by: Remi Kristelijn --- packages/theme/src/pageTheme.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/theme/src/pageTheme.ts b/packages/theme/src/pageTheme.ts index 6d364ea351..c9a61bd95b 100644 --- a/packages/theme/src/pageTheme.ts +++ b/packages/theme/src/pageTheme.ts @@ -64,8 +64,4 @@ export const pageTheme: Record = { other: genPageTheme(colorVariants.darkGrey, shapes.wave), app: genPageTheme(colorVariants.toastyOrange, shapes.wave), apis: genPageTheme(colorVariants.eveningSea, shapes.wave2), - grpc: genPageTheme(colorVariants.marineBlue, shapes.wave2), - asyncapi: genPageTheme(colorVariants.rubyRed, shapes.wave2), - graphql: genPageTheme(colorVariants.purpleSky, shapes.wave2), - openapi: genPageTheme(colorVariants.toastyOrange, shapes.wave2), }; From 36e233cb026801dc23c76c04a8aebd77024ef6b0 Mon Sep 17 00:00:00 2001 From: Remi Kristelijn Date: Fri, 9 Apr 2021 09:11:50 +0200 Subject: [PATCH 063/395] fix: missing code Signed-off-by: Remi Kristelijn --- docs/getting-started/app-custom-theme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index 473da02670..181f541929 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -131,7 +131,7 @@ const themeOptions = createThemeOptions({ library: genPageTheme(['#123456','#123456'] shapes.wave), other: genPageTheme(['#123456','#123456'], shapes.wave), app: genPageTheme(['#123456','#123456'], shapes.wave), - apis: genPageTheme(['#123456','#123456'], + apis: genPageTheme(['#123456','#123456'], shapes.wave), }, }); ``` From 26ae929a7b7b84b22cbbe4f804e67e431cf6c619 Mon Sep 17 00:00:00 2001 From: David Tuite Date: Fri, 2 Apr 2021 17:26:06 +0100 Subject: [PATCH 064/395] Upgrade @graphql-codeget/cli to latest Signed-off-by: David Tuite --- plugins/catalog-graphql/package.json | 2 +- yarn.lock | 203 +++++++++++++++++---------- 2 files changed, 132 insertions(+), 73 deletions(-) diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 1e2124f3df..3ab6d64dc8 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -44,7 +44,7 @@ "devDependencies": { "@backstage/cli": "^0.6.5", "@backstage/test-utils": "^0.1.9", - "@graphql-codegen/cli": "^1.17.7", + "@graphql-codegen/cli": "^1.21.3", "@graphql-codegen/typescript": "^1.17.7", "@graphql-codegen/typescript-resolvers": "^1.17.7", "@types/express": "^4.17.7", diff --git a/yarn.lock b/yarn.lock index c3bd4a2296..cf967cf96f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2199,6 +2199,16 @@ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2": + version "3.0.2" + resolved "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d" + integrity sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA== + dependencies: + lodash.get "^4" + make-error "^1" + ts-node "^9" + tslib "^2" + "@eslint/eslintrc@^0.2.1": version "0.2.1" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" @@ -2419,13 +2429,13 @@ meros "^1.1.2" subscriptions-transport-ws "^0.9.18" -"@graphql-codegen/cli@^1.17.7": - version "1.17.10" - resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.17.10.tgz#efebf9b887fdb94dd26dbf3eb1950e832efcda0e" - integrity sha512-nQYbabB3aS3XArETJc/NrpUtlj/Dzh2KeDgvVRsc3zxopcudZTKj1dcTCOA/QZPSpbzALbZZ/1loBVVrMIe+Iw== +"@graphql-codegen/cli@^1.21.3": + version "1.21.3" + resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.21.3.tgz#3506c5d019c6995be1927bd4d9c67a739fafe5e6" + integrity sha512-jwg0mKhseg0QI4/T4IQcttTBCZgnahiTWqnYWIK+E8nrbXCE9o2hxvaYin/Kq9+5oFtxDePED56cjVs/ESRw6g== dependencies: - "@graphql-codegen/core" "1.17.8" - "@graphql-codegen/plugin-helpers" "^1.17.9" + "@graphql-codegen/core" "1.17.9" + "@graphql-codegen/plugin-helpers" "^1.18.4" "@graphql-tools/apollo-engine-loader" "^6" "@graphql-tools/code-file-loader" "^6" "@graphql-tools/git-loader" "^6" @@ -2435,19 +2445,18 @@ "@graphql-tools/load" "^6" "@graphql-tools/prisma-loader" "^6" "@graphql-tools/url-loader" "^6" - "@graphql-tools/utils" "^6" + "@graphql-tools/utils" "^7.0.0" ansi-escapes "^4.3.1" - camel-case "^4.1.1" chalk "^4.1.0" - chokidar "^3.4.2" + change-case-all "1.0.12" + chokidar "^3.4.3" common-tags "^1.8.0" - constant-case "^3.0.3" cosmiconfig "^7.0.0" debounce "^1.2.0" - dependency-graph "^0.9.0" + dependency-graph "^0.11.0" detect-indent "^6.0.0" glob "^7.1.6" - graphql-config "^3.0.2" + graphql-config "^3.2.0" indent-string "^4.0.0" inquirer "^7.3.3" is-glob "^4.0.1" @@ -2456,30 +2465,27 @@ listr "^0.14.3" listr-update-renderer "^0.5.0" log-symbols "^4.0.0" - lower-case "^2.0.1" minimatch "^3.0.4" mkdirp "^1.0.4" - pascal-case "^3.1.1" - request "^2.88.2" string-env-interpolation "^1.0.1" ts-log "^2.2.3" - tslib "~2.0.1" - upper-case "^2.0.1" + tslib "~2.1.0" valid-url "^1.0.9" wrap-ansi "^7.0.0" - yargs "^16.0.3" + yaml "^1.10.0" + yargs "^16.1.1" -"@graphql-codegen/core@1.17.8": - version "1.17.8" - resolved "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.17.8.tgz#d70281bcf9f4b7b560ab5b16f7fc7a2853c49a8a" - integrity sha512-HUntoeLhLZf6wroD1HYLsniz51N3zW7cjgwojGKgbUsI6Oa8pGsh+kKaN9xtvlb/hIpsRJ00q9LbPVIM/kXQtQ== +"@graphql-codegen/core@1.17.9": + version "1.17.9" + resolved "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.17.9.tgz#c03e71018ff04d26f5139a2d90a32b31d3bb2b43" + integrity sha512-7nwy+bMWqb0iYJ2DKxA9UiE16meeJ2Ch2XWS/N/ZnA0snTR+GZ20USI8z6YqP1Fuist7LvGO1MbitO2qBT8raA== dependencies: - "@graphql-codegen/plugin-helpers" "^1.17.8" - "@graphql-tools/merge" "^6.0.18" - "@graphql-tools/utils" "^6.0.18" - tslib "~2.0.0" + "@graphql-codegen/plugin-helpers" "^1.18.2" + "@graphql-tools/merge" "^6" + "@graphql-tools/utils" "^6" + tslib "~2.0.1" -"@graphql-codegen/plugin-helpers@^1.17.8", "@graphql-codegen/plugin-helpers@^1.17.9", "@graphql-codegen/plugin-helpers@^1.18.2", "@graphql-codegen/plugin-helpers@^1.18.3": +"@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== @@ -2490,6 +2496,17 @@ 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" + "@graphql-codegen/typescript-resolvers@^1.17.7": version "1.18.2" resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-1.18.2.tgz#7513b92df7c5a0d3c27342c591ada7340696cf8f" @@ -2675,6 +2692,15 @@ unixify "1.0.0" valid-url "1.0.9" +"@graphql-tools/merge@^6": + version "6.2.11" + resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.11.tgz#398f6c5fb6498fe0b5f062c65cf648c0e4a57e9c" + integrity sha512-temQABWkDTZb/qJwcIdrEbyJ5WkhaWZQeYxiuxGqZWlIOoFkYfqzfAP2qKl2Ry+ZkN+Q/Yozr1/ap//xjpwAlA== + dependencies: + "@graphql-tools/schema" "^7.0.0" + "@graphql-tools/utils" "^7.7.0" + tslib "~2.1.0" + "@graphql-tools/merge@^6.0.0": version "6.0.15" resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.0.15.tgz#09c84bd08971edfb3e1035d71432b47687820bdc" @@ -2684,15 +2710,6 @@ "@graphql-tools/utils" "6.0.15" tslib "~2.0.0" -"@graphql-tools/merge@^6.0.18": - version "6.0.18" - resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.0.18.tgz#d105e16c6f5f874ddfdba3f3f4a2f676a6d2d04a" - integrity sha512-XAFbqMyXsExnuzgr5+JQC8mxsYp0aGIR0m+GbleQDZSlqDOL2maF5xM3dGOOkguz0Paa7ei/5UfnMXyRU3cW/w== - dependencies: - "@graphql-tools/schema" "6.0.18" - "@graphql-tools/utils" "6.0.18" - tslib "~2.0.0" - "@graphql-tools/merge@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.4.tgz#5b3b68083d55a38a7f3caac6e0adc46f428c2a3b" @@ -2756,14 +2773,6 @@ "@graphql-tools/utils" "6.0.15" tslib "~2.0.0" -"@graphql-tools/schema@6.0.18": - version "6.0.18" - resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.0.18.tgz#243eb370e4cded00767202bbabf0893f65c3f5b9" - integrity sha512-xrScjRX9pTSVxqiSkx7Hn/9rzxLweysINa5Pkirdkv5lJY4e0Db53osur0nG/+SJyUmIN70tUtuhEZq4Ezr/PA== - dependencies: - "@graphql-tools/utils" "6.0.18" - tslib "~2.0.0" - "@graphql-tools/schema@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.2.4.tgz#cc4e9f5cab0f4ec48500e666719d99fc5042481d" @@ -2772,6 +2781,14 @@ "@graphql-tools/utils" "^6.2.4" tslib "~2.0.1" +"@graphql-tools/schema@^7.0.0": + version "7.1.3" + resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.1.3.tgz#d816400da51fbac1f0086e35540ab63b5e30e858" + integrity sha512-ZY76hmcJlF1iyg3Im0sQ3ASRkiShjgv102vLTVcH22lEGJeCaCyyS/GF1eUHom418S60bS8Th6+autRUxfBiBg== + dependencies: + "@graphql-tools/utils" "^7.1.2" + tslib "~2.1.0" + "@graphql-tools/url-loader@^6", "@graphql-tools/url-loader@^6.0.0", "@graphql-tools/url-loader@^6.2.4": version "6.3.0" resolved "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-6.3.0.tgz#75b82bdf0983d3e389c75948a7abff20fa45a630" @@ -2795,15 +2812,7 @@ "@ardatan/aggregate-error" "0.0.1" camel-case "4.1.1" -"@graphql-tools/utils@6.0.18": - version "6.0.18" - resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.0.18.tgz#bba960f0ab327c8304089d41da0b7a3e00fe430f" - integrity sha512-8ntYuXJucBtjViOYljeKBzScfpVTnv7BfqIPU/WJ65h6nXD+qf8fMUR1C4MpCUeFvSjMiDSB5Z4enJmau/9D3A== - dependencies: - "@ardatan/aggregate-error" "0.0.1" - camel-case "4.1.1" - -"@graphql-tools/utils@^6", "@graphql-tools/utils@^6.0.0", "@graphql-tools/utils@^6.0.18", "@graphql-tools/utils@^6.2.4": +"@graphql-tools/utils@^6", "@graphql-tools/utils@^6.0.0", "@graphql-tools/utils@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.2.4.tgz#38a2314d2e5e229ad4f78cca44e1199e18d55856" integrity sha512-ybgZ9EIJE3JMOtTrTd2VcIpTXtDrn2q6eiYkeYMKRVh3K41+LZa6YnR2zKERTXqTWqhobROwLt4BZbw2O3Aeeg== @@ -2821,6 +2830,15 @@ camel-case "4.1.2" tslib "~2.1.0" +"@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.7.0": + version "7.7.1" + resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.7.1.tgz#81f32cb4819b34b3a378d51ab2cd60935977f0b4" + integrity sha512-SFT4/dTfrwWer1wSOLU+jqgv3oa/xTR8q+MiNbE9nCH2FXyMsqIOaXKm9wHfKIWFWHozqBdcnwFkQZrdD7H2TQ== + dependencies: + "@ardatan/aggregate-error" "0.0.6" + camel-case "4.1.2" + tslib "~2.1.0" + "@graphql-tools/wrap@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-6.2.4.tgz#2709817da6e469753735a9fe038c9e99736b2c57" @@ -2871,6 +2889,11 @@ prop-types "^15.6.2" scheduler "^0.19.0" +"@iarna/toml@^2.2.5": + version "2.2.5" + resolved "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" + integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== + "@icons/material@^0.2.4": version "0.2.4" resolved "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" @@ -9528,7 +9551,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== @@ -9638,6 +9661,21 @@ chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.3.1, chokidar@^3.4.1, chokidar@^3. optionalDependencies: fsevents "~2.1.2" +chokidar@^3.4.3: + version "3.5.1" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -10265,15 +10303,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -constant-case@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/constant-case/-/constant-case-3.0.3.tgz#ac910a99caf3926ac5112f352e3af599d8c5fc0a" - integrity sha512-FXtsSnnrFYpzDmvwDGQW+l8XK3GV1coLyBN0eBz16ZUzGaZcT2ANVCJmLeuw2GQgxKHQIe9e0w2dzkSfaRlUmA== - dependencies: - no-case "^3.0.3" - tslib "^1.10.0" - upper-case "^2.0.1" - constant-case@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" @@ -10490,6 +10519,13 @@ cors@^2.8.4, cors@^2.8.5: object-assign "^4" vary "^1" +cosmiconfig-toml-loader@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/cosmiconfig-toml-loader/-/cosmiconfig-toml-loader-1.0.0.tgz#0681383651cceff918177debe9084c0d3769509b" + integrity sha512-H/2gurFWVi7xXvCyvsWRLCMekl4tITJcX0QEsDMpzxtuxDyM59xLatYNg4s/k9AA/HdtCYfj2su8mgA0GSDLDA== + dependencies: + "@iarna/toml" "^2.2.5" + cosmiconfig@6.0.0, cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -11529,11 +11565,6 @@ dependency-graph@^0.11.0: resolved "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== -dependency-graph@^0.9.0: - version "0.9.0" - resolved "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318" - integrity sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w== - deprecated-decorator@^0.1.6: version "0.1.6" resolved "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37" @@ -13735,6 +13766,11 @@ fsevents@^2.1.2, fsevents@~2.1.2: resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + fstream@^1.0.0, fstream@^1.0.12: version "1.0.12" resolved "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" @@ -14429,6 +14465,24 @@ graphql-config@^3.0.2: string-env-interpolation "1.0.1" tslib "^2.0.0" +graphql-config@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/graphql-config/-/graphql-config-3.2.0.tgz#3ec3a7e319792086b80e54db4b37372ad4a79a32" + integrity sha512-ygEKDeQNZKpm4137560n2oY3bGM0D5zyRsQVaJntKkufWdgPg6sb9/4J1zJW2y/yC1ortAbhNho09qmeJeLa9g== + dependencies: + "@endemolshinegroup/cosmiconfig-typescript-loader" "3.0.2" + "@graphql-tools/graphql-file-loader" "^6.0.0" + "@graphql-tools/json-file-loader" "^6.0.0" + "@graphql-tools/load" "^6.0.0" + "@graphql-tools/merge" "^6.0.0" + "@graphql-tools/url-loader" "^6.0.0" + "@graphql-tools/utils" "^6.0.0" + cosmiconfig "6.0.0" + cosmiconfig-toml-loader "1.0.0" + minimatch "3.0.4" + string-env-interpolation "1.0.1" + tslib "^2.0.0" + graphql-extensions@^0.12.8: version "0.12.8" resolved "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.8.tgz#9cdc2c43d8fe5e0f6c3177a004ac011da2a8aa0f" @@ -17758,6 +17812,11 @@ 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: + version "4.4.2" + resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -18062,7 +18121,7 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@1.x, make-error@^1.1.1, make-error@^1.3.6: +make-error@1.x, make-error@^1, make-error@^1.1.1, make-error@^1.3.6: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -25501,7 +25560,7 @@ ts-node@^8.10.2, ts-node@^8.6.2: source-map-support "^0.5.17" yn "3.1.1" -ts-node@^9.1.1: +ts-node@^9, ts-node@^9.1.1: version "9.1.1" resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== @@ -25543,7 +25602,7 @@ 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.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@~2.1.0: +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== @@ -27102,7 +27161,7 @@ yargs@^15.1.0, yargs@^15.3.1, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.0.3, yargs@^16.2.0: +yargs@^16.0.3, yargs@^16.1.1, yargs@^16.2.0: version "16.2.0" resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== From 8fd2a3364266a51b5291649a9a22a274d4e18dce Mon Sep 17 00:00:00 2001 From: Tim Hansen Date: Fri, 9 Apr 2021 13:02:54 -0600 Subject: [PATCH 065/395] Export SignInConfig type Signed-off-by: Tim Hansen --- packages/core/src/layout/SignInPage/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/layout/SignInPage/index.ts b/packages/core/src/layout/SignInPage/index.ts index 49f55aefc5..9ea0be9cbd 100644 --- a/packages/core/src/layout/SignInPage/index.ts +++ b/packages/core/src/layout/SignInPage/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ +export type { SignInConfig } from './types'; export { SignInPage } from './SignInPage'; From 84c54474dd43e873b3662f1824cdcf08759baf55 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Thu, 1 Apr 2021 15:24:33 +0200 Subject: [PATCH 066/395] fix: Forward user token to scaffolder taskworker for subsequent api requests Signed-off-by: Erik Larsson --- .changeset/eight-plums-hide.md | 5 +++++ plugins/scaffolder-backend/src/scaffolder/actions/types.ts | 4 ++++ .../scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts | 1 + plugins/scaffolder-backend/src/scaffolder/tasks/types.ts | 1 + plugins/scaffolder-backend/src/service/router.ts | 6 +++++- 5 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .changeset/eight-plums-hide.md diff --git a/.changeset/eight-plums-hide.md b/.changeset/eight-plums-hide.md new file mode 100644 index 0000000000..bf34b7ee63 --- /dev/null +++ b/.changeset/eight-plums-hide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Forward user token to scaffolder taskworker for subsequent api requests diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts index 955cb72de9..fbe18b848e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts @@ -32,6 +32,10 @@ export type ActionContext = { logger: Logger; logStream: Writable; + /** + * User token forwarded from initial request, for use in subsequent api requests + */ + token?: string | undefined; workspacePath: string; input: Input; output(name: string, value: JsonValue): void; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index 3a846f79a5..a6c97027d2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -134,6 +134,7 @@ export class TaskWorker { logger: taskLogger, logStream: stream, input, + token: task.spec.token, workspacePath, async createTemporaryDirectory() { const tmpDir = await fs.mkdtemp( diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index 6963817a1e..a5affc418d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -44,6 +44,7 @@ export type DbTaskEventRow = { export type TaskSpec = { baseUrl?: string; + token?: string | undefined; values: JsonObject; steps: Array<{ id: string; diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 1e2891cfb8..c5f42edd76 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -358,8 +358,9 @@ export async function createRouter( .post('/v2/tasks', async (req, res) => { const templateName: string = req.body.templateName; const values: TemplaterValues = req.body.values; + const token = getBearerToken(req.headers.authorization); const template = await entityClient.findTemplate(templateName, { - token: getBearerToken(req.headers.authorization), + token, }); let taskSpec; @@ -386,6 +387,7 @@ export async function createRouter( taskSpec = { baseUrl, + token, values, steps: template.spec.steps.map((step, index) => ({ ...step, @@ -412,6 +414,8 @@ export async function createRouter( if (!task) { throw new NotFoundError(`Task with id ${taskId} does not exist`); } + // Do not disclose token + delete task.spec.token; res.status(200).json(task); }) .get('/v2/tasks/:taskId/eventstream', async (req, res) => { From 008e8a8b1c02f7b78cd8547e9a07c47ea6ce2259 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Fri, 2 Apr 2021 00:24:22 +0200 Subject: [PATCH 067/395] vale Signed-off-by: Erik Larsson --- .changeset/eight-plums-hide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eight-plums-hide.md b/.changeset/eight-plums-hide.md index bf34b7ee63..d1f8bcecfe 100644 --- a/.changeset/eight-plums-hide.md +++ b/.changeset/eight-plums-hide.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-backend': patch --- -Forward user token to scaffolder taskworker for subsequent api requests +Forward user token to scaffolder task for subsequent api requests From a41a912f2df7988ef9fd6674d42164859b5cd218 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Fri, 9 Apr 2021 23:33:15 +0200 Subject: [PATCH 068/395] Store secrets in separate db column Signed-off-by: Erik Larsson --- .../migrations/20210409225200_secrets.js | 38 +++++++++++++++++++ .../src/scaffolder/tasks/DatabaseTaskStore.ts | 13 ++++++- .../src/scaffolder/tasks/StorageTaskBroker.ts | 8 +++- .../src/scaffolder/tasks/TaskWorker.ts | 2 +- .../src/scaffolder/tasks/types.ts | 14 +++++-- .../scaffolder-backend/src/service/router.ts | 9 +++-- 6 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 plugins/scaffolder-backend/migrations/20210409225200_secrets.js diff --git a/plugins/scaffolder-backend/migrations/20210409225200_secrets.js b/plugins/scaffolder-backend/migrations/20210409225200_secrets.js new file mode 100644 index 0000000000..e1bd6d2a51 --- /dev/null +++ b/plugins/scaffolder-backend/migrations/20210409225200_secrets.js @@ -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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('tasks', table => { + table + .string('secrets') + .nullable() + .comment('JSON encoded secrets to authenticate tasks with'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('tasks', table => { + table.dropColumn('secrets'); + }); +}; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index 91264bd3e2..fdc403ec65 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -24,6 +24,7 @@ import { DbTaskRow, Status, TaskEventType, + TaskSecrets, TaskSpec, TaskStore, TaskStoreEmitOptions, @@ -42,6 +43,7 @@ export type RawDbTaskRow = { status: Status; last_heartbeat_at?: string; created_at: string; + secrets?: string; }; export type RawDbTaskEventRow = { @@ -71,23 +73,29 @@ export class DatabaseTaskStore implements TaskStore { } try { const spec = JSON.parse(result.spec); + const secrets = result.secrets ? JSON.parse(result.secrets) : undefined; return { id: result.id, spec, status: result.status, lastHeartbeatAt: result.last_heartbeat_at, createdAt: result.created_at, + secrets, }; } catch (error) { throw new Error(`Failed to parse spec of task '${taskId}', ${error}`); } } - async createTask(spec: TaskSpec): Promise<{ taskId: string }> { + async createTask( + spec: TaskSpec, + secrets?: TaskSecrets, + ): Promise<{ taskId: string }> { const taskId = uuid(); await this.db('tasks').insert({ id: taskId, spec: JSON.stringify(spec), + secrets: secrets ? JSON.stringify(secrets) : undefined, status: 'open', }); return { taskId }; @@ -119,12 +127,14 @@ export class DatabaseTaskStore implements TaskStore { try { const spec = JSON.parse(task.spec); + const secrets = task.secrets ? JSON.parse(task.spec) : undefined; return { id: task.id, spec, status: 'processing', lastHeartbeatAt: task.last_heartbeat_at, createdAt: task.created_at, + secrets, }; } catch (error) { throw new Error(`Failed to parse spec of task '${task.id}', ${error}`); @@ -209,6 +219,7 @@ export class DatabaseTaskStore implements TaskStore { }) .update({ status, + secrets: undefined, }); if (updateCount !== 1) { throw new ConflictError( diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index fb1f4ab422..8f30afde6f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -18,6 +18,7 @@ import { Logger } from 'winston'; import { CompletedTaskState, Task, + TaskSecrets, TaskSpec, TaskStore, TaskBroker, @@ -136,8 +137,11 @@ export class StorageTaskBroker implements TaskBroker { } } - async dispatch(spec: TaskSpec): Promise { - const taskRow = await this.storage.createTask(spec); + async dispatch( + spec: TaskSpec, + secrets?: TaskSecrets, + ): Promise { + const taskRow = await this.storage.createTask(spec, secrets); this.signalDispatch(); return { taskId: taskRow.taskId, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index a6c97027d2..acdf32a383 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -134,7 +134,7 @@ export class TaskWorker { logger: taskLogger, logStream: stream, input, - token: task.spec.token, + token: task.secrets?.identityToken, workspacePath, async createTemporaryDirectory() { const tmpDir = await fs.mkdtemp( diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index a5affc418d..56d2f25e02 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -31,6 +31,7 @@ export type DbTaskRow = { status: Status; createdAt: string; lastHeartbeatAt?: string; + secrets?: TaskSecrets; }; export type TaskEventType = 'completion' | 'log'; @@ -44,7 +45,6 @@ export type DbTaskEventRow = { export type TaskSpec = { baseUrl?: string; - token?: string | undefined; values: JsonObject; steps: Array<{ id: string; @@ -55,12 +55,17 @@ export type TaskSpec = { output: { [name: string]: string }; }; +export type TaskSecrets = { + identityToken: string | undefined; +}; + export type DispatchResult = { taskId: string; }; export interface Task { spec: TaskSpec; + secrets?: TaskSecrets; done: boolean; emitLog(message: string, metadata?: JsonValue): Promise; complete(result: CompletedTaskState, metadata?: JsonValue): Promise; @@ -69,7 +74,7 @@ export interface Task { export interface TaskBroker { claim(): Promise; - dispatch(spec: TaskSpec): Promise; + dispatch(spec: TaskSpec, secrets?: TaskSecrets): Promise; vacuumTasks(timeoutS: { timeoutS: number }): Promise; observe( options: { @@ -94,7 +99,10 @@ export type TaskStoreGetEventsOptions = { }; export interface TaskStore { - createTask(task: TaskSpec): Promise<{ taskId: string }>; + createTask( + task: TaskSpec, + secrets?: TaskSecrets, + ): Promise<{ taskId: string }>; getTask(taskId: string): Promise; claimTask(): Promise; completeTask(options: { diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index c5f42edd76..c77007a573 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -387,7 +387,6 @@ export async function createRouter( taskSpec = { baseUrl, - token, values, steps: template.spec.steps.map((step, index) => ({ ...step, @@ -404,7 +403,9 @@ export async function createRouter( ); } - const result = await taskBroker.dispatch(taskSpec); + const result = await taskBroker.dispatch(taskSpec, { + identityToken: token, + }); res.status(201).json({ id: result.taskId }); }) @@ -414,8 +415,8 @@ export async function createRouter( if (!task) { throw new NotFoundError(`Task with id ${taskId} does not exist`); } - // Do not disclose token - delete task.spec.token; + // Do not disclose secrets + delete task.secrets; res.status(200).json(task); }) .get('/v2/tasks/:taskId/eventstream', async (req, res) => { From 1073fce8ec6c57dc41c8d29f5019413db713dc88 Mon Sep 17 00:00:00 2001 From: Remi Kristelijn Date: Sat, 10 Apr 2021 08:17:20 +0200 Subject: [PATCH 069/395] fix: not header markdownlint MD041 Signed-off-by: Remi Kristelijn --- .changeset/thirty-owls-lay.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/thirty-owls-lay.md b/.changeset/thirty-owls-lay.md index ce08042276..3f3ce64606 100644 --- a/.changeset/thirty-owls-lay.md +++ b/.changeset/thirty-owls-lay.md @@ -2,4 +2,4 @@ '@backstage/core': patch --- -# exposes undocumented `PageTheme` +exposes undocumented `PageTheme` From 934275ddbd7f07457f79c4a1321e60cd4681ad11 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 5 Apr 2021 15:52:10 +0200 Subject: [PATCH 070/395] plugins: added config-schema plugin Signed-off-by: Patrik Oldsberg --- plugins/config-schema/.eslintrc.js | 3 + plugins/config-schema/README.md | 13 +++ plugins/config-schema/dev/index.tsx | 26 +++++ plugins/config-schema/package.json | 47 ++++++++ .../ExampleComponent.test.tsx | 44 ++++++++ .../ExampleComponent/ExampleComponent.tsx | 53 +++++++++ .../src/components/ExampleComponent/index.ts | 16 +++ .../ExampleFetchComponent.test.tsx | 40 +++++++ .../ExampleFetchComponent.tsx | 105 ++++++++++++++++++ .../components/ExampleFetchComponent/index.ts | 16 +++ plugins/config-schema/src/index.ts | 16 +++ plugins/config-schema/src/plugin.test.ts | 22 ++++ plugins/config-schema/src/plugin.ts | 33 ++++++ plugins/config-schema/src/routes.ts | 20 ++++ plugins/config-schema/src/setupTests.ts | 17 +++ 15 files changed, 471 insertions(+) create mode 100644 plugins/config-schema/.eslintrc.js create mode 100644 plugins/config-schema/README.md create mode 100644 plugins/config-schema/dev/index.tsx create mode 100644 plugins/config-schema/package.json create mode 100644 plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx create mode 100644 plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx create mode 100644 plugins/config-schema/src/components/ExampleComponent/index.ts create mode 100644 plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx create mode 100644 plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx create mode 100644 plugins/config-schema/src/components/ExampleFetchComponent/index.ts create mode 100644 plugins/config-schema/src/index.ts create mode 100644 plugins/config-schema/src/plugin.test.ts create mode 100644 plugins/config-schema/src/plugin.ts create mode 100644 plugins/config-schema/src/routes.ts create mode 100644 plugins/config-schema/src/setupTests.ts diff --git a/plugins/config-schema/.eslintrc.js b/plugins/config-schema/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/plugins/config-schema/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/plugins/config-schema/README.md b/plugins/config-schema/README.md new file mode 100644 index 0000000000..4d5d2c588d --- /dev/null +++ b/plugins/config-schema/README.md @@ -0,0 +1,13 @@ +# config-schema + +Welcome to the config-schema plugin! + +_This plugin was created through the Backstage CLI_ + +## Getting started + +Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/config-schema](http://localhost:3000/config-schema). + +You can also serve the plugin in isolation by running `yarn start` in the plugin directory. +This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. +It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory. diff --git a/plugins/config-schema/dev/index.tsx b/plugins/config-schema/dev/index.tsx new file mode 100644 index 0000000000..1a20bfc62a --- /dev/null +++ b/plugins/config-schema/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 { configSchemaPlugin, ConfigSchemaPage } from '../src/plugin'; + +createDevApp() + .registerPlugin(configSchemaPlugin) + .addPage({ + element: , + title: 'Root Page', + }) + .render(); diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json new file mode 100644 index 0000000000..291a7078be --- /dev/null +++ b/plugins/config-schema/package.json @@ -0,0 +1,47 @@ +{ + "name": "@backstage/plugin-config-schema", + "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/core": "^0.7.3", + "@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", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-use": "^15.3.3" + }, + "devDependencies": { + "@backstage/cli": "^0.6.6", + "@backstage/dev-utils": "^0.1.13", + "@backstage/test-utils": "^0.1.9", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^11.2.5", + "@testing-library/user-event": "^12.0.7", + "@types/jest": "^26.0.7", + "@types/node": "^14.14.32", + "msw": "^0.21.2", + "cross-fetch": "^3.0.6" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx b/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx new file mode 100644 index 0000000000..030495be33 --- /dev/null +++ b/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx @@ -0,0 +1,44 @@ +/* + * 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 { ExampleComponent } from './ExampleComponent'; +import { ThemeProvider } from '@material-ui/core'; +import { lightTheme } from '@backstage/theme'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { msw, renderInTestApp } from '@backstage/test-utils'; + +describe('ExampleComponent', () => { + const server = setupServer(); + // Enable sane handlers for network requests + msw.setupDefaultHandlers(server); + + // setup mock response + beforeEach(() => { + server.use( + rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), + ); + }); + + it('should render', async () => { + const rendered = await renderInTestApp( + + + , + ); + expect(rendered.getByText('Welcome to config-schema!')).toBeInTheDocument(); + }); +}); diff --git a/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx b/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx new file mode 100644 index 0000000000..f3d5c86be3 --- /dev/null +++ b/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx @@ -0,0 +1,53 @@ +/* + * 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 { Typography, Grid } from '@material-ui/core'; +import { + InfoCard, + Header, + Page, + Content, + ContentHeader, + HeaderLabel, + SupportButton, +} from '@backstage/core'; +import { ExampleFetchComponent } from '../ExampleFetchComponent'; + +export const ExampleComponent = () => ( + +
+ + +
+ + + A description of your plugin goes here. + + + + + + All content should be wrapped in a card like this. + + + + + + + + +
+); diff --git a/plugins/config-schema/src/components/ExampleComponent/index.ts b/plugins/config-schema/src/components/ExampleComponent/index.ts new file mode 100644 index 0000000000..337d24d5c5 --- /dev/null +++ b/plugins/config-schema/src/components/ExampleComponent/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { ExampleComponent } from './ExampleComponent'; diff --git a/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx b/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx new file mode 100644 index 0000000000..6a5c0351d6 --- /dev/null +++ b/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx @@ -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 React from 'react'; +import { render } from '@testing-library/react'; +import { ExampleFetchComponent } from './ExampleFetchComponent'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { msw } from '@backstage/test-utils'; + +describe('ExampleFetchComponent', () => { + const server = setupServer(); + // Enable sane handlers for network requests + msw.setupDefaultHandlers(server); + + // setup mock response + beforeEach(() => { + server.use( + rest.get('https://randomuser.me/*', (_, res, ctx) => + res(ctx.status(200), ctx.delay(2000), ctx.json({})), + ), + ); + }); + it('should render', async () => { + const rendered = render(); + expect(await rendered.findByTestId('progress')).toBeInTheDocument(); + }); +}); diff --git a/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx b/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx new file mode 100644 index 0000000000..1390c8950f --- /dev/null +++ b/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx @@ -0,0 +1,105 @@ +/* + * 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 { makeStyles } from '@material-ui/core/styles'; +import { Table, TableColumn, Progress } from '@backstage/core'; +import Alert from '@material-ui/lab/Alert'; +import { useAsync } from 'react-use'; + +const useStyles = makeStyles({ + avatar: { + height: 32, + width: 32, + borderRadius: '50%', + }, +}); + +type User = { + gender: string; // "male" + name: { + title: string; // "Mr", + first: string; // "Duane", + last: string; // "Reed" + }; + location: object; // {street: {number: 5060, name: "Hickory Creek Dr"}, city: "Albany", state: "New South Wales",…} + email: string; // "duane.reed@example.com" + login: object; // {uuid: "4b785022-9a23-4ab9-8a23-cb3fb43969a9", username: "blackdog796", password: "patch",…} + dob: object; // {date: "1983-06-22T12:30:23.016Z", age: 37} + registered: object; // {date: "2006-06-13T18:48:28.037Z", age: 14} + phone: string; // "07-2154-5651" + cell: string; // "0405-592-879" + id: { + name: string; // "TFN", + value: string; // "796260432" + }; + picture: { medium: string }; // {medium: "https://randomuser.me/api/portraits/men/95.jpg",…} + nat: string; // "AU" +}; + +type DenseTableProps = { + users: User[]; +}; + +export const DenseTable = ({ users }: DenseTableProps) => { + const classes = useStyles(); + + const columns: TableColumn[] = [ + { title: 'Avatar', field: 'avatar' }, + { title: 'Name', field: 'name' }, + { title: 'Email', field: 'email' }, + { title: 'Nationality', field: 'nationality' }, + ]; + + const data = users.map(user => { + return { + avatar: ( + {user.name.first} + ), + name: `${user.name.first} ${user.name.last}`, + email: user.email, + nationality: user.nat, + }; + }); + + return ( +
+ ); +}; + +export const ExampleFetchComponent = () => { + const { value, loading, error } = useAsync(async (): Promise => { + const response = await fetch('https://randomuser.me/api/?results=20'); + const data = await response.json(); + return data.results; + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + return ; +}; diff --git a/plugins/config-schema/src/components/ExampleFetchComponent/index.ts b/plugins/config-schema/src/components/ExampleFetchComponent/index.ts new file mode 100644 index 0000000000..e7c8364039 --- /dev/null +++ b/plugins/config-schema/src/components/ExampleFetchComponent/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { ExampleFetchComponent } from './ExampleFetchComponent'; diff --git a/plugins/config-schema/src/index.ts b/plugins/config-schema/src/index.ts new file mode 100644 index 0000000000..0254d6a36c --- /dev/null +++ b/plugins/config-schema/src/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { configSchemaPlugin, ConfigSchemaPage } from './plugin'; diff --git a/plugins/config-schema/src/plugin.test.ts b/plugins/config-schema/src/plugin.test.ts new file mode 100644 index 0000000000..0f71d800d4 --- /dev/null +++ b/plugins/config-schema/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 { configSchemaPlugin } from './plugin'; + +describe('config-schema', () => { + it('should export plugin', () => { + expect(configSchemaPlugin).toBeDefined(); + }); +}); diff --git a/plugins/config-schema/src/plugin.ts b/plugins/config-schema/src/plugin.ts new file mode 100644 index 0000000000..8850e02639 --- /dev/null +++ b/plugins/config-schema/src/plugin.ts @@ -0,0 +1,33 @@ +/* + * 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 { createPlugin, createRoutableExtension } from '@backstage/core'; + +import { rootRouteRef } from './routes'; + +export const configSchemaPlugin = createPlugin({ + id: 'config-schema', + routes: { + root: rootRouteRef, + }, +}); + +export const ConfigSchemaPage = configSchemaPlugin.provide( + createRoutableExtension({ + component: () => + import('./components/ExampleComponent').then(m => m.ExampleComponent), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/config-schema/src/routes.ts b/plugins/config-schema/src/routes.ts new file mode 100644 index 0000000000..8128e1f49f --- /dev/null +++ b/plugins/config-schema/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: 'config-schema', +}); diff --git a/plugins/config-schema/src/setupTests.ts b/plugins/config-schema/src/setupTests.ts new file mode 100644 index 0000000000..0cec5b395d --- /dev/null +++ b/plugins/config-schema/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'; From e56c49aa2eb99f5006a9df324776fc61a328ac0f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 5 Apr 2021 15:58:48 +0200 Subject: [PATCH 071/395] config-schema: added initial API types Signed-off-by: Patrik Oldsberg --- plugins/config-schema/package.json | 1 + plugins/config-schema/src/api/index.ts | 18 ++++++++++++++++ plugins/config-schema/src/api/types.ts | 30 ++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 plugins/config-schema/src/api/index.ts create mode 100644 plugins/config-schema/src/api/types.ts diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 291a7078be..85c2ada157 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -20,6 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { + "@backstage/config": "^0.1.4", "@backstage/core": "^0.7.3", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", diff --git a/plugins/config-schema/src/api/index.ts b/plugins/config-schema/src/api/index.ts new file mode 100644 index 0000000000..ed5e40c268 --- /dev/null +++ b/plugins/config-schema/src/api/index.ts @@ -0,0 +1,18 @@ +/* + * 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 { configSchemaApiRef } from './types'; +export type { ConfigSchemaApi } from './types'; diff --git a/plugins/config-schema/src/api/types.ts b/plugins/config-schema/src/api/types.ts new file mode 100644 index 0000000000..310817e68f --- /dev/null +++ b/plugins/config-schema/src/api/types.ts @@ -0,0 +1,30 @@ +/* + * 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 { JsonObject } from '@backstage/config'; +import { createApiRef, Observable } from '@backstage/core'; + +export interface ConfigSchemaResult { + schema?: JsonObject; +} + +export interface ConfigSchemaApi { + schema$(): Observable; +} + +export const configSchemaApiRef = createApiRef({ + id: 'plugin.config-schema', +}); From 02f5bc8d01323314e6a07380410d13982b179e63 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 5 Apr 2021 16:04:03 +0200 Subject: [PATCH 072/395] config-schema: basic schema render page Signed-off-by: Patrik Oldsberg --- .../ConfigSchemaPage/ConfigSchemaPage.tsx | 62 +++++++++++ .../index.ts | 2 +- .../ExampleComponent.test.tsx | 44 -------- .../ExampleComponent/ExampleComponent.tsx | 53 --------- .../ExampleFetchComponent.test.tsx | 40 ------- .../ExampleFetchComponent.tsx | 105 ------------------ .../components/ExampleFetchComponent/index.ts | 16 --- plugins/config-schema/src/plugin.ts | 2 +- 8 files changed, 64 insertions(+), 260 deletions(-) create mode 100644 plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx rename plugins/config-schema/src/components/{ExampleComponent => ConfigSchemaPage}/index.ts (91%) delete mode 100644 plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx delete mode 100644 plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx delete mode 100644 plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx delete mode 100644 plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx delete mode 100644 plugins/config-schema/src/components/ExampleFetchComponent/index.ts diff --git a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx new file mode 100644 index 0000000000..67cff7a596 --- /dev/null +++ b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx @@ -0,0 +1,62 @@ +/* + * 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, { useMemo } from 'react'; +import { Grid } from '@material-ui/core'; +import { + Header, + Page, + Content, + ContentHeader, + HeaderLabel, + SupportButton, + CodeSnippet, + useApi, +} from '@backstage/core'; +import { useObservable } from 'react-use'; +import { configSchemaApiRef } from '../../api'; + +export const ConfigSchemaPage = () => { + const configSchemaApi = useApi(configSchemaApiRef); + const schema = useObservable( + useMemo(() => configSchemaApi.schema$(), [configSchemaApi]), + ); + + return ( + +
+ + +
+ + + A description of your plugin goes here. + + + + {schema ? ( + + ) : ( + 'No schema available' + )} + + + +
+ ); +}; diff --git a/plugins/config-schema/src/components/ExampleComponent/index.ts b/plugins/config-schema/src/components/ConfigSchemaPage/index.ts similarity index 91% rename from plugins/config-schema/src/components/ExampleComponent/index.ts rename to plugins/config-schema/src/components/ConfigSchemaPage/index.ts index 337d24d5c5..e373ae71c6 100644 --- a/plugins/config-schema/src/components/ExampleComponent/index.ts +++ b/plugins/config-schema/src/components/ConfigSchemaPage/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { ExampleComponent } from './ExampleComponent'; +export { ConfigSchemaPage } from './ConfigSchemaPage'; diff --git a/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx b/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx deleted file mode 100644 index 030495be33..0000000000 --- a/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.test.tsx +++ /dev/null @@ -1,44 +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 React from 'react'; -import { ExampleComponent } from './ExampleComponent'; -import { ThemeProvider } from '@material-ui/core'; -import { lightTheme } from '@backstage/theme'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { msw, renderInTestApp } from '@backstage/test-utils'; - -describe('ExampleComponent', () => { - const server = setupServer(); - // Enable sane handlers for network requests - msw.setupDefaultHandlers(server); - - // setup mock response - beforeEach(() => { - server.use( - rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), - ); - }); - - it('should render', async () => { - const rendered = await renderInTestApp( - - - , - ); - expect(rendered.getByText('Welcome to config-schema!')).toBeInTheDocument(); - }); -}); diff --git a/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx b/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx deleted file mode 100644 index f3d5c86be3..0000000000 --- a/plugins/config-schema/src/components/ExampleComponent/ExampleComponent.tsx +++ /dev/null @@ -1,53 +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 React from 'react'; -import { Typography, Grid } from '@material-ui/core'; -import { - InfoCard, - Header, - Page, - Content, - ContentHeader, - HeaderLabel, - SupportButton, -} from '@backstage/core'; -import { ExampleFetchComponent } from '../ExampleFetchComponent'; - -export const ExampleComponent = () => ( - -
- - -
- - - A description of your plugin goes here. - - - - - - All content should be wrapped in a card like this. - - - - - - - - -
-); diff --git a/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx b/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx deleted file mode 100644 index 6a5c0351d6..0000000000 --- a/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx +++ /dev/null @@ -1,40 +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 React from 'react'; -import { render } from '@testing-library/react'; -import { ExampleFetchComponent } from './ExampleFetchComponent'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { msw } from '@backstage/test-utils'; - -describe('ExampleFetchComponent', () => { - const server = setupServer(); - // Enable sane handlers for network requests - msw.setupDefaultHandlers(server); - - // setup mock response - beforeEach(() => { - server.use( - rest.get('https://randomuser.me/*', (_, res, ctx) => - res(ctx.status(200), ctx.delay(2000), ctx.json({})), - ), - ); - }); - it('should render', async () => { - const rendered = render(); - expect(await rendered.findByTestId('progress')).toBeInTheDocument(); - }); -}); diff --git a/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx b/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx deleted file mode 100644 index 1390c8950f..0000000000 --- a/plugins/config-schema/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx +++ /dev/null @@ -1,105 +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 React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import { Table, TableColumn, Progress } from '@backstage/core'; -import Alert from '@material-ui/lab/Alert'; -import { useAsync } from 'react-use'; - -const useStyles = makeStyles({ - avatar: { - height: 32, - width: 32, - borderRadius: '50%', - }, -}); - -type User = { - gender: string; // "male" - name: { - title: string; // "Mr", - first: string; // "Duane", - last: string; // "Reed" - }; - location: object; // {street: {number: 5060, name: "Hickory Creek Dr"}, city: "Albany", state: "New South Wales",…} - email: string; // "duane.reed@example.com" - login: object; // {uuid: "4b785022-9a23-4ab9-8a23-cb3fb43969a9", username: "blackdog796", password: "patch",…} - dob: object; // {date: "1983-06-22T12:30:23.016Z", age: 37} - registered: object; // {date: "2006-06-13T18:48:28.037Z", age: 14} - phone: string; // "07-2154-5651" - cell: string; // "0405-592-879" - id: { - name: string; // "TFN", - value: string; // "796260432" - }; - picture: { medium: string }; // {medium: "https://randomuser.me/api/portraits/men/95.jpg",…} - nat: string; // "AU" -}; - -type DenseTableProps = { - users: User[]; -}; - -export const DenseTable = ({ users }: DenseTableProps) => { - const classes = useStyles(); - - const columns: TableColumn[] = [ - { title: 'Avatar', field: 'avatar' }, - { title: 'Name', field: 'name' }, - { title: 'Email', field: 'email' }, - { title: 'Nationality', field: 'nationality' }, - ]; - - const data = users.map(user => { - return { - avatar: ( - {user.name.first} - ), - name: `${user.name.first} ${user.name.last}`, - email: user.email, - nationality: user.nat, - }; - }); - - return ( -
- ); -}; - -export const ExampleFetchComponent = () => { - const { value, loading, error } = useAsync(async (): Promise => { - const response = await fetch('https://randomuser.me/api/?results=20'); - const data = await response.json(); - return data.results; - }, []); - - if (loading) { - return ; - } else if (error) { - return {error.message}; - } - - return ; -}; diff --git a/plugins/config-schema/src/components/ExampleFetchComponent/index.ts b/plugins/config-schema/src/components/ExampleFetchComponent/index.ts deleted file mode 100644 index e7c8364039..0000000000 --- a/plugins/config-schema/src/components/ExampleFetchComponent/index.ts +++ /dev/null @@ -1,16 +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. - */ -export { ExampleFetchComponent } from './ExampleFetchComponent'; diff --git a/plugins/config-schema/src/plugin.ts b/plugins/config-schema/src/plugin.ts index 8850e02639..841f9f7f04 100644 --- a/plugins/config-schema/src/plugin.ts +++ b/plugins/config-schema/src/plugin.ts @@ -27,7 +27,7 @@ export const configSchemaPlugin = createPlugin({ export const ConfigSchemaPage = configSchemaPlugin.provide( createRoutableExtension({ component: () => - import('./components/ExampleComponent').then(m => m.ExampleComponent), + import('./components/ConfigSchemaPage').then(m => m.ConfigSchemaPage), mountPoint: rootRouteRef, }), ); From e75795ac0fe2d644fb306e4d01b31b9c438ed4dc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 5 Apr 2021 16:09:48 +0200 Subject: [PATCH 073/395] config-schema: dev setup with example schema Signed-off-by: Patrik Oldsberg --- plugins/config-schema/dev/example-schema.json | 1659 +++++++++++++++++ plugins/config-schema/dev/index.tsx | 19 +- plugins/config-schema/package.json | 1 + 3 files changed, 1677 insertions(+), 2 deletions(-) create mode 100644 plugins/config-schema/dev/example-schema.json diff --git a/plugins/config-schema/dev/example-schema.json b/plugins/config-schema/dev/example-schema.json new file mode 100644 index 0000000000..d1e577ff6f --- /dev/null +++ b/plugins/config-schema/dev/example-schema.json @@ -0,0 +1,1659 @@ +{ + "$schema": "https://backstage.io/schema/config-v1", + "title": "Application Configuration Schema", + "type": "object", + "required": ["app", "backend", "costInsights", "sentry", "techdocs"], + "properties": { + "app": { + "type": "object", + "required": ["baseUrl"], + "description": "Generic frontend configuration.", + "properties": { + "baseUrl": { + "type": "string", + "visibility": "frontend", + "description": "The public absolute root URL that the frontend." + }, + "title": { + "type": "string", + "visibility": "frontend", + "description": "The title of the app." + }, + "googleAnalyticsTrackingId": { + "type": "string", + "visibility": "frontend", + "description": "Tracking ID for Google Analytics", + "examples": ["UA-000000-0"] + }, + "listen": { + "type": "object", + "description": "Listening configuration for local development", + "properties": { + "host": { + "type": "string", + "visibility": "frontend", + "description": "The host that the frontend should be bound to. Only used for local development." + }, + "port": { + "type": "number", + "visibility": "frontend", + "description": "The port that the frontend should be bound to. Only used for local development." + } + } + }, + "support": { + "description": "Information about support of this Backstage instance and how to contact the integrator team.", + "type": "object", + "required": ["items", "url"], + "properties": { + "url": { + "description": "The primary support url.", + "visibility": "frontend", + "type": "string" + }, + "items": { + "description": "A list of categorized support item groupings.", + "type": "array", + "items": { + "type": "object", + "required": ["links", "title"], + "properties": { + "title": { + "description": "The title of the support item grouping.", + "visibility": "frontend", + "type": "string" + }, + "icon": { + "description": "An optional icon for the support item grouping.", + "visibility": "frontend", + "type": "string" + }, + "links": { + "description": "A list of support links for the Backstage instance.", + "type": "array", + "items": { + "type": "object", + "required": ["url"], + "properties": { + "url": { + "visibility": "frontend", + "type": "string" + }, + "title": { + "visibility": "frontend", + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "lighthouse": { + "type": "object", + "properties": { + "baseUrl": { + "type": "string", + "visibility": "frontend" + } + } + }, + "auth": { + "type": "object", + "description": "Configuration that provides information on available authentication providers configured for app", + "properties": { + "providers": { + "type": "object", + "description": "The available auth-provider options and attributes", + "additionalProperties": { + "type": "object", + "visibility": "frontend" + }, + "properties": { + "google": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "github": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "gitlab": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "saml": { + "type": "object", + "required": ["entryPoint", "issuer"], + "properties": { + "entryPoint": { + "type": "string" + }, + "logoutUrl": { + "type": "string" + }, + "issuer": { + "type": "string" + }, + "cert": { + "type": "string" + }, + "privateKey": { + "type": "string" + }, + "decryptionPvk": { + "type": "string" + }, + "signatureAlgorithm": { + "enum": ["sha256", "sha512"], + "type": "string" + }, + "digestAlgorithm": { + "type": "string" + } + } + }, + "okta": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "oauth2": { + "type": "object", + "additionalProperties": { + "type": "object", + "required": [ + "authorizationUrl", + "clientId", + "clientSecret", + "tokenUrl" + ], + "properties": { + "clientId": { + "type": "string" + }, + "clientSecret": { + "type": "string" + }, + "authorizationUrl": { + "type": "string" + }, + "tokenUrl": { + "type": "string" + }, + "scope": { + "type": "string" + } + } + } + }, + "oidc": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "auth0": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "microsoft": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "onelogin": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "awsalb": { + "type": "object", + "required": ["region"], + "properties": { + "issuer": { + "type": "string" + }, + "region": { + "type": "string" + } + } + } + } + }, + "environment": { + "description": "The 'environment' attribute added as an optional parameter to have configurable environment value for `auth.providers`.\ndefault value: 'development'\noptional values: 'development' | 'production'", + "visibility": "frontend", + "type": "string" + }, + "session": { + "type": "object", + "properties": { + "secret": { + "description": "The secret attribute of session object.", + "visibility": "secret", + "type": "string" + } + } + } + } + }, + "backend": { + "type": "object", + "required": ["baseUrl", "database", "listen"], + "description": "Generic backend configuration.", + "properties": { + "baseUrl": { + "type": "string", + "description": "The public absolute root URL that the backend is reachable at.", + "visibility": "frontend" + }, + "listen": { + "description": "Address that the backend should listen to.", + "anyOf": [ + { + "type": "object", + "properties": { + "address": { + "description": "Address of the interface that the backend should bind to.", + "type": "string" + }, + "port": { + "description": "Port that the backend should listen to.", + "type": ["string", "number"] + } + } + }, + { + "type": "string" + } + ] + }, + "https": { + "description": "HTTPS configuration for the backend. If omitted the backend will serve HTTP.\n\nSetting this to `true` will cause self-signed certificates to be generated, which\ncan be useful for local development or other non-production scenarios.", + "anyOf": [ + { + "type": "object", + "properties": { + "certificate": { + "description": "Certificate configuration", + "type": "object", + "required": ["cert", "key"], + "properties": { + "cert": { + "description": "PEM encoded certificate. Use $file to load in a file", + "type": "string" + }, + "key": { + "description": "PEM encoded certificate key. Use $file to load in a file.", + "visibility": "secret", + "type": "string" + } + } + } + } + }, + { + "enum": [true], + "type": "boolean" + } + ] + }, + "database": { + "description": "Database connection configuration, select database type using the `client` field", + "anyOf": [ + { + "type": "object", + "properties": { + "client": { + "type": "string", + "enum": ["sqlite3"] + }, + "connection": { + "type": "string" + } + }, + "required": ["client", "connection"] + }, + { + "type": "object", + "properties": { + "client": { + "type": "string", + "enum": ["pg"] + }, + "connection": { + "description": "PostgreSQL connection string or knex configuration object.", + "anyOf": [ + { + "type": "object", + "properties": {}, + "additionalProperties": true + }, + { + "type": "string" + } + ] + } + }, + "required": ["client", "connection"] + } + ] + }, + "cors": { + "type": "object", + "properties": { + "origin": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "methods": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "allowedHeaders": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "exposedHeaders": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "credentials": { + "type": "boolean" + }, + "maxAge": { + "type": "number" + }, + "preflightContinue": { + "type": "boolean" + }, + "optionsSuccessStatus": { + "type": "number" + } + } + }, + "reading": { + "description": "Configuration related to URL reading, used for example for reading catalog info\nfiles, scaffolder templates, and techdocs content.", + "type": "object", + "properties": { + "allow": { + "description": "A list of targets to allow outgoing requests to. Users will be able to make\nrequests on behalf of the backend to the targets that are allowed by this list.", + "type": "array", + "items": { + "type": "object", + "required": ["host"], + "properties": { + "host": { + "description": "A host to allow outgoing requests to, being either a full host or\na subdomain wildcard pattern with a leading `*`. For example `example.com`\nand `*.example.com` are valid values, `prod.*.example.com` is not.\nThe host may also contain a port, for example `example.com:8080`.", + "type": "string" + } + } + } + } + } + }, + "csp": { + "description": "Content Security Policy options.\n\nThe keys are the plain policy ID, e.g. \"upgrade-insecure-requests\". The\nvalues are on the format that the helmet library expects them, as an\narray of strings. There is also the special value false, which means to\nremove the default value that Backstage puts in place for that policy.", + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "enum": [false], + "type": "boolean" + } + ] + } + } + } + }, + "organization": { + "description": "Configuration that provides information about the organization that the app is for.", + "type": "object", + "properties": { + "name": { + "description": "The name of the organization that the app belongs to.", + "visibility": "frontend", + "type": "string" + } + } + }, + "homepage": { + "type": "object", + "properties": { + "clocks": { + "type": "array", + "items": { + "type": "object", + "required": ["label", "timezone"], + "properties": { + "label": { + "visibility": "frontend", + "type": "string" + }, + "timezone": { + "visibility": "frontend", + "type": "string" + } + } + } + } + } + }, + "integrations": { + "description": "Configuration for integrations towards various external repository provider systems", + "type": "object", + "properties": { + "azure": { + "description": "Integration configuration for Azure", + "type": "array", + "items": { + "type": "object", + "required": ["host"], + "properties": { + "host": { + "description": "The hostname of the given Azure instance", + "visibility": "frontend", + "type": "string" + }, + "token": { + "description": "Token used to authenticate requests.", + "visibility": "secret", + "type": "string" + } + } + } + }, + "bitbucket": { + "description": "Integration configuration for Bitbucket", + "type": "array", + "items": { + "type": "object", + "required": ["host"], + "properties": { + "host": { + "description": "The hostname of the given Bitbucket instance", + "visibility": "frontend", + "type": "string" + }, + "token": { + "description": "Token used to authenticate requests.", + "visibility": "secret", + "type": "string" + }, + "apiBaseUrl": { + "description": "The base url for the Bitbucket API, for example https://api.bitbucket.org/2.0", + "visibility": "frontend", + "type": "string" + }, + "username": { + "description": "The username to use for authenticated requests.", + "visibility": "secret", + "type": "string" + }, + "appPassword": { + "description": "Bitbucket app password used to authenticate requests.", + "visibility": "secret", + "type": "string" + } + } + } + }, + "github": { + "description": "Integration configuration for GitHub", + "type": "array", + "items": { + "type": "object", + "required": ["host"], + "properties": { + "host": { + "description": "The hostname of the given GitHub instance", + "visibility": "frontend", + "type": "string" + }, + "token": { + "description": "Token used to authenticate requests.", + "visibility": "secret", + "type": "string" + }, + "apiBaseUrl": { + "description": "The base url for the GitHub API, for example https://api.github.com", + "visibility": "frontend", + "type": "string" + }, + "rawBaseUrl": { + "description": "The base url for GitHub raw resources, for example https://raw.githubusercontent.com", + "visibility": "frontend", + "type": "string" + }, + "apps": { + "description": "GitHub Apps configuration", + "visibility": "backend", + "type": "array", + "items": { + "type": "object", + "required": [ + "appId", + "clientId", + "clientSecret", + "privateKey", + "webhookSecret" + ], + "properties": { + "appId": { + "description": "The numeric GitHub App ID", + "type": "number" + }, + "privateKey": { + "description": "The private key to use for auth against the app", + "visibility": "secret", + "type": "string" + }, + "webhookSecret": { + "description": "The secret used for webhooks", + "visibility": "secret", + "type": "string" + }, + "clientId": { + "description": "The client ID to use", + "type": "string" + }, + "clientSecret": { + "description": "The client secret to use", + "visibility": "secret", + "type": "string" + } + } + } + } + } + } + }, + "gitlab": { + "description": "Integration configuration for GitLab", + "type": "array", + "items": { + "type": "object", + "required": ["host"], + "properties": { + "host": { + "description": "The host of the target that this matches on, e.g. \"gitlab.com\".", + "visibility": "frontend", + "type": "string" + }, + "apiBaseUrl": { + "description": "The base URL of the API of this provider, e.g.\n\"https://gitlab.com/api/v4\", with no trailing slash.\n\nMay be omitted specifically for public GitLab; then it will be deduced.", + "visibility": "frontend", + "type": "string" + }, + "token": { + "description": "The authorization token to use for requests to this provider.\n\nIf no token is specified, anonymous access is used.", + "visibility": "secret", + "type": "string" + }, + "baseUrl": { + "description": "The baseUrl of this provider, e.g. \"https://gitlab.com\", which is\npassed into the GitLab client.\n\nIf no baseUrl is provided, it will default to https://${host}.", + "visibility": "frontend", + "type": "string" + } + } + } + } + } + }, + "catalog": { + "description": "Configuration options for the catalog plugin.", + "type": "object", + "properties": { + "rules": { + "description": "Rules to apply to all catalog entities, from any location.\n\nAn undefined list of matchers means match all, an empty list of\nmatchers means match none.\n\nThis is commonly used to put in what amounts to a whitelist of kinds\nthat regular users of Backstage are permitted to register locations\nfor. This can be used to stop them from registering yaml files\ndescribing for example a Group entity called \"admin\" that they make\nthemselves members of, or similar.", + "type": "array", + "items": { + "type": "object", + "required": ["allow"], + "properties": { + "allow": { + "description": "Allow entities of these particular kinds.\n\nE.g. [\"Component\", \"API\", \"Template\", \"Location\"]", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "readonly": { + "description": "Readonly defines whether the catalog allows writes after startup.\n\nSetting 'readonly=false' allows users to register their own components.\nThis is the default value.\n\nSetting 'readonly=true' configures catalog to only allow reads. This can\nbe used in combination with static locations to only serve operator\nprovided locations. Effectively this removes the ability to register new\ncomponents to a running backstage instance.", + "type": "boolean" + }, + "locations": { + "description": "A set of static locations that the catalog shall always keep itself\nup-to-date with. This is commonly used for large, permanent integrations\nthat are defined by the Backstage operators at an organization, rather\nthan individual things that users register dynamically.\n\nThese have (optional) rules of their own. These override what the global\nrules above specify. This way, you can prevent everybody from register\ne.g. User and Group entities, except for one or a few static locations\nthat have those two kinds explicitly allowed.\n\nFor example:\n\n```yaml\nrules:\n - allow: [Component, API, Template, Location]\nlocations:\n - type: url\n target: https://github.com/org/repo/blob/master/users.yaml\n rules:\n - allow: [User, Group]\n - type: url\n target: https://github.com/org/repo/blob/master/systems.yaml\n rules:\n - allow: [System]\n```", + "type": "array", + "items": { + "type": "object", + "required": ["target", "type"], + "properties": { + "type": { + "description": "The type of location, e.g. \"url\".", + "type": "string" + }, + "target": { + "description": "The target URL of the location, e.g.\n\"https://github.com/org/repo/blob/master/users.yaml\".", + "type": "string" + }, + "rules": { + "description": "Optional extra rules that apply to this particular location.\n\nThese override the global rules above.", + "type": "array", + "items": { + "type": "object", + "required": ["allow"], + "properties": { + "allow": { + "description": "Allow entities of these particular kinds.\n\nE.g. [\"Group\", \"User\"]", + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "processors": { + "description": "List of processor-specific options and attributes", + "type": "object", + "properties": { + "githubOrg": { + "description": "GithubOrgReaderProcessor configuration", + "type": "object", + "required": ["providers"], + "properties": { + "providers": { + "description": "The configuration parameters for each single GitHub org provider.", + "type": "array", + "items": { + "type": "object", + "required": ["target"], + "properties": { + "target": { + "description": "The prefix of the target that this matches on, e.g.\n\"https://github.com\", with no trailing slash.", + "type": "string" + }, + "apiBaseUrl": { + "description": "The base URL of the API of this provider, e.g.\n\"https://api.github.com\", with no trailing slash.\n\nMay be omitted specifically for GitHub; then it will be deduced.", + "type": "string" + }, + "token": { + "description": "The authorization token to use for requests to this provider.\n\nIf no token is specified, anonymous access is used.", + "visibility": "secret", + "type": "string" + } + } + } + } + } + }, + "ldapOrg": { + "description": "LdapOrgReaderProcessor configuration", + "type": "object", + "required": ["providers"], + "properties": { + "providers": { + "description": "The configuration parameters for each single LDAP provider.", + "type": "array", + "items": { + "type": "object", + "required": ["groups", "target", "users"], + "properties": { + "target": { + "description": "The prefix of the target that this matches on, e.g.\n\"ldaps://ds.example.net\", with no trailing slash.", + "type": "string" + }, + "bind": { + "description": "The settings to use for the bind command. If none are specified,\nthe bind command is not issued.", + "type": "object", + "required": ["dn", "secret"], + "properties": { + "dn": { + "description": "The DN of the user to auth as.\n\nE.g. \"uid=ldap-robot,ou=robots,ou=example,dc=example,dc=net\"", + "type": "string" + }, + "secret": { + "description": "The secret of the user to auth as (its password).", + "visibility": "secret", + "type": "string" + } + } + }, + "users": { + "description": "The settings that govern the reading and interpretation of users.", + "type": "object", + "required": ["dn", "options"], + "properties": { + "dn": { + "description": "The DN under which users are stored.\n\nE.g. \"ou=people,ou=example,dc=example,dc=net\"", + "type": "string" + }, + "options": { + "description": "The search options to use. The default is scope \"one\" and\nattributes \"*\" and \"+\".\n\nIt is common to want to specify a filter, to narrow down the set\nof matching items.", + "type": "object", + "properties": { + "scope": { + "enum": ["base", "one", "sub"], + "type": "string" + }, + "filter": { + "type": "string" + }, + "attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "paged": { + "anyOf": [ + { + "type": "object", + "properties": { + "pageSize": { + "type": "number" + }, + "pagePause": { + "type": "boolean" + } + } + }, + { + "type": "boolean" + } + ] + } + } + }, + "set": { + "description": "JSON paths (on a.b.c form) and hard coded values to set on those\npaths.\n\nThis can be useful for example if you want to hard code a\nnamespace or similar on the generated entities.", + "type": "object" + }, + "map": { + "description": "Mappings from well known entity fields, to LDAP attribute names", + "type": "object", + "properties": { + "rdn": { + "description": "The name of the attribute that holds the relative\ndistinguished name of each entry. Defaults to \"uid\".", + "type": "string" + }, + "name": { + "description": "The name of the attribute that shall be used for the value of\nthe metadata.name field of the entity. Defaults to \"uid\".", + "type": "string" + }, + "description": { + "description": "The name of the attribute that shall be used for the value of\nthe metadata.description field of the entity.", + "type": "string" + }, + "displayName": { + "description": "The name of the attribute that shall be used for the value of\nthe spec.profile.displayName field of the entity. Defaults to\n\"cn\".", + "type": "string" + }, + "email": { + "description": "The name of the attribute that shall be used for the value of\nthe spec.profile.email field of the entity. Defaults to\n\"mail\".", + "type": "string" + }, + "picture": { + "description": "The name of the attribute that shall be used for the value of\nthe spec.profile.picture field of the entity.", + "type": "string" + }, + "memberOf": { + "description": "The name of the attribute that shall be used for the values of\nthe spec.memberOf field of the entity. Defaults to \"memberOf\".", + "type": "string" + } + } + } + } + }, + "groups": { + "description": "The settings that govern the reading and interpretation of groups.", + "type": "object", + "required": ["dn", "options"], + "properties": { + "dn": { + "description": "The DN under which groups are stored.\n\nE.g. \"ou=people,ou=example,dc=example,dc=net\"", + "type": "string" + }, + "options": { + "description": "The search options to use. The default is scope \"one\" and\nattributes \"*\" and \"+\".\n\nIt is common to want to specify a filter, to narrow down the set\nof matching items.", + "type": "object", + "properties": { + "scope": { + "enum": ["base", "one", "sub"], + "type": "string" + }, + "filter": { + "type": "string" + }, + "attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "paged": { + "anyOf": [ + { + "type": "object", + "properties": { + "pageSize": { + "type": "number" + }, + "pagePause": { + "type": "boolean" + } + } + }, + { + "type": "boolean" + } + ] + } + } + }, + "set": { + "description": "JSON paths (on a.b.c form) and hard coded values to set on those\npaths.\n\nThis can be useful for example if you want to hard code a\nnamespace or similar on the generated entities.", + "type": "object" + }, + "map": { + "description": "Mappings from well known entity fields, to LDAP attribute names", + "type": "object", + "properties": { + "rdn": { + "description": "The name of the attribute that holds the relative\ndistinguished name of each entry. Defaults to \"cn\".", + "type": "string" + }, + "name": { + "description": "The name of the attribute that shall be used for the value of\nthe metadata.name field of the entity. Defaults to \"cn\".", + "type": "string" + }, + "description": { + "description": "The name of the attribute that shall be used for the value of\nthe metadata.description field of the entity. Defaults to\n\"description\".", + "type": "string" + }, + "type": { + "description": "The name of the attribute that shall be used for the value of\nthe spec.type field of the entity. Defaults to \"groupType\".", + "type": "string" + }, + "displayName": { + "description": "The name of the attribute that shall be used for the value of\nthe spec.profile.displayName field of the entity. Defaults to\n\"cn\".", + "type": "string" + }, + "email": { + "description": "The name of the attribute that shall be used for the value of\nthe spec.profile.email field of the entity.", + "type": "string" + }, + "picture": { + "description": "The name of the attribute that shall be used for the value of\nthe spec.profile.picture field of the entity.", + "type": "string" + }, + "memberOf": { + "description": "The name of the attribute that shall be used for the values of\nthe spec.parent field of the entity. Defaults to \"memberOf\".", + "type": "string" + }, + "members": { + "description": "The name of the attribute that shall be used for the values of\nthe spec.children field of the entity. Defaults to \"member\".", + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "awsOrganization": { + "description": "AwsOrganizationCloudAccountProcessor configuration", + "type": "object", + "required": ["provider"], + "properties": { + "provider": { + "type": "object", + "properties": { + "roleArn": { + "description": "The role to be assumed by this processor", + "type": "string" + } + } + } + } + }, + "microsoftGraphOrg": { + "description": "MicrosoftGraphOrgReaderProcessor configuration", + "type": "object", + "required": ["providers"], + "properties": { + "providers": { + "description": "The configuration parameters for each single Microsoft Graph provider.", + "type": "array", + "items": { + "type": "object", + "required": [ + "clientId", + "clientSecret", + "target", + "tenantId" + ], + "properties": { + "target": { + "description": "The prefix of the target that this matches on, e.g.\n\"https://graph.microsoft.com/v1.0\", with no trailing slash.", + "type": "string" + }, + "authority": { + "description": "The auth authority used.\n\nDefault value \"https://login.microsoftonline.com\"", + "type": "string" + }, + "tenantId": { + "description": "The tenant whose org data we are interested in.", + "type": "string" + }, + "clientId": { + "description": "The OAuth client ID to use for authenticating requests.", + "type": "string" + }, + "clientSecret": { + "description": "The OAuth client secret to use for authenticating requests.", + "visibility": "secret", + "type": "string" + }, + "userFilter": { + "description": "The filter to apply to extract users.\n\nE.g. \"accountEnabled eq true and userType eq 'member'\"", + "type": "string" + }, + "groupFilter": { + "description": "The filter to apply to extract groups.\n\nE.g. \"securityEnabled eq false and mailEnabled eq true\"", + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "costInsights": { + "type": "object", + "required": ["engineerCost", "products"], + "properties": { + "engineerCost": { + "visibility": "frontend", + "type": "number" + }, + "products": { + "type": "object", + "additionalProperties": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "visibility": "frontend", + "type": "string" + }, + "icon": { + "visibility": "frontend", + "enum": [ + "compute", + "data", + "database", + "ml", + "search", + "storage" + ], + "type": "string" + } + } + } + }, + "metrics": { + "type": "object", + "additionalProperties": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "visibility": "frontend", + "type": "string" + }, + "default": { + "visibility": "frontend", + "type": "boolean" + } + } + } + } + } + }, + "fossa": { + "type": "object", + "required": ["organizationId"], + "properties": { + "organizationId": { + "description": "The organization id in fossa.", + "visibility": "frontend", + "type": "string" + } + } + }, + "kubernetes": { + "type": "object", + "required": ["clusterLocatorMethods", "serviceLocatorMethod"], + "properties": { + "serviceLocatorMethod": { + "type": "object", + "required": ["type"], + "visibility": "frontend", + "properties": { + "type": { + "type": "string", + "enum": ["multiTenant"], + "visibility": "frontend" + } + } + }, + "clusterLocatorMethods": { + "type": "array", + "visibility": "frontend" + }, + "customResources": { + "type": "array", + "visibility": "frontend" + } + } + }, + "kafka": { + "type": "object", + "required": ["clientId", "clusters"], + "properties": { + "clientId": { + "description": "Client ID used to Backstage uses to identify when connecting to the Kafka cluster.", + "type": "string" + }, + "clusters": { + "type": "array", + "items": { + "type": "object", + "required": ["brokers", "name"], + "properties": { + "name": { + "type": "string" + }, + "brokers": { + "description": "List of brokers in the Kafka cluster to connect to.", + "type": "array", + "items": { + "type": "string" + } + }, + "ssl": { + "description": "Optional SSL connection parameters to connect to the cluster. Passed directly to Node tls.connect.\nSee https://nodejs.org/dist/latest-v8.x/docs/api/tls.html#tls_tls_createsecurecontext_options", + "anyOf": [ + { + "type": "object", + "properties": { + "ca": { + "type": "array", + "items": { + "type": "string" + } + }, + "key": { + "visibility": "secret", + "type": "string" + }, + "cert": { + "type": "string" + } + }, + "required": ["ca", "cert", "key"] + }, + { + "type": "boolean" + } + ] + }, + "sasl": { + "description": "Optional SASL connection parameters.", + "type": "object", + "required": ["mechanism", "password", "username"], + "properties": { + "mechanism": { + "enum": ["plain", "scram-sha-256", "scram-sha-512"], + "type": "string" + }, + "username": { + "type": "string" + }, + "password": { + "visibility": "secret", + "type": "string" + } + } + } + } + } + } + } + }, + "rollbar": { + "description": "Configuration options for the rollbar-backend plugin", + "type": "object", + "required": ["accountToken"], + "properties": { + "accountToken": { + "description": "The autentication token for accessing the Rollbar API", + "type": "string" + }, + "organization": { + "description": "The Rollbar organization name. This can be omitted by using the `rollbar.com/project-slug` annotation.", + "visibility": "frontend", + "type": "string" + } + } + }, + "proxy": { + "description": "A list of forwarding-proxies. Each key is a route to match,\nbelow the prefix that the proxy plugin is mounted on. It must\nstart with a '/'.", + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "properties": { + "target": { + "description": "Target of the proxy. Url string to be parsed with the url module.", + "type": "string" + }, + "headers": { + "description": "Object with extra headers to be added to target requests.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "changeOrigin": { + "description": "Changes the origin of the host header to the target URL. Default: true.", + "type": "boolean" + }, + "pathRewrite": { + "description": "Rewrite target's url path. Object-keys will be used as RegExp to match paths.\nIf pathRewrite is not specified, it is set to a single rewrite that removes the entire prefix and route.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "allowedMethods": { + "description": "Limit the forwarded HTTP methods, for example allowedMethods: ['GET'] to enforce read-only access.", + "type": "array", + "items": { + "type": "string" + } + }, + "allowedHeaders": { + "description": "Limit the forwarded HTTP methods. By default, only the headers that are considered safe for CORS\nand headers that are set by the proxy will be forwarded.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["target"] + }, + { + "type": "string" + } + ] + } + }, + "scaffolder": { + "description": "Configuration options for the scaffolder plugin", + "type": "object", + "properties": { + "github": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "properties": { + "visiblity": { + "description": "The visibility to set on created repositories.", + "enum": ["internal", "private", "public"], + "type": "string" + } + } + }, + "gitlab": { + "type": "object", + "required": ["api"], + "properties": { + "api": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "visiblity": { + "description": "The visibility to set on created repositories.", + "enum": ["internal", "private", "public"], + "type": "string" + } + } + }, + "azure": { + "type": "object", + "required": ["api", "baseUrl"], + "properties": { + "baseUrl": { + "type": "string" + }, + "api": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "bitbucket": { + "type": "object", + "required": ["api"], + "properties": { + "api": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "visiblity": { + "description": "The visibility to set on created repositories.", + "enum": ["private", "public"], + "type": "string" + } + } + } + } + }, + "sonarQube": { + "description": "Optional configurations for the SonarQube plugin", + "type": "object", + "required": ["baseUrl"], + "properties": { + "baseUrl": { + "description": "The base url of the sonarqube installation. Defaults to https://sonarcloud.io.", + "visibility": "frontend", + "type": "string" + } + } + }, + "sentry": { + "description": "Configuration options for the sentry plugin", + "type": "object", + "required": ["organization"], + "properties": { + "organization": { + "description": "The 'organization' attribute", + "visibility": "frontend", + "type": "string" + } + } + }, + "techdocs": { + "description": "Configuration options for the techdocs-backend plugin", + "type": "object", + "required": ["builder"], + "properties": { + "builder": { + "description": "Documentation building process depends on the builder attr", + "visibility": "frontend", + "enum": ["external", "local"], + "type": "string" + }, + "generators": { + "description": "Techdocs generator information", + "type": "object", + "required": ["techdocs"], + "properties": { + "techdocs": { + "enum": ["docker", "local"], + "type": "string" + } + } + }, + "publisher": { + "description": "Techdocs publisher information", + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["local"] + } + }, + "required": ["type"] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["awsS3"] + }, + "awsS3": { + "description": "Required when 'type' is set to awsS3", + "type": "object", + "required": ["bucketName"], + "properties": { + "credentials": { + "description": "(Optional) Credentials used to access a storage bucket.\nIf not set, environment variables or aws config file will be used to authenticate.", + "visibility": "secret", + "type": "object", + "required": ["accessKeyId", "secretAccessKey"], + "properties": { + "accessKeyId": { + "description": "User access key id", + "visibility": "secret", + "type": "string" + }, + "secretAccessKey": { + "description": "User secret access key", + "visibility": "secret", + "type": "string" + }, + "roleArn": { + "description": "ARN of role to be assumed", + "visibility": "backend", + "type": "string" + } + } + }, + "bucketName": { + "description": "(Required) Cloud Storage Bucket Name", + "visibility": "backend", + "type": "string" + }, + "region": { + "description": "(Optional) AWS Region.\nIf not set, AWS_REGION environment variable or aws config file will be used.", + "visibility": "secret", + "type": "string" + }, + "endpoint": { + "description": "(Optional) AWS Endpoint.\nThe endpoint URI to send requests to. The default endpoint is built from the configured region.", + "visibility": "secret", + "type": "string" + } + } + } + }, + "required": ["type"] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["openStackSwift"] + }, + "openStackSwift": { + "description": "Required when 'type' is set to openStackSwift", + "type": "object", + "required": [ + "authUrl", + "containerName", + "credentials", + "domainId", + "domainName", + "keystoneAuthVersion", + "region" + ], + "properties": { + "credentials": { + "description": "(Required) Credentials used to access a storage bucket.", + "visibility": "secret", + "type": "object", + "required": ["password", "username"], + "properties": { + "username": { + "description": "(Required) Root user name", + "visibility": "secret", + "type": "string" + }, + "password": { + "description": "(Required) Root user password", + "visibility": "secret", + "type": "string" + } + } + }, + "containerName": { + "description": "(Required) Cloud Storage Container Name", + "visibility": "backend", + "type": "string" + }, + "authUrl": { + "description": "(Required) Auth url sometimes OpenStack uses different port check your OpenStack apis.", + "visibility": "backend", + "type": "string" + }, + "keystoneAuthVersion": { + "description": "(Optional) Auth version\nIf not set, 'v2.0' will be used.", + "visibility": "backend", + "type": "string" + }, + "domainId": { + "description": "(Required) Domain Id", + "visibility": "backend", + "type": "string" + }, + "domainName": { + "description": "(Required) Domain Name", + "visibility": "backend", + "type": "string" + }, + "region": { + "description": "(Required) Region", + "visibility": "backend", + "type": "string" + } + } + } + }, + "required": ["type"] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["azureBlobStorage"] + }, + "azureBlobStorage": { + "description": "Required when 'type' is set to azureBlobStorage", + "type": "object", + "required": ["containerName", "credentials"], + "properties": { + "credentials": { + "description": "(Required) Credentials used to access a storage container.", + "visibility": "secret", + "type": "object", + "required": ["accountName"], + "properties": { + "accountName": { + "description": "Account access name", + "visibility": "secret", + "type": "string" + }, + "accountKey": { + "description": "(Optional) Account secret primary key\nIf not set, environment variables will be used to authenticate.", + "visibility": "secret", + "type": "string" + } + } + }, + "containerName": { + "description": "(Required) Cloud Storage Container Name", + "visibility": "backend", + "type": "string" + } + } + } + }, + "required": ["type"] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["googleGcs"] + }, + "googleGcs": { + "description": "Required when 'type' is set to googleGcs", + "type": "object", + "required": ["bucketName"], + "properties": { + "bucketName": { + "description": "(Required) Cloud Storage Bucket Name", + "visibility": "backend", + "type": "string" + }, + "credentials": { + "description": "(Optional) API key used to write to a storage bucket.\nIf not set, environment variables will be used to authenticate.", + "visibility": "secret", + "type": "string" + } + } + } + }, + "required": ["type"] + } + ] + }, + "requestUrl": { + "visibility": "frontend", + "type": "string" + }, + "storageUrl": { + "type": "string" + } + } + }, + "travisci": { + "description": "Configuration options for the travisci plugin", + "type": "object", + "properties": { + "baseUrl": { + "description": "The 'baseUrl' attribute. It should point to the address of the travis portal.\nIf not provided, frontend plugin will use 'https://travis-ci.com/'", + "visibility": "frontend", + "type": "string" + } + } + } + }, + "description": "This is the schema describing the structure of the app-config.yaml configuration file." +} diff --git a/plugins/config-schema/dev/index.tsx b/plugins/config-schema/dev/index.tsx index 1a20bfc62a..03aa8e172a 100644 --- a/plugins/config-schema/dev/index.tsx +++ b/plugins/config-schema/dev/index.tsx @@ -13,12 +13,27 @@ * 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 { configSchemaPlugin, ConfigSchemaPage } from '../src/plugin'; +import React from 'react'; +import Observable from 'zen-observable'; +import { configSchemaApiRef } from '../src/api'; +import { ConfigSchemaResult } from '../src/api/types'; +import { ConfigSchemaPage, configSchemaPlugin } from '../src/plugin'; +import exampleSchema from './example-schema.json'; createDevApp() .registerPlugin(configSchemaPlugin) + .registerApi({ + api: configSchemaApiRef, + deps: {}, + factory: () => ({ + schema$: () => + new Observable(sub => + sub.next({ schema: exampleSchema }), + ), + }), + }) .addPage({ element: , title: 'Root Page', diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 85c2ada157..3ca14a8162 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -26,6 +26,7 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", + "zen-observable": "^0.8.15", "react": "^16.13.1", "react-dom": "^16.13.1", "react-use": "^15.3.3" From 079b3e025bbe0f98d5aa109825ef7768c3a974d8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 5 Apr 2021 18:27:59 +0200 Subject: [PATCH 074/395] config-schema: switch schema type and separate out SchemaViewer Signed-off-by: Patrik Oldsberg --- plugins/config-schema/dev/index.tsx | 3 ++- plugins/config-schema/package.json | 1 + plugins/config-schema/src/api/types.ts | 4 +-- .../ConfigSchemaPage/ConfigSchemaPage.tsx | 13 +++------- .../components/SchemaViewer/SchemaViewer.tsx | 26 +++++++++++++++++++ .../src/components/SchemaViewer/index.ts | 17 ++++++++++++ 6 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx create mode 100644 plugins/config-schema/src/components/SchemaViewer/index.ts diff --git a/plugins/config-schema/dev/index.tsx b/plugins/config-schema/dev/index.tsx index 03aa8e172a..412f0d283e 100644 --- a/plugins/config-schema/dev/index.tsx +++ b/plugins/config-schema/dev/index.tsx @@ -15,6 +15,7 @@ */ import { createDevApp } from '@backstage/dev-utils'; +import { Schema } from 'jsonschema'; import React from 'react'; import Observable from 'zen-observable'; import { configSchemaApiRef } from '../src/api'; @@ -30,7 +31,7 @@ createDevApp() factory: () => ({ schema$: () => new Observable(sub => - sub.next({ schema: exampleSchema }), + sub.next({ schema: (exampleSchema as unknown) as Schema }), ), }), }) diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 3ca14a8162..67dcfa5976 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -26,6 +26,7 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", + "jsonschema": "^1.2.6", "zen-observable": "^0.8.15", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/plugins/config-schema/src/api/types.ts b/plugins/config-schema/src/api/types.ts index 310817e68f..025ef76f0c 100644 --- a/plugins/config-schema/src/api/types.ts +++ b/plugins/config-schema/src/api/types.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { JsonObject } from '@backstage/config'; import { createApiRef, Observable } from '@backstage/core'; +import { Schema } from 'jsonschema'; export interface ConfigSchemaResult { - schema?: JsonObject; + schema?: Schema; } export interface ConfigSchemaApi { diff --git a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx index 67cff7a596..8811a3e0bd 100644 --- a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx +++ b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx @@ -22,17 +22,17 @@ import { ContentHeader, HeaderLabel, SupportButton, - CodeSnippet, useApi, } from '@backstage/core'; import { useObservable } from 'react-use'; import { configSchemaApiRef } from '../../api'; +import { SchemaViewer } from '../SchemaViewer'; export const ConfigSchemaPage = () => { const configSchemaApi = useApi(configSchemaApiRef); const schema = useObservable( useMemo(() => configSchemaApi.schema$(), [configSchemaApi]), - ); + )?.schema; return ( @@ -46,14 +46,7 @@ export const ConfigSchemaPage = () => { - {schema ? ( - - ) : ( - 'No schema available' - )} + {schema ? : 'No schema available'} diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx new file mode 100644 index 0000000000..3f4c11fc31 --- /dev/null +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.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 { CodeSnippet } from '@backstage/core'; +import { Schema } from 'jsonschema'; + +export interface SchemaViewerProps { + schema: Schema; +} + +export const SchemaViewer = ({ schema }: SchemaViewerProps) => { + return ; +}; diff --git a/plugins/config-schema/src/components/SchemaViewer/index.ts b/plugins/config-schema/src/components/SchemaViewer/index.ts new file mode 100644 index 0000000000..4852c4e21d --- /dev/null +++ b/plugins/config-schema/src/components/SchemaViewer/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 { SchemaViewer } from './SchemaViewer'; From 5c63bc44abbd7f0aa7ed439393f29d7cd67b5196 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 5 Apr 2021 21:16:20 +0200 Subject: [PATCH 075/395] config-schema: initial propper schema viewer Signed-off-by: Patrik Oldsberg --- .../components/SchemaViewer/SchemaViewer.tsx | 261 +++++++++++++++++- 1 file changed, 259 insertions(+), 2 deletions(-) diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index 3f4c11fc31..db29e5acbe 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -14,13 +14,270 @@ * limitations under the License. */ import React from 'react'; -import { CodeSnippet } from '@backstage/core'; import { Schema } from 'jsonschema'; +import { + Box, + Chip, + Divider, + Paper, + Table, + TableBody, + TableCell, + TableRow, + Typography, +} from '@material-ui/core'; +import { JsonValue } from '@backstage/config'; + +interface SchemaViewProps { + path: string; + depth: number; + schema: Schema; +} + +export interface MetadataViewRowProps { + label: string; + text?: string; + data?: JsonValue; +} + +export function MetadataViewRow({ label, text, data }: MetadataViewRowProps) { + if (text === undefined && data === undefined) { + return null; + } + return ( + + + + {label} + + + + + {data ? JSON.stringify(data) : text} + + + + ); +} + +export function MetadataView({ schema }: { schema: Schema }) { + return ( + +
+ + + + + + + + + + + + + + + + + + +
+ + ); +} + +export function ScalarView({ schema }: SchemaViewProps) { + return ( + <> + {schema.description && ( + + {schema.description} + + )} + + + ); +} + +function isRequired(name: string, required?: boolean | string[]) { + if (required === true) { + return true; + } + if (Array.isArray(required)) { + return required.includes(name); + } + return false; +} + +function titleVariant(depth: number) { + if (depth <= 1) { + return 'h2'; + } else if (depth === 2) { + return 'h3'; + } else if (depth === 3) { + return 'h4'; + } else if (depth === 4) { + return 'h5'; + } + return 'h6'; +} + +export function VisibilityView({ schema }: { schema: Schema }) { + const { visibility } = schema as { visibility?: string }; + if (visibility === 'frontend') { + return ( + } + /> + ); + } else if (visibility === 'secret') { + return ( + } + /> + ); + } + return null; +} + +export function ArrayView({ path, depth, schema }: SchemaViewProps) { + const itemDepth = depth + 1; + const itemPath = path ? `${path}[]` : '[]'; + const itemSchema = schema.items; + + return ( + <> + + {schema.description && ( + + {schema.description} + + )} + + + Items + + + + + + {itemPath} + + + {itemSchema && ( + + )} + + + + ); +} + +export function ObjectView({ path, depth, schema }: SchemaViewProps) { + const properties = Object.entries(schema.properties ?? {}); + return ( + <> + {depth > 0 && ( + + {schema.description && ( + + {schema.description} + + )} + + + )} + {properties.length > 0 && ( + <> + {depth > 0 && Properties} + {properties.map(([name, propSchema], index) => { + const propDepth = depth + 1; + const propPath = path ? `${path}.${name}` : name; + + return ( + + + + + + {propPath} + + {isRequired(name, schema.required) && ( + + + required + + + )} + + + + + + ); + })} + + )} + + ); +} + +export function SchemaView(props: SchemaViewProps) { + // TODO(Rugvip): allOf, anyOf, oneOf + switch (props.schema.type) { + case 'array': + return ; + case 'object': + case undefined: + return ; + default: + return ; + } +} export interface SchemaViewerProps { schema: Schema; } export const SchemaViewer = ({ schema }: SchemaViewerProps) => { - return ; + return ; }; From 888f0b52bd50b25654cccf7921f6d07e4c9d2435 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 6 Apr 2021 01:22:13 +0200 Subject: [PATCH 076/395] config-schema: refactor out PropertyTitle and make required a chip Signed-off-by: Patrik Oldsberg --- .../components/SchemaViewer/SchemaViewer.tsx | 96 +++++++++++++++---- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index db29e5acbe..5db522b9a8 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -19,6 +19,7 @@ import { Box, Chip, Divider, + makeStyles, Paper, Table, TableBody, @@ -46,8 +47,8 @@ export function MetadataViewRow({ label, text, data }: MetadataViewRowProps) { } return ( - - + + {label} @@ -167,6 +168,68 @@ export function VisibilityView({ schema }: { schema: Schema }) { return null; } +const usePropertyTitleStyles = makeStyles(theme => ({ + title: { + marginBottom: 0, + }, + chip: { + marginLeft: theme.spacing(1), + marginRight: 0, + marginBottom: 0, + }, +})); + +export function PropertyTitle({ + path, + depth, + schema, + required, +}: { + path: string; + depth: number; + schema?: Schema; + required?: boolean; +}) { + const classes = usePropertyTitleStyles(); + const chips = new Array(); + const chipProps = { size: 'small' as const, classes: { root: classes.chip } }; + + if (required) { + chips.push( + , + ); + } + + const visibility = (schema as { visibility?: string })?.visibility; + if (visibility === 'frontend') { + chips.push( + , + ); + } else if (visibility === 'secret') { + chips.push( + , + ); + } + + return ( + + + {path} + + {chips.length > 0 && } + {chips} + + ); +} + export function ArrayView({ path, depth, schema }: SchemaViewProps) { const itemDepth = depth + 1; const itemPath = path ? `${path}[]` : '[]'; @@ -186,11 +249,11 @@ export function ArrayView({ path, depth, schema }: SchemaViewProps) { - - - {itemPath} - - + {itemSchema && ( - - - {propPath} - - {isRequired(name, schema.required) && ( - - - required - - - )} - - + Date: Tue, 6 Apr 2021 01:59:48 +0200 Subject: [PATCH 077/395] config-schema: refactor PropertyTitle into ChildView and add MatchView Signed-off-by: Patrik Oldsberg --- .../components/SchemaViewer/SchemaViewer.tsx | 160 +++++++++++------- 1 file changed, 97 insertions(+), 63 deletions(-) diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index 5db522b9a8..b49651ae7b 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -168,7 +168,7 @@ export function VisibilityView({ schema }: { schema: Schema }) { return null; } -const usePropertyTitleStyles = makeStyles(theme => ({ +const useChildViewStyles = makeStyles(theme => ({ title: { marginBottom: 0, }, @@ -179,18 +179,20 @@ const usePropertyTitleStyles = makeStyles(theme => ({ }, })); -export function PropertyTitle({ +export function ChildView({ path, depth, schema, required, + lastChild, }: { path: string; depth: number; schema?: Schema; required?: boolean; + lastChild?: boolean; }) { - const classes = usePropertyTitleStyles(); + const classes = useChildViewStyles(); const chips = new Array(); const chipProps = { size: 'small' as const, classes: { root: classes.chip } }; @@ -212,20 +214,28 @@ export function PropertyTitle({ } return ( - - - {path} - - {chips.length > 0 && } - {chips} + + + + + + {path} + + {chips.length > 0 && } + {chips} + + {schema && ( + + )} + ); } @@ -246,23 +256,12 @@ export function ArrayView({ path, depth, schema }: SchemaViewProps) { Items - - - - - {itemSchema && ( - - )} - - + ); } @@ -284,42 +283,77 @@ export function ObjectView({ path, depth, schema }: SchemaViewProps) { {properties.length > 0 && ( <> {depth > 0 && Properties} - {properties.map(([name, propSchema], index) => { - const propDepth = depth + 1; - const propPath = path ? `${path}.${name}` : name; - - return ( - - - - - - - - ); - })} + {properties.map(([name, propSchema], index) => ( + + ))} )} ); } +export function MatchView({ + path, + depth, + schema, + label, +}: { + path: string; + depth: number; + schema: Schema[]; + label: string; +}) { + return ( + <> + {label} + {schema.map((optionSchema, index) => ( + + ))} + + ); +} + export function SchemaView(props: SchemaViewProps) { - // TODO(Rugvip): allOf, anyOf, oneOf - switch (props.schema.type) { + const { schema } = props; + if (schema.anyOf) { + return ( + + ); + } + if (schema.oneOf) { + return ( + + ); + } + if (schema.allOf) { + return ( + + ); + } + switch (schema.type) { case 'array': return ; case 'object': From d1fb5135d463a5c320028d613fea416d496f5e65 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 6 Apr 2021 02:09:36 +0200 Subject: [PATCH 078/395] config-schema: add support for additional and pattern props and items Signed-off-by: Patrik Oldsberg --- .../components/SchemaViewer/SchemaViewer.tsx | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index b49651ae7b..5e6c1ec94c 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -68,6 +68,12 @@ export function MetadataView({ schema }: { schema: Schema }) { + {schema.additionalProperties === true && ( + + )} + {schema.additionalItems === true && ( + + )} + {schema.additionalItems && schema.additionalItems !== true && ( + <> + Additional Items + + + )} ); } export function ObjectView({ path, depth, schema }: SchemaViewProps) { const properties = Object.entries(schema.properties ?? {}); + const patternProperties = Object.entries(schema.patternProperties ?? {}); + return ( <> {depth > 0 && ( @@ -294,6 +313,33 @@ export function ObjectView({ path, depth, schema }: SchemaViewProps) { ))} )} + {patternProperties.length > 0 && ( + <> + {depth > 0 && ( + Pattern Properties + )} + {patternProperties.map(([name, propSchema], index) => ( + ` : name} + depth={depth + 1} + schema={propSchema} + lastChild={index === patternProperties.length - 1} + required={isRequired(name, schema.required)} + /> + ))} + + )} + {schema.additionalProperties && schema.additionalProperties !== true && ( + <> + Additional Properties + + + )} ); } From 2bfc5466f70725d9d1d15d22a7ff9c078fd46a02 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 6 Apr 2021 10:38:24 +0200 Subject: [PATCH 079/395] config-schema: add tree view schema browser Signed-off-by: Patrik Oldsberg --- .../ConfigSchemaPage/ConfigSchemaPage.tsx | 11 +- .../components/SchemaViewer/SchemaViewer.tsx | 187 +++++++++++++++++- 2 files changed, 188 insertions(+), 10 deletions(-) diff --git a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx index 8811a3e0bd..689ac4379f 100644 --- a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx +++ b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ import React, { useMemo } from 'react'; -import { Grid } from '@material-ui/core'; import { Header, Page, @@ -36,19 +35,15 @@ export const ConfigSchemaPage = () => { return ( -
+
- + A description of your plugin goes here. - - - {schema ? : 'No schema available'} - - + {schema ? : 'No schema available'} ); diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index 5e6c1ec94c..874fea03a9 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; +import React, { ReactNode, useMemo } from 'react'; import { Schema } from 'jsonschema'; import { Box, Chip, + createStyles, Divider, + fade, makeStyles, Paper, Table, @@ -26,8 +28,12 @@ import { TableCell, TableRow, Typography, + withStyles, } from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import ChevronRightIcon from '@material-ui/icons/ChevronRight'; import { JsonValue } from '@backstage/config'; +import { TreeItem, TreeItemProps, TreeView } from '@material-ui/lab'; interface SchemaViewProps { path: string; @@ -414,6 +420,183 @@ export interface SchemaViewerProps { schema: Schema; } +const StyledTreeItem = withStyles(theme => + createStyles({ + label: { + userSelect: 'none', + }, + group: { + marginLeft: 7, + paddingLeft: theme.spacing(1), + borderLeft: `1px solid ${fade(theme.palette.text.primary, 0.15)}`, + }, + }), +)((props: TreeItemProps) => ); + +export function createSchemaBrowserItems( + expanded: string[], + schema: Schema, + path: string = '', + depth: number = 0, +): ReactNode { + let matchArr; + if (schema.anyOf) { + matchArr = schema.anyOf; + } else if (schema.oneOf) { + matchArr = schema.oneOf; + } else if (schema.allOf) { + matchArr = schema.allOf; + } + if (matchArr) { + return matchArr.map((childSchema, index) => { + const childPath = `${path}/${index}`; + if (depth > 0) expanded.push(childPath); + return ( + `} + > + {createSchemaBrowserItems( + expanded, + childSchema, + childPath, + depth + 1, + )} + + ); + }); + } + + switch (schema.type) { + case 'array': { + const childPath = `${path}[]`; + if (depth > 0) expanded.push(childPath); + return ( + + {schema.items && + createSchemaBrowserItems( + expanded, + schema.items as Schema, + childPath, + depth + 1, + )} + + ); + } + case 'object': + case undefined: { + const children = []; + + if (schema.properties) { + children.push( + ...Object.entries(schema.properties).map(([name, childSchema]) => { + const childPath = path ? `${path}/${name}` : name; + if (depth > 0) expanded.push(childPath); + return ( + + {createSchemaBrowserItems( + expanded, + childSchema, + childPath, + depth + 1, + )} + + ); + }), + ); + } + + if (schema.patternProperties) { + children.push( + ...Object.entries(schema.patternProperties).map( + ([name, childSchema]) => { + const childPath = `${path}/<${name}>`; + if (depth > 0) expanded.push(childPath); + return ( + `} + > + {createSchemaBrowserItems( + expanded, + childSchema, + childPath, + depth + 1, + )} + + ); + }, + ), + ); + } + + if (schema.additionalProperties && schema.additionalProperties !== true) { + const childPath = `${path}/*`; + if (depth > 0) expanded.push(childPath); + children.push( + + {createSchemaBrowserItems( + expanded, + schema.additionalProperties, + childPath, + depth + 1, + )} + , + ); + } + + return <>{children}; + } + + default: + return null; + } +} + +export function SchemaBrowser({ schema }: { schema: Schema }) { + const data = useMemo(() => { + const expanded = new Array(); + + const items = createSchemaBrowserItems(expanded, schema); + + return { items, expanded }; + }, [schema]); + + return ( + } + defaultExpandIcon={} + > + {data.items} + + ); +} + export const SchemaViewer = ({ schema }: SchemaViewerProps) => { - return ; + return ( + + + + + + + + + + + + + + ); }; From a8d31306396f941034580714549d0024f1c72a94 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 9 Apr 2021 17:49:11 +0200 Subject: [PATCH 080/395] config-schema: scrolling schema view Signed-off-by: Patrik Oldsberg --- .../components/SchemaViewer/SchemaViewer.tsx | 80 ++++++++++++++++--- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index 874fea03a9..6b8eab67e7 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -13,7 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { ReactNode, useMemo } from 'react'; +import React, { + createContext, + ReactNode, + useContext, + useEffect, + useMemo, + useRef, +} from 'react'; import { Schema } from 'jsonschema'; import { Box, @@ -35,6 +42,26 @@ import ChevronRightIcon from '@material-ui/icons/ChevronRight'; import { JsonValue } from '@backstage/config'; import { TreeItem, TreeItemProps, TreeView } from '@material-ui/lab'; +class ScrollForwarder { + private readonly listeners = new Map void>(); + + setScrollListener(id: string, listener: () => void): () => void { + this.listeners.set(id, listener); + + return () => { + if (this.listeners.get(id) === listener) { + this.listeners.delete(id); + } + }; + } + + scrollTo(id: string) { + this.listeners.get(id)?.(); + } +} + +const ScrollContext = createContext(undefined); + interface SchemaViewProps { path: string; depth: number; @@ -205,6 +232,15 @@ export function ChildView({ lastChild?: boolean; }) { const classes = useChildViewStyles(); + const titleRef = useRef(null); + const scroll = useContext(ScrollContext); + + useEffect(() => { + return scroll?.setScrollListener(path, () => { + titleRef.current?.scrollIntoView({ behavior: 'smooth' }); + }); + }, [scroll, path]); + const chips = new Array(); const chipProps = { size: 'small' as const, classes: { root: classes.chip } }; @@ -236,6 +272,7 @@ export function ChildView({ alignItems="center" > @@ -449,7 +486,7 @@ export function createSchemaBrowserItems( } if (matchArr) { return matchArr.map((childSchema, index) => { - const childPath = `${path}/${index}`; + const childPath = `${path}.${index}`; if (depth > 0) expanded.push(childPath); return ( { - const childPath = path ? `${path}/${name}` : name; + const childPath = path ? `${path}.${name}` : name; if (depth > 0) expanded.push(childPath); return ( @@ -511,7 +548,7 @@ export function createSchemaBrowserItems( children.push( ...Object.entries(schema.patternProperties).map( ([name, childSchema]) => { - const childPath = `${path}/<${name}>`; + const childPath = `${path}.<${name}>`; if (depth > 0) expanded.push(childPath); return ( 0) expanded.push(childPath); children.push( @@ -556,6 +593,8 @@ export function createSchemaBrowserItems( } export function SchemaBrowser({ schema }: { schema: Schema }) { + const scroll = useContext(ScrollContext); + const expandedRef = useRef([]); const data = useMemo(() => { const expanded = new Array(); @@ -564,12 +603,27 @@ export function SchemaBrowser({ schema }: { schema: Schema }) { return { items, expanded }; }, [schema]); + if (!scroll) { + throw new Error('No scroll handler available'); + } + + const handleToggle = (_event: unknown, expanded: string[]) => { + expandedRef.current = expanded; + }; + + const handleSelect = (_event: unknown, nodeId: string) => { + if (expandedRef.current.includes(nodeId)) { + scroll.scrollTo(nodeId); + } + }; + return ( } defaultExpandIcon={} + onNodeToggle={handleToggle} + onNodeSelect={handleSelect} > {data.items} @@ -588,13 +642,15 @@ export const SchemaViewer = ({ schema }: SchemaViewerProps) => { maxHeight="100%" > - - - + + + + - - - + + + + From 2c27b4f4fd264dd597326b6e6ec62678e53c4fb9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Apr 2021 12:02:41 +0200 Subject: [PATCH 081/395] config-schema: clean up main page Signed-off-by: Patrik Oldsberg --- .../ConfigSchemaPage/ConfigSchemaPage.tsx | 18 ++---------------- .../components/SchemaViewer/SchemaViewer.tsx | 4 ++-- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx index 689ac4379f..add916e997 100644 --- a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx +++ b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx @@ -14,15 +14,7 @@ * limitations under the License. */ import React, { useMemo } from 'react'; -import { - Header, - Page, - Content, - ContentHeader, - HeaderLabel, - SupportButton, - useApi, -} from '@backstage/core'; +import { Header, Page, Content, useApi } from '@backstage/core'; import { useObservable } from 'react-use'; import { configSchemaApiRef } from '../../api'; import { SchemaViewer } from '../SchemaViewer'; @@ -35,14 +27,8 @@ export const ConfigSchemaPage = () => { return ( -
- - -
+
- - A description of your plugin goes here. - {schema ? : 'No schema available'} diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index 6b8eab67e7..e34755a39e 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -403,7 +403,7 @@ export function MatchView({ {label} {schema.map((optionSchema, index) => ( { - const childPath = `${path}.${index}`; + const childPath = `${path}/${index + 1}`; if (depth > 0) expanded.push(childPath); return ( Date: Sat, 10 Apr 2021 12:25:49 +0200 Subject: [PATCH 082/395] config-schema: split out schema view components Signed-off-by: Patrik Oldsberg --- .../src/components/SchemaView/ArrayView.tsx | 59 +++ .../src/components/SchemaView/ChildView.tsx | 123 +++++ .../src/components/SchemaView/MatchView.tsx | 45 ++ .../components/SchemaView/MetadataView.tsx | 110 +++++ .../src/components/SchemaView/ObjectView.tsx | 92 ++++ .../src/components/SchemaView/ScalarView.tsx | 33 ++ .../src/components/SchemaView/SchemaView.tsx | 62 +++ .../src/components/SchemaView/index.ts | 17 + .../src/components/SchemaView/types.ts | 23 + .../components/SchemaViewer/SchemaViewer.tsx | 450 +----------------- .../SchemaViewer/ScrollTargetsContext.tsx | 52 ++ 11 files changed, 626 insertions(+), 440 deletions(-) create mode 100644 plugins/config-schema/src/components/SchemaView/ArrayView.tsx create mode 100644 plugins/config-schema/src/components/SchemaView/ChildView.tsx create mode 100644 plugins/config-schema/src/components/SchemaView/MatchView.tsx create mode 100644 plugins/config-schema/src/components/SchemaView/MetadataView.tsx create mode 100644 plugins/config-schema/src/components/SchemaView/ObjectView.tsx create mode 100644 plugins/config-schema/src/components/SchemaView/ScalarView.tsx create mode 100644 plugins/config-schema/src/components/SchemaView/SchemaView.tsx create mode 100644 plugins/config-schema/src/components/SchemaView/index.ts create mode 100644 plugins/config-schema/src/components/SchemaView/types.ts create mode 100644 plugins/config-schema/src/components/SchemaViewer/ScrollTargetsContext.tsx diff --git a/plugins/config-schema/src/components/SchemaView/ArrayView.tsx b/plugins/config-schema/src/components/SchemaView/ArrayView.tsx new file mode 100644 index 0000000000..15f4dd8800 --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/ArrayView.tsx @@ -0,0 +1,59 @@ +/* + * 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 { Box, Typography } from '@material-ui/core'; +import { Schema } from 'jsonschema'; +import React from 'react'; +import { ChildView } from './ChildView'; +import { MetadataView } from './MetadataView'; +import { SchemaViewProps } from './types'; + +export function ArrayView({ path, depth, schema }: SchemaViewProps) { + const itemDepth = depth + 1; + const itemPath = path ? `${path}[]` : '[]'; + const itemSchema = schema.items; + + return ( + <> + + {schema.description && ( + + {schema.description} + + )} + + + Items + + {schema.additionalItems && schema.additionalItems !== true && ( + <> + Additional Items + + + )} + + ); +} diff --git a/plugins/config-schema/src/components/SchemaView/ChildView.tsx b/plugins/config-schema/src/components/SchemaView/ChildView.tsx new file mode 100644 index 0000000000..bc4f3bb63e --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/ChildView.tsx @@ -0,0 +1,123 @@ +/* + * 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 { JsonValue } from '@backstage/config'; +import { Box, Chip, Divider, makeStyles, Typography } from '@material-ui/core'; +import { Schema } from 'jsonschema'; +import React, { useEffect, useRef } from 'react'; +import { useScrollTargets } from '../SchemaViewer/ScrollContext'; +import { SchemaView } from './SchemaView'; + +export interface MetadataViewRowProps { + label: string; + text?: string; + data?: JsonValue; +} + +function titleVariant(depth: number) { + if (depth <= 1) { + return 'h2'; + } else if (depth === 2) { + return 'h3'; + } else if (depth === 3) { + return 'h4'; + } else if (depth === 4) { + return 'h5'; + } + return 'h6'; +} + +const useChildViewStyles = makeStyles(theme => ({ + title: { + marginBottom: 0, + }, + chip: { + marginLeft: theme.spacing(1), + marginRight: 0, + marginBottom: 0, + }, +})); + +export function ChildView({ + path, + depth, + schema, + required, + lastChild, +}: { + path: string; + depth: number; + schema?: Schema; + required?: boolean; + lastChild?: boolean; +}) { + const classes = useChildViewStyles(); + const titleRef = useRef(null); + const scroll = useScrollTargets(); + + useEffect(() => { + return scroll?.setScrollListener(path, () => { + titleRef.current?.scrollIntoView({ behavior: 'smooth' }); + }); + }, [scroll, path]); + + const chips = new Array(); + const chipProps = { size: 'small' as const, classes: { root: classes.chip } }; + + if (required) { + chips.push( + , + ); + } + + const visibility = (schema as { visibility?: string })?.visibility; + if (visibility === 'frontend') { + chips.push( + , + ); + } else if (visibility === 'secret') { + chips.push( + , + ); + } + + return ( + + + + + + {path} + + {chips.length > 0 && } + {chips} + + {schema && ( + + )} + + + ); +} diff --git a/plugins/config-schema/src/components/SchemaView/MatchView.tsx b/plugins/config-schema/src/components/SchemaView/MatchView.tsx new file mode 100644 index 0000000000..df0dbba8ef --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/MatchView.tsx @@ -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 { Typography } from '@material-ui/core'; +import { Schema } from 'jsonschema'; +import React from 'react'; +import { ChildView } from './ChildView'; + +export function MatchView({ + path, + depth, + schema, + label, +}: { + path: string; + depth: number; + schema: Schema[]; + label: string; +}) { + return ( + <> + {label} + {schema.map((optionSchema, index) => ( + + ))} + + ); +} diff --git a/plugins/config-schema/src/components/SchemaView/MetadataView.tsx b/plugins/config-schema/src/components/SchemaView/MetadataView.tsx new file mode 100644 index 0000000000..41d48149ad --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/MetadataView.tsx @@ -0,0 +1,110 @@ +/* + * 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 { JsonValue } from '@backstage/config'; +import { + Paper, + Table, + TableBody, + TableCell, + TableRow, + Typography, +} from '@material-ui/core'; +import { Schema } from 'jsonschema'; +import React from 'react'; + +export interface MetadataViewRowProps { + label: string; + text?: string; + data?: JsonValue; +} + +export function MetadataViewRow({ label, text, data }: MetadataViewRowProps) { + if (text === undefined && data === undefined) { + return null; + } + return ( + + + + {label} + + + + + {data ? JSON.stringify(data) : text} + + + + ); +} + +export function MetadataView({ schema }: { schema: Schema }) { + return ( + + + + + + {schema.additionalProperties === true && ( + + )} + {schema.additionalItems === true && ( + + )} + + + + + + + + + + + + + + + +
+
+ ); +} diff --git a/plugins/config-schema/src/components/SchemaView/ObjectView.tsx b/plugins/config-schema/src/components/SchemaView/ObjectView.tsx new file mode 100644 index 0000000000..e3d0effd0d --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/ObjectView.tsx @@ -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. + */ + +import { Box, Typography } from '@material-ui/core'; +import React from 'react'; +import { ChildView } from './ChildView'; +import { MetadataView } from './MetadataView'; +import { SchemaViewProps } from './types'; + +function isRequired(name: string, required?: boolean | string[]) { + if (required === true) { + return true; + } + if (Array.isArray(required)) { + return required.includes(name); + } + return false; +} + +export function ObjectView({ path, depth, schema }: SchemaViewProps) { + const properties = Object.entries(schema.properties ?? {}); + const patternProperties = Object.entries(schema.patternProperties ?? {}); + + return ( + <> + {depth > 0 && ( + + {schema.description && ( + + {schema.description} + + )} + + + )} + {properties.length > 0 && ( + <> + {depth > 0 && Properties} + {properties.map(([name, propSchema], index) => ( + + ))} + + )} + {patternProperties.length > 0 && ( + <> + {depth > 0 && ( + Pattern Properties + )} + {patternProperties.map(([name, propSchema], index) => ( + ` : name} + depth={depth + 1} + schema={propSchema} + lastChild={index === patternProperties.length - 1} + required={isRequired(name, schema.required)} + /> + ))} + + )} + {schema.additionalProperties && schema.additionalProperties !== true && ( + <> + Additional Properties + + + )} + + ); +} diff --git a/plugins/config-schema/src/components/SchemaView/ScalarView.tsx b/plugins/config-schema/src/components/SchemaView/ScalarView.tsx new file mode 100644 index 0000000000..1349358abd --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/ScalarView.tsx @@ -0,0 +1,33 @@ +/* + * 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 { Box, Typography } from '@material-ui/core'; +import React from 'react'; +import { MetadataView } from './MetadataView'; +import { SchemaViewProps } from './types'; + +export function ScalarView({ schema }: SchemaViewProps) { + return ( + <> + {schema.description && ( + + {schema.description} + + )} + + + ); +} diff --git a/plugins/config-schema/src/components/SchemaView/SchemaView.tsx b/plugins/config-schema/src/components/SchemaView/SchemaView.tsx new file mode 100644 index 0000000000..bf5d7fd18c --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/SchemaView.tsx @@ -0,0 +1,62 @@ +/* + * 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 { ArrayView } from './ArrayView'; +import { MatchView } from './MatchView'; +import { ObjectView } from './ObjectView'; +import { ScalarView } from './ScalarView'; +import { SchemaViewProps } from './types'; + +export function SchemaView(props: SchemaViewProps) { + const { schema } = props; + if (schema.anyOf) { + return ( + + ); + } + if (schema.oneOf) { + return ( + + ); + } + if (schema.allOf) { + return ( + + ); + } + switch (schema.type) { + case 'array': + return ; + case 'object': + case undefined: + return ; + default: + return ; + } +} diff --git a/plugins/config-schema/src/components/SchemaView/index.ts b/plugins/config-schema/src/components/SchemaView/index.ts new file mode 100644 index 0000000000..8840696be6 --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/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 { SchemaView } from './SchemaView'; diff --git a/plugins/config-schema/src/components/SchemaView/types.ts b/plugins/config-schema/src/components/SchemaView/types.ts new file mode 100644 index 0000000000..94b676ec3e --- /dev/null +++ b/plugins/config-schema/src/components/SchemaView/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. + */ + +import { Schema } from 'jsonschema'; + +export interface SchemaViewProps { + path: string; + depth: number; + schema: Schema; +} diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index e34755a39e..3ad1f55451 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -13,445 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { - createContext, - ReactNode, - useContext, - useEffect, - useMemo, - useRef, -} from 'react'; -import { Schema } from 'jsonschema'; -import { - Box, - Chip, - createStyles, - Divider, - fade, - makeStyles, - Paper, - Table, - TableBody, - TableCell, - TableRow, - Typography, - withStyles, -} from '@material-ui/core'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; + +import { Box, createStyles, fade, Paper, withStyles } from '@material-ui/core'; import ChevronRightIcon from '@material-ui/icons/ChevronRight'; -import { JsonValue } from '@backstage/config'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { TreeItem, TreeItemProps, TreeView } from '@material-ui/lab'; - -class ScrollForwarder { - private readonly listeners = new Map void>(); - - setScrollListener(id: string, listener: () => void): () => void { - this.listeners.set(id, listener); - - return () => { - if (this.listeners.get(id) === listener) { - this.listeners.delete(id); - } - }; - } - - scrollTo(id: string) { - this.listeners.get(id)?.(); - } -} - -const ScrollContext = createContext(undefined); - -interface SchemaViewProps { - path: string; - depth: number; - schema: Schema; -} - -export interface MetadataViewRowProps { - label: string; - text?: string; - data?: JsonValue; -} - -export function MetadataViewRow({ label, text, data }: MetadataViewRowProps) { - if (text === undefined && data === undefined) { - return null; - } - return ( - - - - {label} - - - - - {data ? JSON.stringify(data) : text} - - - - ); -} - -export function MetadataView({ schema }: { schema: Schema }) { - return ( - - - - - - {schema.additionalProperties === true && ( - - )} - {schema.additionalItems === true && ( - - )} - - - - - - - - - - - - - - - -
-
- ); -} - -export function ScalarView({ schema }: SchemaViewProps) { - return ( - <> - {schema.description && ( - - {schema.description} - - )} - - - ); -} - -function isRequired(name: string, required?: boolean | string[]) { - if (required === true) { - return true; - } - if (Array.isArray(required)) { - return required.includes(name); - } - return false; -} - -function titleVariant(depth: number) { - if (depth <= 1) { - return 'h2'; - } else if (depth === 2) { - return 'h3'; - } else if (depth === 3) { - return 'h4'; - } else if (depth === 4) { - return 'h5'; - } - return 'h6'; -} - -export function VisibilityView({ schema }: { schema: Schema }) { - const { visibility } = schema as { visibility?: string }; - if (visibility === 'frontend') { - return ( - } - /> - ); - } else if (visibility === 'secret') { - return ( - } - /> - ); - } - return null; -} - -const useChildViewStyles = makeStyles(theme => ({ - title: { - marginBottom: 0, - }, - chip: { - marginLeft: theme.spacing(1), - marginRight: 0, - marginBottom: 0, - }, -})); - -export function ChildView({ - path, - depth, - schema, - required, - lastChild, -}: { - path: string; - depth: number; - schema?: Schema; - required?: boolean; - lastChild?: boolean; -}) { - const classes = useChildViewStyles(); - const titleRef = useRef(null); - const scroll = useContext(ScrollContext); - - useEffect(() => { - return scroll?.setScrollListener(path, () => { - titleRef.current?.scrollIntoView({ behavior: 'smooth' }); - }); - }, [scroll, path]); - - const chips = new Array(); - const chipProps = { size: 'small' as const, classes: { root: classes.chip } }; - - if (required) { - chips.push( - , - ); - } - - const visibility = (schema as { visibility?: string })?.visibility; - if (visibility === 'frontend') { - chips.push( - , - ); - } else if (visibility === 'secret') { - chips.push( - , - ); - } - - return ( - - - - - - {path} - - {chips.length > 0 && } - {chips} - - {schema && ( - - )} - - - ); -} - -export function ArrayView({ path, depth, schema }: SchemaViewProps) { - const itemDepth = depth + 1; - const itemPath = path ? `${path}[]` : '[]'; - const itemSchema = schema.items; - - return ( - <> - - {schema.description && ( - - {schema.description} - - )} - - - Items - - {schema.additionalItems && schema.additionalItems !== true && ( - <> - Additional Items - - - )} - - ); -} - -export function ObjectView({ path, depth, schema }: SchemaViewProps) { - const properties = Object.entries(schema.properties ?? {}); - const patternProperties = Object.entries(schema.patternProperties ?? {}); - - return ( - <> - {depth > 0 && ( - - {schema.description && ( - - {schema.description} - - )} - - - )} - {properties.length > 0 && ( - <> - {depth > 0 && Properties} - {properties.map(([name, propSchema], index) => ( - - ))} - - )} - {patternProperties.length > 0 && ( - <> - {depth > 0 && ( - Pattern Properties - )} - {patternProperties.map(([name, propSchema], index) => ( - ` : name} - depth={depth + 1} - schema={propSchema} - lastChild={index === patternProperties.length - 1} - required={isRequired(name, schema.required)} - /> - ))} - - )} - {schema.additionalProperties && schema.additionalProperties !== true && ( - <> - Additional Properties - - - )} - - ); -} - -export function MatchView({ - path, - depth, - schema, - label, -}: { - path: string; - depth: number; - schema: Schema[]; - label: string; -}) { - return ( - <> - {label} - {schema.map((optionSchema, index) => ( - - ))} - - ); -} - -export function SchemaView(props: SchemaViewProps) { - const { schema } = props; - if (schema.anyOf) { - return ( - - ); - } - if (schema.oneOf) { - return ( - - ); - } - if (schema.allOf) { - return ( - - ); - } - switch (schema.type) { - case 'array': - return ; - case 'object': - case undefined: - return ; - default: - return ; - } -} +import { Schema } from 'jsonschema'; +import React, { ReactNode, useMemo, useRef } from 'react'; +import { SchemaView } from '../SchemaView'; +import { ScrollTargetsProvider, useScrollTargets } from './ScrollContext'; export interface SchemaViewerProps { schema: Schema; @@ -593,7 +163,7 @@ export function createSchemaBrowserItems( } export function SchemaBrowser({ schema }: { schema: Schema }) { - const scroll = useContext(ScrollContext); + const scroll = useScrollTargets(); const expandedRef = useRef([]); const data = useMemo(() => { const expanded = new Array(); @@ -642,7 +212,7 @@ export const SchemaViewer = ({ schema }: SchemaViewerProps) => { maxHeight="100%" > - + @@ -650,7 +220,7 @@ export const SchemaViewer = ({ schema }: SchemaViewerProps) => { - + diff --git a/plugins/config-schema/src/components/SchemaViewer/ScrollTargetsContext.tsx b/plugins/config-schema/src/components/SchemaViewer/ScrollTargetsContext.tsx new file mode 100644 index 0000000000..085b237754 --- /dev/null +++ b/plugins/config-schema/src/components/SchemaViewer/ScrollTargetsContext.tsx @@ -0,0 +1,52 @@ +/* + * 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, { createContext, ReactNode, useContext } from 'react'; + +class ScrollTargetsForwarder { + private readonly listeners = new Map void>(); + + setScrollListener(id: string, listener: () => void): () => void { + this.listeners.set(id, listener); + + return () => { + if (this.listeners.get(id) === listener) { + this.listeners.delete(id); + } + }; + } + + scrollTo(id: string) { + this.listeners.get(id)?.(); + } +} + +const ScrollTargetsContext = createContext( + undefined, +); + +export function ScrollTargetsProvider({ children }: { children: ReactNode }) { + return ( + + ); +} + +export function useScrollTargets() { + return useContext(ScrollTargetsContext); +} From bcfef33a7f400ed91ced16a1682d4b843f7ba1c1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Apr 2021 12:40:30 +0200 Subject: [PATCH 083/395] config-schema: break out schema browser and scroll targets context Signed-off-by: Patrik Oldsberg --- .../ConfigSchemaPage/ConfigSchemaPage.tsx | 2 +- .../SchemaBrowser/SchemaBrowser.tsx | 196 ++++++++++++++++++ .../src/components/SchemaBrowser/index.ts | 17 ++ .../src/components/SchemaView/ChildView.tsx | 2 +- .../components/SchemaViewer/SchemaViewer.tsx | 183 +--------------- .../ScrollTargetsContext.tsx | 0 .../components/ScrollTargetsContext/index.ts | 20 ++ 7 files changed, 239 insertions(+), 181 deletions(-) create mode 100644 plugins/config-schema/src/components/SchemaBrowser/SchemaBrowser.tsx create mode 100644 plugins/config-schema/src/components/SchemaBrowser/index.ts rename plugins/config-schema/src/components/{SchemaViewer => ScrollTargetsContext}/ScrollTargetsContext.tsx (100%) create mode 100644 plugins/config-schema/src/components/ScrollTargetsContext/index.ts diff --git a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx index add916e997..4bc7cfd98c 100644 --- a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx +++ b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx @@ -27,7 +27,7 @@ export const ConfigSchemaPage = () => { return ( -
+
{schema ? : 'No schema available'} diff --git a/plugins/config-schema/src/components/SchemaBrowser/SchemaBrowser.tsx b/plugins/config-schema/src/components/SchemaBrowser/SchemaBrowser.tsx new file mode 100644 index 0000000000..52005802b8 --- /dev/null +++ b/plugins/config-schema/src/components/SchemaBrowser/SchemaBrowser.tsx @@ -0,0 +1,196 @@ +/* + * 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 { createStyles, fade, withStyles } from '@material-ui/core'; +import ChevronRightIcon from '@material-ui/icons/ChevronRight'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { TreeItem, TreeItemProps, TreeView } from '@material-ui/lab'; +import { Schema } from 'jsonschema'; +import React, { ReactNode, useMemo, useRef } from 'react'; +import { useScrollTargets } from '../ScrollTargetsContext'; + +const StyledTreeItem = withStyles(theme => + createStyles({ + label: { + userSelect: 'none', + }, + group: { + marginLeft: 7, + paddingLeft: theme.spacing(1), + borderLeft: `1px solid ${fade(theme.palette.text.primary, 0.15)}`, + }, + }), +)((props: TreeItemProps) => ); + +export function createSchemaBrowserItems( + expanded: string[], + schema: Schema, + path: string = '', + depth: number = 0, +): ReactNode { + let matchArr; + if (schema.anyOf) { + matchArr = schema.anyOf; + } else if (schema.oneOf) { + matchArr = schema.oneOf; + } else if (schema.allOf) { + matchArr = schema.allOf; + } + if (matchArr) { + return matchArr.map((childSchema, index) => { + const childPath = `${path}/${index + 1}`; + if (depth > 0) expanded.push(childPath); + return ( + `} + > + {createSchemaBrowserItems( + expanded, + childSchema, + childPath, + depth + 1, + )} + + ); + }); + } + + switch (schema.type) { + case 'array': { + const childPath = `${path}[]`; + if (depth > 0) expanded.push(childPath); + return ( + + {schema.items && + createSchemaBrowserItems( + expanded, + schema.items as Schema, + childPath, + depth + 1, + )} + + ); + } + case 'object': + case undefined: { + const children = []; + + if (schema.properties) { + children.push( + ...Object.entries(schema.properties).map(([name, childSchema]) => { + const childPath = path ? `${path}.${name}` : name; + if (depth > 0) expanded.push(childPath); + return ( + + {createSchemaBrowserItems( + expanded, + childSchema, + childPath, + depth + 1, + )} + + ); + }), + ); + } + + if (schema.patternProperties) { + children.push( + ...Object.entries(schema.patternProperties).map( + ([name, childSchema]) => { + const childPath = `${path}.<${name}>`; + if (depth > 0) expanded.push(childPath); + return ( + `} + > + {createSchemaBrowserItems( + expanded, + childSchema, + childPath, + depth + 1, + )} + + ); + }, + ), + ); + } + + if (schema.additionalProperties && schema.additionalProperties !== true) { + const childPath = `${path}.*`; + if (depth > 0) expanded.push(childPath); + children.push( + + {createSchemaBrowserItems( + expanded, + schema.additionalProperties, + childPath, + depth + 1, + )} + , + ); + } + + return <>{children}; + } + + default: + return null; + } +} + +export function SchemaBrowser({ schema }: { schema: Schema }) { + const scroll = useScrollTargets(); + const expandedRef = useRef([]); + const data = useMemo(() => { + const expanded = new Array(); + + const items = createSchemaBrowserItems(expanded, schema); + + return { items, expanded }; + }, [schema]); + + if (!scroll) { + throw new Error('No scroll handler available'); + } + + const handleToggle = (_event: unknown, expanded: string[]) => { + expandedRef.current = expanded; + }; + + const handleSelect = (_event: unknown, nodeId: string) => { + if (expandedRef.current.includes(nodeId)) { + scroll.scrollTo(nodeId); + } + }; + + return ( + } + defaultExpandIcon={} + onNodeToggle={handleToggle} + onNodeSelect={handleSelect} + > + {data.items} + + ); +} diff --git a/plugins/config-schema/src/components/SchemaBrowser/index.ts b/plugins/config-schema/src/components/SchemaBrowser/index.ts new file mode 100644 index 0000000000..2b3e8fe79a --- /dev/null +++ b/plugins/config-schema/src/components/SchemaBrowser/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 { SchemaBrowser } from './SchemaBrowser'; diff --git a/plugins/config-schema/src/components/SchemaView/ChildView.tsx b/plugins/config-schema/src/components/SchemaView/ChildView.tsx index bc4f3bb63e..ff970d5251 100644 --- a/plugins/config-schema/src/components/SchemaView/ChildView.tsx +++ b/plugins/config-schema/src/components/SchemaView/ChildView.tsx @@ -18,7 +18,7 @@ import { JsonValue } from '@backstage/config'; import { Box, Chip, Divider, makeStyles, Typography } from '@material-ui/core'; import { Schema } from 'jsonschema'; import React, { useEffect, useRef } from 'react'; -import { useScrollTargets } from '../SchemaViewer/ScrollContext'; +import { useScrollTargets } from '../ScrollTargetsContext/ScrollTargetsContext'; import { SchemaView } from './SchemaView'; export interface MetadataViewRowProps { diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx index 3ad1f55451..3ed3cca0ee 100644 --- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx @@ -14,192 +14,17 @@ * limitations under the License. */ -import { Box, createStyles, fade, Paper, withStyles } from '@material-ui/core'; -import ChevronRightIcon from '@material-ui/icons/ChevronRight'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import { TreeItem, TreeItemProps, TreeView } from '@material-ui/lab'; +import { Box, Paper } from '@material-ui/core'; import { Schema } from 'jsonschema'; -import React, { ReactNode, useMemo, useRef } from 'react'; +import React from 'react'; import { SchemaView } from '../SchemaView'; -import { ScrollTargetsProvider, useScrollTargets } from './ScrollContext'; +import { SchemaBrowser } from '../SchemaBrowser'; +import { ScrollTargetsProvider } from '../ScrollTargetsContext/ScrollTargetsContext'; export interface SchemaViewerProps { schema: Schema; } -const StyledTreeItem = withStyles(theme => - createStyles({ - label: { - userSelect: 'none', - }, - group: { - marginLeft: 7, - paddingLeft: theme.spacing(1), - borderLeft: `1px solid ${fade(theme.palette.text.primary, 0.15)}`, - }, - }), -)((props: TreeItemProps) => ); - -export function createSchemaBrowserItems( - expanded: string[], - schema: Schema, - path: string = '', - depth: number = 0, -): ReactNode { - let matchArr; - if (schema.anyOf) { - matchArr = schema.anyOf; - } else if (schema.oneOf) { - matchArr = schema.oneOf; - } else if (schema.allOf) { - matchArr = schema.allOf; - } - if (matchArr) { - return matchArr.map((childSchema, index) => { - const childPath = `${path}/${index + 1}`; - if (depth > 0) expanded.push(childPath); - return ( - `} - > - {createSchemaBrowserItems( - expanded, - childSchema, - childPath, - depth + 1, - )} - - ); - }); - } - - switch (schema.type) { - case 'array': { - const childPath = `${path}[]`; - if (depth > 0) expanded.push(childPath); - return ( - - {schema.items && - createSchemaBrowserItems( - expanded, - schema.items as Schema, - childPath, - depth + 1, - )} - - ); - } - case 'object': - case undefined: { - const children = []; - - if (schema.properties) { - children.push( - ...Object.entries(schema.properties).map(([name, childSchema]) => { - const childPath = path ? `${path}.${name}` : name; - if (depth > 0) expanded.push(childPath); - return ( - - {createSchemaBrowserItems( - expanded, - childSchema, - childPath, - depth + 1, - )} - - ); - }), - ); - } - - if (schema.patternProperties) { - children.push( - ...Object.entries(schema.patternProperties).map( - ([name, childSchema]) => { - const childPath = `${path}.<${name}>`; - if (depth > 0) expanded.push(childPath); - return ( - `} - > - {createSchemaBrowserItems( - expanded, - childSchema, - childPath, - depth + 1, - )} - - ); - }, - ), - ); - } - - if (schema.additionalProperties && schema.additionalProperties !== true) { - const childPath = `${path}.*`; - if (depth > 0) expanded.push(childPath); - children.push( - - {createSchemaBrowserItems( - expanded, - schema.additionalProperties, - childPath, - depth + 1, - )} - , - ); - } - - return <>{children}; - } - - default: - return null; - } -} - -export function SchemaBrowser({ schema }: { schema: Schema }) { - const scroll = useScrollTargets(); - const expandedRef = useRef([]); - const data = useMemo(() => { - const expanded = new Array(); - - const items = createSchemaBrowserItems(expanded, schema); - - return { items, expanded }; - }, [schema]); - - if (!scroll) { - throw new Error('No scroll handler available'); - } - - const handleToggle = (_event: unknown, expanded: string[]) => { - expandedRef.current = expanded; - }; - - const handleSelect = (_event: unknown, nodeId: string) => { - if (expandedRef.current.includes(nodeId)) { - scroll.scrollTo(nodeId); - } - }; - - return ( - } - defaultExpandIcon={} - onNodeToggle={handleToggle} - onNodeSelect={handleSelect} - > - {data.items} - - ); -} - export const SchemaViewer = ({ schema }: SchemaViewerProps) => { return ( diff --git a/plugins/config-schema/src/components/SchemaViewer/ScrollTargetsContext.tsx b/plugins/config-schema/src/components/ScrollTargetsContext/ScrollTargetsContext.tsx similarity index 100% rename from plugins/config-schema/src/components/SchemaViewer/ScrollTargetsContext.tsx rename to plugins/config-schema/src/components/ScrollTargetsContext/ScrollTargetsContext.tsx diff --git a/plugins/config-schema/src/components/ScrollTargetsContext/index.ts b/plugins/config-schema/src/components/ScrollTargetsContext/index.ts new file mode 100644 index 0000000000..d2d35ec6b1 --- /dev/null +++ b/plugins/config-schema/src/components/ScrollTargetsContext/index.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. + */ + +export { + ScrollTargetsProvider, + useScrollTargets, +} from './ScrollTargetsContext'; From 589427078385332f66d77605fac80ced8d0e5a78 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Apr 2021 13:47:34 +0200 Subject: [PATCH 084/395] config-schema: separate loading and missing schema Signed-off-by: Patrik Oldsberg --- .../ConfigSchemaPage/ConfigSchemaPage.tsx | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx index 4bc7cfd98c..a2082ef972 100644 --- a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx +++ b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx @@ -14,23 +14,35 @@ * limitations under the License. */ import React, { useMemo } from 'react'; -import { Header, Page, Content, useApi } from '@backstage/core'; +import { Header, Page, Content, useApi, Progress } from '@backstage/core'; import { useObservable } from 'react-use'; import { configSchemaApiRef } from '../../api'; import { SchemaViewer } from '../SchemaViewer'; +import { Typography } from '@material-ui/core'; export const ConfigSchemaPage = () => { const configSchemaApi = useApi(configSchemaApiRef); - const schema = useObservable( + const schemaResult = useObservable( useMemo(() => configSchemaApi.schema$(), [configSchemaApi]), - )?.schema; + ); + + let content; + if (schemaResult) { + if (schemaResult.schema) { + content = ; + } else { + content = ( + No configuration schema available + ); + } + } else { + content = ; + } return (
- - {schema ? : 'No schema available'} - + {content} ); }; From c1862f42caeaa4653a40db1223b8678ff6c2bf64 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Apr 2021 13:48:20 +0200 Subject: [PATCH 085/395] config-schema: add StaticSchemaLoader Signed-off-by: Patrik Oldsberg --- plugins/config-schema/package.json | 1 + .../src/api/StaticSchemaLoader.ts | 57 +++++++++++++++++++ plugins/config-schema/src/api/index.ts | 1 + plugins/config-schema/src/index.ts | 2 + 4 files changed, 61 insertions(+) create mode 100644 plugins/config-schema/src/api/StaticSchemaLoader.ts diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 67dcfa5976..83d04e1334 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -22,6 +22,7 @@ "dependencies": { "@backstage/config": "^0.1.4", "@backstage/core": "^0.7.3", + "@backstage/errors": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", diff --git a/plugins/config-schema/src/api/StaticSchemaLoader.ts b/plugins/config-schema/src/api/StaticSchemaLoader.ts new file mode 100644 index 0000000000..ee61370468 --- /dev/null +++ b/plugins/config-schema/src/api/StaticSchemaLoader.ts @@ -0,0 +1,57 @@ +/* + * 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 ObservableImpl from 'zen-observable'; +import { ResponseError } from '@backstage/errors'; +import { Schema } from 'jsonschema'; +import { ConfigSchemaApi, ConfigSchemaResult } from './types'; + +const DEFAULT_URL = 'config-schema.json'; + +/** + * A ConfigSchemaApi implementation that loads the configuration from a URL. + */ +export class StaticSchemaLoader implements ConfigSchemaApi { + private readonly url: string; + + constructor({ url = DEFAULT_URL }: { url?: string } = {}) { + this.url = url; + } + + schema$(): Observable { + return new ObservableImpl(subscriber => { + this.fetchSchema().then( + schema => subscriber.next({ schema }), + error => subscriber.error(error), + ); + }); + } + + private async fetchSchema(): Promise { + const res = await fetch(this.url); + + if (!res.ok) { + if (res.status === 404) { + return undefined; + } + + throw ResponseError.fromResponse(res); + } + + return await res.json(); + } +} diff --git a/plugins/config-schema/src/api/index.ts b/plugins/config-schema/src/api/index.ts index ed5e40c268..eb705b3fa3 100644 --- a/plugins/config-schema/src/api/index.ts +++ b/plugins/config-schema/src/api/index.ts @@ -16,3 +16,4 @@ export { configSchemaApiRef } from './types'; export type { ConfigSchemaApi } from './types'; +export { StaticSchemaLoader } from './StaticSchemaLoader'; diff --git a/plugins/config-schema/src/index.ts b/plugins/config-schema/src/index.ts index 0254d6a36c..009b093d50 100644 --- a/plugins/config-schema/src/index.ts +++ b/plugins/config-schema/src/index.ts @@ -13,4 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +export * from './api'; export { configSchemaPlugin, ConfigSchemaPage } from './plugin'; From 15c58af8ad2f930d9e34b5f2ceb4584720b694c7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Apr 2021 14:02:59 +0200 Subject: [PATCH 086/395] config-schema: update README Signed-off-by: Patrik Oldsberg --- plugins/config-schema/README.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/config-schema/README.md b/plugins/config-schema/README.md index 4d5d2c588d..7367868e7f 100644 --- a/plugins/config-schema/README.md +++ b/plugins/config-schema/README.md @@ -1,13 +1,19 @@ # config-schema -Welcome to the config-schema plugin! +The `config-schema` plugin lets you browse a documentation reference of the configuration schema of a particular Backstage installation. It is intended as a tool for integrators rather than something that is useful to end users of Backstage. -_This plugin was created through the Backstage CLI_ +## Usage -## Getting started +The plugin exports a single full-page extension, the `ConfigSchemaPage`, which you add to an app like a usual top-level tool on a dedicated route. -Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/config-schema](http://localhost:3000/config-schema). +It also exports a `configSchemaApiRef` without any default implementation, meaning that an API needs to be registered in the app for the plugin to work. An implementation of the API that is provided out of the box is the `StaticSchemaLoader`, which loads the schema from a URL. It can be added to the app by adding the following to your app's `api.ts`: -You can also serve the plugin in isolation by running `yarn start` in the plugin directory. -This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. -It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory. +```ts +createApiFactory(configSchemaApiRef, new StaticSchemaLoader()); +``` + +The configuration schema consumed by the `StaticSchemaLoader` can be generated using the following command: + +```shell +yarn --silent backstage-cli config:schema --format=json +``` From a10377f2451965df81cd8ab3c33c90cf06d172a6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Apr 2021 14:18:25 +0200 Subject: [PATCH 087/395] config-schema: bump @backstage package versions Signed-off-by: Patrik Oldsberg --- plugins/config-schema/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 83d04e1334..02e3ac3514 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.3", + "@backstage/core": "^0.7.4", "@backstage/errors": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -34,9 +34,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", From e23b3f8f658e85ef59f7de4a5fa8cbf980500495 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 10 Apr 2021 15:10:56 +0200 Subject: [PATCH 088/395] config-schema: added basic test + key fixes Signed-off-by: Patrik Oldsberg --- .../src/components/SchemaView/MatchView.tsx | 1 + .../src/components/SchemaView/ObjectView.tsx | 2 + .../SchemaViewer/SchemaViewer.test.tsx | 136 ++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 plugins/config-schema/src/components/SchemaViewer/SchemaViewer.test.tsx diff --git a/plugins/config-schema/src/components/SchemaView/MatchView.tsx b/plugins/config-schema/src/components/SchemaView/MatchView.tsx index df0dbba8ef..db6060b31a 100644 --- a/plugins/config-schema/src/components/SchemaView/MatchView.tsx +++ b/plugins/config-schema/src/components/SchemaView/MatchView.tsx @@ -34,6 +34,7 @@ export function MatchView({ {label} {schema.map((optionSchema, index) => ( 0 && Properties} {properties.map(([name, propSchema], index) => ( ( ` : name} depth={depth + 1} schema={propSchema} diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.test.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.test.tsx new file mode 100644 index 0000000000..48dc92098a --- /dev/null +++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.test.tsx @@ -0,0 +1,136 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import { Schema } from 'jsonschema'; +import React from 'react'; +import { SchemaViewer } from './SchemaViewer'; + +describe('SchemaViewer', () => { + it('should render a simple schema', () => { + const schema = { + type: 'object', + properties: { + a: { + description: 'My A', + type: 'string', + }, + b: { + description: 'My B', + type: 'number', + }, + }, + }; + + render(); + + expect(screen.getAllByText('a').length).toBe(2); + expect(screen.getByText('My A')).toBeInTheDocument(); + + expect(screen.getAllByText('b').length).toBe(2); + expect(screen.getByText('My B')).toBeInTheDocument(); + }); + + it('should render complex schema', () => { + const schema: Schema = { + type: 'object', + properties: { + a: { + description: 'My A', + type: 'object', + patternProperties: { + 'prefix.*': { + description: 'Prefix prop', + type: 'string', + }, + }, + additionalProperties: { + description: 'Additional properties for A', + type: 'number', + minimum: 72, + maximum: 79, + }, + }, + b: { + oneOf: [ + { type: 'string', description: 'B one of 1' }, + { + type: 'array', + description: 'B one of 2', + items: { + anyOf: [ + { type: 'string', description: 'Any of B 1' }, + { type: 'number', description: 'Any of B 2' }, + { + type: 'object', + description: 'Any of B 3', + properties: { + deep: { + allOf: [ + { + type: 'number', + description: 'Impossible 1', + }, + { + type: 'boolean', + description: 'Impossible 2', + }, + ], + }, + }, + }, + ], + }, + }, + ], + }, + }, + }; + + render(); + + expect(screen.getAllByText('a').length).toBe(2); + expect(screen.getByText('My A')).toBeInTheDocument(); + expect(screen.getByText('a.')).toBeInTheDocument(); + expect(screen.getByText('Prefix prop')).toBeInTheDocument(); + + expect(screen.getByText('a.*')).toBeInTheDocument(); + expect(screen.getByText('Additional properties for A')).toBeInTheDocument(); + expect(screen.getByText('72')).toBeInTheDocument(); + expect(screen.getByText('79')).toBeInTheDocument(); + + expect(screen.getAllByText('b').length).toBe(2); + expect(screen.getByText('b/1')).toBeInTheDocument(); + expect(screen.getByText('B one of 1')).toBeInTheDocument(); + + expect(screen.getByText('b/2')).toBeInTheDocument(); + expect(screen.getByText('B one of 2')).toBeInTheDocument(); + + expect(screen.getByText('b/2[]')).toBeInTheDocument(); + expect(screen.getByText('b/2[]/1')).toBeInTheDocument(); + expect(screen.getByText('Any of B 1')).toBeInTheDocument(); + expect(screen.getByText('b/2[]/2')).toBeInTheDocument(); + expect(screen.getByText('Any of B 2')).toBeInTheDocument(); + expect(screen.getByText('b/2[]/3')).toBeInTheDocument(); + expect(screen.getByText('Any of B 3')).toBeInTheDocument(); + + expect(screen.getByText('b/2[]/3.deep')).toBeInTheDocument(); + expect(screen.getByText('b/2[]/3.deep/1')).toBeInTheDocument(); + expect(screen.getByText('Impossible 1')).toBeInTheDocument(); + expect(screen.getByText('b/2[]/3.deep/2')).toBeInTheDocument(); + expect(screen.getByText('Impossible 2')).toBeInTheDocument(); + }); +}); From 8210a2ea521e3c49e1217d7356acde8baa48f967 Mon Sep 17 00:00:00 2001 From: Travis Truman Date: Sat, 10 Apr 2021 15:48:08 -0400 Subject: [PATCH 089/395] Correcting the path to the Root component Signed-off-by: Travis Truman --- docs/getting-started/configure-app-with-plugins.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index 964987c4a7..e5b4d08a3f 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -68,9 +68,9 @@ proxy: In a standard Backstage app created with [@backstage/create-app](./create-an-app.md), the sidebar is managed inside -`packages/app/src/components/Root.tsx`. The file exports the entire `Sidebar` -element of your app, which you can extend with additional entries by adding new -`SidebarItem` elements. +`packages/app/src/components/Root/Root.tsx`. The file exports the entire +`Sidebar` element of your app, which you can extend with additional entries by +adding new `SidebarItem` elements. For example, if you install the `api-docs` plugin, a matching `SidebarItem` could be something like this: From 46995e92bf660012bef31b6a4aefa1f13096ad3e Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Sun, 11 Apr 2021 10:01:52 +0200 Subject: [PATCH 090/395] Use text column type Signed-off-by: Erik Larsson --- plugins/scaffolder-backend/migrations/20210409225200_secrets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/migrations/20210409225200_secrets.js b/plugins/scaffolder-backend/migrations/20210409225200_secrets.js index e1bd6d2a51..e96f406782 100644 --- a/plugins/scaffolder-backend/migrations/20210409225200_secrets.js +++ b/plugins/scaffolder-backend/migrations/20210409225200_secrets.js @@ -22,7 +22,7 @@ exports.up = async function up(knex) { await knex.schema.alterTable('tasks', table => { table - .string('secrets') + .text('secrets') .nullable() .comment('JSON encoded secrets to authenticate tasks with'); }); From 47c96fb5396419d715298202ab60196a33fb1a3e Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Sun, 11 Apr 2021 15:35:49 +0200 Subject: [PATCH 091/395] Fix bugs, add tests Signed-off-by: Erik Larsson --- .../actions/builtin/catalog/register.ts | 11 ++++--- .../src/scaffolder/tasks/DatabaseTaskStore.ts | 4 +-- .../tasks/StorageTaskBroker.test.ts | 30 ++++++++++++++++++- .../src/scaffolder/tasks/StorageTaskBroker.ts | 6 ++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts index 8ee98f5d20..5d169a73fd 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts @@ -95,10 +95,13 @@ export function createCatalogRegisterAction(options: { ctx.logger.info(`Registering ${catalogInfoUrl} in the catalog`); - const result = await catalogClient.addLocation({ - type: 'url', - target: catalogInfoUrl, - }); + const result = await catalogClient.addLocation( + { + type: 'url', + target: catalogInfoUrl, + }, + ...(ctx.token ? [{ token: ctx.token }] : []), + ); if (result.entities.length >= 1) { const { kind, name, namespace } = getEntityName(result.entities[0]); ctx.output('entityRef', `${kind}:${namespace}/${name}`); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index fdc403ec65..1f1228baf8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -127,7 +127,7 @@ export class DatabaseTaskStore implements TaskStore { try { const spec = JSON.parse(task.spec); - const secrets = task.secrets ? JSON.parse(task.spec) : undefined; + const secrets = task.secrets ? JSON.parse(task.secrets) : undefined; return { id: task.id, spec, @@ -219,7 +219,7 @@ export class DatabaseTaskStore implements TaskStore { }) .update({ status, - secrets: undefined, + secrets: null as any, }); if (updateCount !== 1) { throw new ConflictError( diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts index fd2de30332..4a025c25e2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts @@ -21,7 +21,7 @@ import { import { ConfigReader } from '@backstage/config'; import { DatabaseTaskStore } from './DatabaseTaskStore'; import { StorageTaskBroker, TaskAgent } from './StorageTaskBroker'; -import { TaskSpec, DbTaskEventRow } from './types'; +import { TaskSecrets, TaskSpec, DbTaskEventRow } from './types'; async function createStore(): Promise { const manager = SingleConnectionDatabaseManager.fromConfig( @@ -39,6 +39,7 @@ async function createStore(): Promise { describe('StorageTaskBroker', () => { let storage: DatabaseTaskStore; + const fakeSecrets = { identityToken: 'secret' } as TaskSecrets; beforeAll(async () => { storage = await createStore(); @@ -78,6 +79,13 @@ describe('StorageTaskBroker', () => { await expect(taskC.spec.steps[0].id).toBe('c'); }); + it('should store secrets', async () => { + const broker = new StorageTaskBroker(storage, logger); + await broker.dispatch({} as TaskSpec, fakeSecrets); + const task = await broker.claim(); + expect(task.secrets).toEqual(fakeSecrets); + }, 10000); + it('should complete a task', async () => { const broker = new StorageTaskBroker(storage, logger); const dispatchResult = await broker.dispatch({} as TaskSpec); @@ -87,6 +95,16 @@ describe('StorageTaskBroker', () => { expect(taskRow.status).toBe('completed'); }, 10000); + it('should remove secrets after completing a task', async () => { + const broker = new StorageTaskBroker(storage, logger); + const dispatchResult = await broker.dispatch({} as TaskSpec, fakeSecrets); + const task = await broker.claim(); + await task.complete('completed'); + const taskRow = await storage.getTask(dispatchResult.taskId); + expect(taskRow.status).toBe('completed'); + expect(taskRow.secrets).toBeUndefined(); + }, 10000); + it('should fail a task', async () => { const broker = new StorageTaskBroker(storage, logger); const dispatchResult = await broker.dispatch({} as TaskSpec); @@ -96,6 +114,16 @@ describe('StorageTaskBroker', () => { expect(taskRow.status).toBe('failed'); }); + it('should remove secrets afteer failing a task', async () => { + const broker = new StorageTaskBroker(storage, logger); + const dispatchResult = await broker.dispatch({} as TaskSpec, fakeSecrets); + const task = await broker.claim(); + await task.complete('failed'); + const taskRow = await storage.getTask(dispatchResult.taskId); + expect(taskRow.status).toBe('failed'); + expect(taskRow.secrets).toBeUndefined(); + }); + it('multiple brokers should be able to observe a single task', async () => { const broker1 = new StorageTaskBroker(storage, logger); const broker2 = new StorageTaskBroker(storage, logger); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 8f30afde6f..6a82fa53ca 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -49,6 +49,10 @@ export class TaskAgent implements Task { return this.state.spec; } + get secrets() { + return this.state.secrets; + } + async getWorkspaceName() { return this.state.taskId; } @@ -102,6 +106,7 @@ export class TaskAgent implements Task { interface TaskState { spec: TaskSpec; taskId: string; + secrets?: TaskSecrets; } function defer() { @@ -127,6 +132,7 @@ export class StorageTaskBroker implements TaskBroker { { taskId: pendingTask.id, spec: pendingTask.spec, + secrets: pendingTask.secrets, }, this.storage, this.logger, From 22e3f003b7b689f73f550779e112473a2f435f48 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 12 Apr 2021 13:51:57 +0200 Subject: [PATCH 092/395] chore: fix of resolutions for now for the package that's broken the build Signed-off-by: blam --- package.json | 3 ++- packages/create-app/templates/default-app/package.json.hbs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index fcabe5b3e5..be9998ce22 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "resolutions": { "**/@roadiehq/**/@backstage/core": "*", "**/@roadiehq/**/@backstage/plugin-catalog": "*", - "**/@roadiehq/**/@backstage/catalog-model": "*" + "**/@roadiehq/**/@backstage/catalog-model": "*", + "graphql-language-service-interface": "2.8.2" }, "version": "1.0.0", "devDependencies": { diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index d7f7fbafaf..2f1ae134bf 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -22,6 +22,9 @@ "create-plugin": "backstage-cli create-plugin --scope internal --no-private", "remove-plugin": "backstage-cli remove-plugin" }, + "resolutions": { + "graphql-language-service-interface": "2.8.2" + }, "workspaces": { "packages": [ "packages/*", From b49a525ab67a843a05ac3e7e9f70d480544fbe4d Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 12 Apr 2021 14:00:52 +0200 Subject: [PATCH 093/395] chore: add changeset Signed-off-by: blam --- .changeset/fluffy-rice-push.md | 5 +++++ yarn.lock | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/fluffy-rice-push.md diff --git a/.changeset/fluffy-rice-push.md b/.changeset/fluffy-rice-push.md new file mode 100644 index 0000000000..69dd7fe4f6 --- /dev/null +++ b/.changeset/fluffy-rice-push.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Fixing dependency resolution for problematic library graphql-language-service-interface diff --git a/yarn.lock b/yarn.lock index cf967cf96f..f4843d960e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14492,7 +14492,7 @@ graphql-extensions@^0.12.8: apollo-server-env "^3.0.0" apollo-server-types "^0.6.3" -graphql-language-service-interface@^2.8.2: +graphql-language-service-interface@2.8.2, graphql-language-service-interface@^2.8.2: version "2.8.2" resolved "https://registry.npmjs.org/graphql-language-service-interface/-/graphql-language-service-interface-2.8.2.tgz#b3bb2aef7eaf0dff0b4ea419fa412c5f66fa268b" integrity sha512-otbOQmhgkAJU1QJgQkMztNku6SbJLu/uodoFOYOOtJsizTjrMs93vkYaHCcYnLA3oi1Goj27XcHjMnRCYQOZXQ== From a4c85bd0e31489712f3914d6a4d9ba6cabc54add Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 12 Apr 2021 14:04:45 +0200 Subject: [PATCH 094/395] chore: update changeset description Signed-off-by: blam --- .changeset/fluffy-rice-push.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.changeset/fluffy-rice-push.md b/.changeset/fluffy-rice-push.md index 69dd7fe4f6..dc56db4678 100644 --- a/.changeset/fluffy-rice-push.md +++ b/.changeset/fluffy-rice-push.md @@ -2,4 +2,28 @@ '@backstage/create-app': patch --- -Fixing dependency resolution for problematic library graphql-language-service-interface +Fixing dependency resolution for problematic library `graphql-language-service-interface`. + +This change might not have to be applied to your local installation, however if you run into this error: + +``` +Error: Failed to compile. +/tmp/backstage-e2e-uMeycm/test-app/node_modules/graphql-language-service-interface/esm/GraphQLLanguageService.js 100:23 +Module parse failed: Unexpected token (100:23) +You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders +| } +| let customRules = null; +> if (extensions?.customValidationRules && +| typeof extensions.customValidationRules === 'function') { +| customRules = extensions.customValidationRules(this._graphQLConfig); +``` + +You can fix it by adding the following to the root `package.json`. + +```json +... +"resolutions": { + "graphql-language-service-interface": "2.8.2" + }, +... +``` From 02e9f013044cf4f3a6913aba4b56b8f1c3102956 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 12 Apr 2021 14:41:07 +0200 Subject: [PATCH 095/395] chore: was missing one other dependency Signed-off-by: blam --- .changeset/fluffy-rice-push.md | 3 ++- package.json | 3 ++- packages/create-app/templates/default-app/package.json.hbs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.changeset/fluffy-rice-push.md b/.changeset/fluffy-rice-push.md index dc56db4678..032d580c6b 100644 --- a/.changeset/fluffy-rice-push.md +++ b/.changeset/fluffy-rice-push.md @@ -23,7 +23,8 @@ You can fix it by adding the following to the root `package.json`. ```json ... "resolutions": { - "graphql-language-service-interface": "2.8.2" + "graphql-language-service-interface": "2.8.2", + "graphql-language-service-parser": "1.9.0" }, ... ``` diff --git a/package.json b/package.json index be9998ce22..d87b98fbdb 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,8 @@ "**/@roadiehq/**/@backstage/core": "*", "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*", - "graphql-language-service-interface": "2.8.2" + "graphql-language-service-interface": "2.8.2", + "graphql-language-service-parser": "1.9.0" }, "version": "1.0.0", "devDependencies": { diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index 2f1ae134bf..7ae86c0fbc 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -23,7 +23,8 @@ "remove-plugin": "backstage-cli remove-plugin" }, "resolutions": { - "graphql-language-service-interface": "2.8.2" + "graphql-language-service-interface": "2.8.2", + "graphql-language-service-parser": "1.9.0" }, "workspaces": { "packages": [ From 77f13cb4ca77af0d92cfe02e919c7f6084f3571d Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Mon, 12 Apr 2021 15:19:42 +0200 Subject: [PATCH 096/395] Update roadie plugins to newer versions * Enable plugins in entity page * Change plugin imports to use new named exports Signed-off-by: Jussi Hallila --- packages/app/package.json | 8 +- .../app/src/components/catalog/EntityPage.tsx | 86 +++++++++---------- packages/app/src/plugins.ts | 8 +- yarn.lock | 36 ++++---- 4 files changed, 71 insertions(+), 67 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index 2bac2e6e09..1fc0335aa2 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -42,10 +42,10 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@octokit/rest": "^18.0.12", - "@roadiehq/backstage-plugin-buildkite": "^0.3.0", - "@roadiehq/backstage-plugin-github-insights": "^0.3.3", - "@roadiehq/backstage-plugin-github-pull-requests": "^0.7.9", - "@roadiehq/backstage-plugin-travis-ci": "^0.4.7", + "@roadiehq/backstage-plugin-buildkite": "^1.0.0", + "@roadiehq/backstage-plugin-github-insights": "^1.0.0", + "@roadiehq/backstage-plugin-github-pull-requests": "^1.0.0", + "@roadiehq/backstage-plugin-travis-ci": "^1.0.0", "history": "^5.0.0", "prop-types": "^15.7.2", "react": "^16.12.0", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index d8ee62a12c..d6f91957a9 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -81,27 +81,27 @@ import { EntitySentryContent } from '@backstage/plugin-sentry'; import { EntityTechdocsContent } from '@backstage/plugin-techdocs'; import { EntityTodoContent } from '@backstage/plugin-todo'; import { Button, Grid } from '@material-ui/core'; -// import { -// EntityBuildkiteContent, -// isBuildkiteAvailable, -// } from '@roadiehq/backstage-plugin-buildkite'; -// import { -// EntityGitHubInsightsContent, -// EntityLanguagesCard, -// EntityReadMeCard, -// EntityReleasesCard, -// isGithubInsightsAvailable, -// } from '@roadiehq/backstage-plugin-github-insights'; -// import { -// EntityGithubPullRequestsContent, -// EntityGithubPullRequestsOverviewCard, -// isGithubPullRequestsAvailable, -// } from '@roadiehq/backstage-plugin-github-pull-requests'; -// import { -// EntityTravisCIContent, -// EntityTravisCIOverviewCard, -// isTravisciAvailable, -// } from '@roadiehq/backstage-plugin-travis-ci'; +import { + EntityBuildkiteContent, + isBuildkiteAvailable, +} from '@roadiehq/backstage-plugin-buildkite'; +import { + EntityGithubInsightsContent, + EntityGithubInsightsLanguagesCard, + EntityGithubInsightsReadmeCard, + EntityGithubInsightsReleasesCard, + isGithubInsightsAvailable, +} from '@roadiehq/backstage-plugin-github-insights'; +import { + EntityGithubPullRequestsContent, + EntityGithubPullRequestsOverviewCard, + isGithubPullRequestsAvailable, +} from '@roadiehq/backstage-plugin-github-pull-requests'; +import { + EntityTravisCIContent, + EntityTravisCIOverviewCard, + isTravisciAvailable, +} from '@roadiehq/backstage-plugin-travis-ci'; const EntityLayoutWrapper = (props: { children?: ReactNode }) => { const [badgesDialogOpen, setBadgesDialogOpen] = useState(false); @@ -135,9 +135,9 @@ export const cicdContent = ( - {/* + - */} + @@ -147,9 +147,9 @@ export const cicdContent = ( - {/* + - */} + @@ -182,11 +182,11 @@ const cicdCard = ( - {/* + - */} + @@ -228,17 +228,17 @@ const overviewContent = ( {cicdCard} - {/* + Boolean(isGithubInsightsAvailable(e))}> - - + + - + - */} + @@ -248,13 +248,13 @@ const overviewContent = ( - {/* + Boolean(isGithubPullRequestsAvailable(e))}> - */} + @@ -295,13 +295,13 @@ const serviceEntityPage = ( - {/* + - */} + - {/* - - */} + + + @@ -339,13 +339,13 @@ const websiteEntityPage = ( - {/* + - */} + - {/* + - */} + diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index ccc7e2a45c..e08bfd6abe 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -27,19 +27,19 @@ export { plugin as GraphiQL } from '@backstage/plugin-graphiql'; export { plugin as GithubActions } from '@backstage/plugin-github-actions'; export { plugin as Rollbar } from '@backstage/plugin-rollbar'; export { plugin as Newrelic } from '@backstage/plugin-newrelic'; -export { plugin as TravisCI } from '@roadiehq/backstage-plugin-travis-ci'; +export { travisciPlugin } from '@roadiehq/backstage-plugin-travis-ci'; export { plugin as Jenkins } from '@backstage/plugin-jenkins'; export { plugin as ApiDocs } from '@backstage/plugin-api-docs'; -export { plugin as GithubPullRequests } from '@roadiehq/backstage-plugin-github-pull-requests'; +export { githubPullRequestsPlugin } from '@roadiehq/backstage-plugin-github-pull-requests'; export { plugin as GcpProjects } from '@backstage/plugin-gcp-projects'; export { plugin as Kubernetes } from '@backstage/plugin-kubernetes'; export { plugin as Cloudbuild } from '@backstage/plugin-cloudbuild'; export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; -export { plugin as GitHubInsights } from '@roadiehq/backstage-plugin-github-insights'; +export { githubInsightsPlugin } from '@roadiehq/backstage-plugin-github-insights'; export { plugin as CatalogImport } from '@backstage/plugin-catalog-import'; export { plugin as UserSettings } from '@backstage/plugin-user-settings'; export { plugin as PagerDuty } from '@backstage/plugin-pagerduty'; -export { plugin as Buildkite } from '@roadiehq/backstage-plugin-buildkite'; +export { buildkitePlugin } from '@roadiehq/backstage-plugin-buildkite'; export { plugin as Search } from '@backstage/plugin-search'; export { plugin as Org } from '@backstage/plugin-org'; export { plugin as Kafka } from '@backstage/plugin-kafka'; diff --git a/yarn.lock b/yarn.lock index c3bd4a2296..c58b697ac5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4375,14 +4375,15 @@ resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-2.4.1.tgz#b0dedff8877b114147e298966ca3faba895a7a62" integrity sha512-pZaWL5Dw+km8S0hFLIK1lRHaeNtheMxTF2mZrWhf6HlGWCTGkQJnXta2UgshJN/nKtZPgO1L4FKz42Eun9nnhg== -"@roadiehq/backstage-plugin-buildkite@^0.3.0": - version "0.3.0" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-0.3.0.tgz#60db5e712b88bc9cf3476737a1835f4fc26ae616" - integrity sha512-YeATwsR9G93/l3zZmzDN2k0vZzo0Tw0G0pp16B6p1Tz4lBUxiQ40D0anSsVrzep4NR3rxbzqzh7OGZ8Pihfcpw== +"@roadiehq/backstage-plugin-buildkite@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-1.0.0.tgz#0c00352eb7a204ac45f55bc5dd4c17c9c1cfdf9e" + integrity sha512-R6pxMSOeTK+4OBBhSktEEEIkaVTcOWTsgnpB5FEZ748YZ3Ul4dp4H2S3bup2OnMIL79xY2oAxYt1iRmAe69Bng== dependencies: "@backstage/catalog-model" "^0.7.4" "@backstage/core" "^0.7.3" "@backstage/plugin-catalog" "^0.5.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" @@ -4396,13 +4397,14 @@ react-router-dom "6.0.0-beta.0" react-use "^15.3.6" -"@roadiehq/backstage-plugin-github-insights@^0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-0.3.3.tgz#f2b4aeff76930d4ea4f5ca80bf1ad6f407dd6b74" - integrity sha512-sRczrC4JRli8Po1FXL5M6qiCJiUUWpin+kH7XSlo5JJoK5+UdNP05l1qFkMkeCyPdkJp/iVvXArkHPyWnm361g== +"@roadiehq/backstage-plugin-github-insights@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-1.0.0.tgz#8b30bd3c4979aab8cd145c4c0b28488badd8e662" + integrity sha512-KynUXVGb+lpMoDoGrolOtsY9roFuPaMre92g1/DZBoLU2BXFpdmnhJXf1YaDHVuBIITP0AhtQfZpu8KNXm/Cmg== dependencies: "@backstage/catalog-model" "^0.7.4" "@backstage/core" "^0.7.3" + "@backstage/plugin-catalog-react" "^0.1.4" "@backstage/theme" "^0.2.5" "@date-io/core" "2.10.7" "@material-ui/core" "^4.11.0" @@ -4416,13 +4418,14 @@ react-router "^6.0.0-beta.0" react-use "^17.2.1" -"@roadiehq/backstage-plugin-github-pull-requests@^0.7.9": - version "0.7.9" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.7.9.tgz#61ea6bc6a50defe0223ef8dff124379673f54c55" - integrity sha512-qUyCShhtV4x3QaZewiw13lQBmWLTjybOTsy7x+j4iY6IXkOhol5E2uWVTWifJLxDXg76FsXKWw9eRIqBSOrTRQ== +"@roadiehq/backstage-plugin-github-pull-requests@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-1.0.0.tgz#5103d9ff65ed38a752ceb8ac1c7369fd0724388f" + integrity sha512-HAi3X0kto/xMNaMzy9f4t142MGvxwuxDfiLN+bZUsWwta4iI3CgK/9fZAd5kU9+E04EFxkRXmg72FXxG64H6Zg== dependencies: "@backstage/catalog-model" "^0.7.4" "@backstage/core" "^0.7.3" + "@backstage/plugin-catalog-react" "^0.1.4" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@octokit/rest" "^18.1.1" @@ -4436,14 +4439,15 @@ react-router "6.0.0-beta.0" react-use "^15.3.6" -"@roadiehq/backstage-plugin-travis-ci@^0.4.7": - version "0.4.7" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.4.7.tgz#ce37ff8b3124975999f0cfe01170b8b5aee55fb3" - integrity sha512-hDyOND6/gpCy0GpHLwTDXwNfVWVIBpjh5Ipac0bBa7Yyyj0MKI4UVmLu1K99fRZk1aI6n6TIyLYAJTabLmuYuQ== +"@roadiehq/backstage-plugin-travis-ci@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-1.0.0.tgz#5aa29f4ba2086b6341a903a22c843d898808f503" + integrity sha512-JjMDwbou1iY0sSoit8ttpzXEP6lhmLmxf/Pj6Am/1rcia5KLdeMUqpilkzQ33LeHiMXXxu95gp4r6aJ5vC9wGg== dependencies: "@backstage/catalog-model" "^0.7.4" "@backstage/core" "^0.7.3" "@backstage/plugin-catalog" "^0.5.1" + "@backstage/plugin-catalog-react" "^0.1.4" "@backstage/theme" "^0.2.5" "@material-ui/core" "^4.9.1" "@material-ui/icons" "^4.9.1" From 99c7ff15c970d880488537c267fcf2bf222e76a6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 12 Apr 2021 14:55:54 +0200 Subject: [PATCH 097/395] cli: update some webpack config to be v5 compatible Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/bundler/transforms.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/lib/bundler/transforms.ts b/packages/cli/src/lib/bundler/transforms.ts index 4f097343c2..6107485d78 100644 --- a/packages/cli/src/lib/bundler/transforms.ts +++ b/packages/cli/src/lib/bundler/transforms.ts @@ -74,7 +74,7 @@ export const transforms = (options: TransformOptions): Transforms => { /\.jpe?g$/, /\.png$/, /\.frag/, - { test: /\.svg/, not: [/\.icon\.svg/] }, + { and: [/\.svg/, { not: [/\.icon\.svg/] }] }, /\.xml/, ], loader: require.resolve('url-loader'), From ca324156b51e92da4c95dfa8b1a7a5c8fd3c028f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Apr 2021 14:24:18 +0000 Subject: [PATCH 098/395] chore(deps): bump @babel/core from 7.12.9 to 7.13.15 Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.9 to 7.13.15. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.13.15/packages/babel-core) Signed-off-by: dependabot[bot] --- yarn.lock | 358 +++++++++++++++--------------------------------------- 1 file changed, 101 insertions(+), 257 deletions(-) diff --git a/yarn.lock b/yarn.lock index f4843d960e..7d4eda4f1c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -249,7 +249,7 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/code-frame@7.10.4", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": +"@babel/code-frame@7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== @@ -263,77 +263,45 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/code-frame@^7.12.13": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5": version "7.12.13" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== dependencies: "@babel/highlight" "^7.12.13" -"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": +"@babel/compat-data@^7.12.7": version "7.12.7" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== +"@babel/compat-data@^7.13.12": + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.15.tgz#7e8eea42d0b64fda2b375b22d06c605222e848f4" + integrity sha512-ltnibHKR1VnrU4ymHyQ/CXtNXI6yZC0oJThyW78Hft8XndANwi+9H+UIklBDraIjFEJzw8wmcM427oDd9KS5wA== + "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.4.4", "@babel/core@^7.7.5": - version "7.12.9" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" - integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.13.15.tgz#a6d40917df027487b54312202a06812c4f7792d0" + integrity sha512-6GXmNYeNjS2Uz+uls5jalOemgIhnTMeaXo+yBUA72kC2uX/8VW6XyhVIo2L8/q0goKQA3EVKx0KOQpVKSeWadQ== dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.5" - "@babel/parser" "^7.12.7" - "@babel/template" "^7.12.7" - "@babel/traverse" "^7.12.9" - "@babel/types" "^7.12.7" + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.9" + "@babel/helper-compilation-targets" "^7.13.13" + "@babel/helper-module-transforms" "^7.13.14" + "@babel/helpers" "^7.13.10" + "@babel/parser" "^7.13.15" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.15" + "@babel/types" "^7.13.14" convert-source-map "^1.7.0" debug "^4.1.0" - gensync "^1.0.0-beta.1" + gensync "^1.0.0-beta.2" json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" + semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.10.5": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" - integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== - dependencies: - "@babel/types" "^7.10.5" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.11.0", "@babel/generator@^7.5.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" - integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== - dependencies: - "@babel/types" "^7.11.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.11.5", "@babel/generator@^7.9.6": - version "7.11.6" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" - integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== - dependencies: - "@babel/types" "^7.11.5" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.12.5": - version "7.12.5" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" - integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A== - dependencies: - "@babel/types" "^7.12.5" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.13.0": +"@babel/generator@^7.11.5", "@babel/generator@^7.13.9", "@babel/generator@^7.5.0": version "7.13.9" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== @@ -399,15 +367,15 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.12.5": - version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" - integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== +"@babel/helper-compilation-targets@^7.12.5", "@babel/helper-compilation-targets@^7.13.13": + version "7.13.13" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.13.tgz#2b2972a0926474853f41e4adbc69338f520600e5" + integrity sha512-q1kcdHNZehBwD9jYPh3WyXcsFERi39X4I59I3NadciWtNDyZ6x+GboOxncFK0kXlKIv6BJm5acncehXWUjWQMQ== dependencies: - "@babel/compat-data" "^7.12.5" - "@babel/helper-validator-option" "^7.12.1" + "@babel/compat-data" "^7.13.12" + "@babel/helper-validator-option" "^7.12.17" browserslist "^4.14.5" - semver "^5.5.0" + semver "^6.3.0" "@babel/helper-create-class-features-plugin@^7.10.4": version "7.10.5" @@ -466,7 +434,7 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.9.5": +"@babel/helper-function-name@^7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== @@ -519,12 +487,12 @@ dependencies: "@babel/types" "^7.12.7" -"@babel/helper-member-expression-to-functions@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" - integrity sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ== +"@babel/helper-member-expression-to-functions@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" + integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== dependencies: - "@babel/types" "^7.13.0" + "@babel/types" "^7.13.12" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4": version "7.10.4" @@ -540,27 +508,26 @@ dependencies: "@babel/types" "^7.12.5" -"@babel/helper-module-imports@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0" - integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g== +"@babel/helper-module-imports@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" + integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.13.12" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz#42eb4bd8eea68bab46751212c357bfed8b40f6f1" - integrity sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.13.14": + version "7.13.14" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz#e600652ba48ccb1641775413cb32cfa4e8b495ef" + integrity sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g== dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-replace-supers" "^7.13.0" - "@babel/helper-simple-access" "^7.12.13" + "@babel/helper-module-imports" "^7.13.12" + "@babel/helper-replace-supers" "^7.13.12" + "@babel/helper-simple-access" "^7.13.12" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-validator-identifier" "^7.12.11" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" - lodash "^4.17.19" + "@babel/traverse" "^7.13.13" + "@babel/types" "^7.13.14" "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" @@ -617,15 +584,15 @@ "@babel/traverse" "^7.12.5" "@babel/types" "^7.12.5" -"@babel/helper-replace-supers@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" - integrity sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw== +"@babel/helper-replace-supers@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz#6442f4c1ad912502481a564a7386de0c77ff3804" + integrity sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.13.0" + "@babel/helper-member-expression-to-functions" "^7.13.12" "@babel/helper-optimise-call-expression" "^7.12.13" "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" + "@babel/types" "^7.13.12" "@babel/helper-simple-access@^7.12.13": version "7.12.13" @@ -634,6 +601,13 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-simple-access@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" + integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== + dependencies: + "@babel/types" "^7.13.12" + "@babel/helper-skip-transparent-expression-wrappers@^7.11.0": version "7.11.0" resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" @@ -648,7 +622,7 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.8.3": +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== @@ -677,6 +651,11 @@ resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -687,14 +666,14 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.12.5": - version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" - integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== +"@babel/helpers@^7.13.10": + version "7.13.10" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8" + integrity sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ== dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" "@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4", "@babel/highlight@^7.8.3": version "7.10.4" @@ -714,35 +693,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@7.11.5", "@babel/parser@^7.11.5": +"@babel/parser@7.11.5": version "7.11.5" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== -"@babel/parser@^7.0.0", "@babel/parser@^7.11.0": - version "7.11.3" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" - integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== - -"@babel/parser@^7.1.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6": - version "7.9.6" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" - integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== - -"@babel/parser@^7.10.4", "@babel/parser@^7.10.5": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" - integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== - -"@babel/parser@^7.12.13", "@babel/parser@^7.13.0": - version "7.13.11" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.13.11.tgz#f93ebfc99d21c1772afbbaa153f47e7ce2f50b88" - integrity sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q== - -"@babel/parser@^7.12.7": - version "7.12.7" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056" - integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.11.5", "@babel/parser@^7.12.13", "@babel/parser@^7.13.15": + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.13.15.tgz#8e66775fb523599acb6a289e12929fa5ab0954d8" + integrity sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.1" @@ -1663,16 +1622,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/template@^7.12.13": +"@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" integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== @@ -1681,24 +1631,6 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/template@^7.12.7": - version "7.12.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" - integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.12.7" - "@babel/types" "^7.12.7" - -"@babel/template@^7.3.3": - version "7.8.6" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" - "@babel/traverse@7.11.5": version "7.11.5" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" @@ -1714,82 +1646,21 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/traverse@^7.0.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" - integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.11.0" - "@babel/types" "^7.11.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.1.0": - version "7.9.6" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" - integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.10.4": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" - integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.5" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - "@babel/parser" "^7.10.5" - "@babel/types" "^7.10.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9": - version "7.12.9" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz#fad26c972eabbc11350e0b695978de6cc8e8596f" - integrity sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.7" - "@babel/types" "^7.12.7" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" - integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.5", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.13", "@babel/traverse@^7.13.15": + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.15.tgz#c38bf7679334ddd4028e8e1f7b3aa5019f0dada7" + integrity sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.0" + "@babel/generator" "^7.13.9" "@babel/helper-function-name" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.13.0" - "@babel/types" "^7.13.0" + "@babel/parser" "^7.13.15" + "@babel/types" "^7.13.14" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.19" -"@babel/types@7.11.5", "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.6", "@babel/types@^7.9.6": +"@babel/types@7.11.5": version "7.11.5" resolved "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== @@ -1798,37 +1669,10 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@babel/types@^7.11.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" - integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.12.6", "@babel/types@^7.12.7": - version "7.12.7" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.7.tgz#6039ff1e242640a29452c9ae572162ec9a8f5d13" - integrity sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.12.10": - version "7.12.10" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.10.tgz#7965e4a7260b26f09c56bcfcb0498af1f6d9b260" - integrity sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.12.13", "@babel/types@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" - integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.13.14" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz#c35a4abb15c7cd45a2746d78ab328e362cbace0d" + integrity sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ== dependencies: "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" @@ -13898,10 +13742,10 @@ generic-pool@2.4.3: resolved "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" integrity sha1-eAw29p360FpaBF3Te+etyhGk9v8= -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^1.0.1: version "1.0.3" @@ -14502,7 +14346,7 @@ graphql-language-service-interface@2.8.2, graphql-language-service-interface@^2. graphql-language-service-utils "^2.5.1" vscode-languageserver-types "^3.15.1" -graphql-language-service-parser@^1.9.0: +graphql-language-service-parser@1.9.0, graphql-language-service-parser@^1.9.0: version "1.9.0" resolved "https://registry.npmjs.org/graphql-language-service-parser/-/graphql-language-service-parser-1.9.0.tgz#79af21294119a0a7e81b6b994a1af36833bab724" integrity sha512-B5xPZLbBmIp0kHvpY1Z35I5DtPoDK9wGxQVRDIzcBaiIvAmlTrDvjo3bu7vKREdjFbYKvWNgrEWENuprMbF17Q== @@ -17912,7 +17756,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.13, 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.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== @@ -23127,7 +22971,7 @@ resolve-url@^0.2.1: resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.3.2, resolve@^1.9.0: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.9.0: version "1.20.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== From bc9d62f4f7b452141b383ad00124ed9ba2c1c3e0 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Thu, 8 Apr 2021 18:38:39 +0200 Subject: [PATCH 099/395] Create a new method to check the configuration of a techdocs publisher to not crash the application on errors Signed-off-by: Dominik Henneke --- .changeset/fluffy-lies-complain.md | 18 ++ .../__mocks__/@google-cloud/storage.ts | 10 +- packages/techdocs-common/__mocks__/aws-sdk.ts | 14 +- .../techdocs-common/__mocks__/pkgcloud.ts | 15 +- .../src/stages/publish/awsS3.test.ts | 41 ++- .../src/stages/publish/awsS3.ts | 62 ++-- .../stages/publish/azureBlobStorage.test.ts | 264 +++++++----------- .../src/stages/publish/azureBlobStorage.ts | 63 +++-- .../src/stages/publish/googleStorage.test.ts | 31 +- .../src/stages/publish/googleStorage.ts | 54 ++-- .../src/stages/publish/local.ts | 7 + .../src/stages/publish/openStackSwift.test.ts | 45 ++- .../src/stages/publish/openStackSwift.ts | 59 ++-- .../src/stages/publish/publish.ts | 14 +- .../src/stages/publish/types.ts | 16 ++ 15 files changed, 423 insertions(+), 290 deletions(-) create mode 100644 .changeset/fluffy-lies-complain.md diff --git a/.changeset/fluffy-lies-complain.md b/.changeset/fluffy-lies-complain.md new file mode 100644 index 0000000000..addffc2baa --- /dev/null +++ b/.changeset/fluffy-lies-complain.md @@ -0,0 +1,18 @@ +--- +'@backstage/techdocs-common': patch +--- + +Move the sanity checks of the publisher configurations to a dedicated `PublisherBase#validateConfiguration()` method instead of throwing an error when doing `Publisher.fromConfig(...)`. +If you want to preserve this check in your application, use the following code: + +```ts +const publisher = await Publisher.fromConfig(config, { + logger, + discovery, +}); + +const validation = await publisher.validateConfiguration(); +if (!validation.isValid) { + throw new Error('Invalid TechDocs publisher configuration'); +} +``` diff --git a/packages/techdocs-common/__mocks__/@google-cloud/storage.ts b/packages/techdocs-common/__mocks__/@google-cloud/storage.ts index 264852d31c..f8d0368f27 100644 --- a/packages/techdocs-common/__mocks__/@google-cloud/storage.ts +++ b/packages/techdocs-common/__mocks__/@google-cloud/storage.ts @@ -81,10 +81,12 @@ class Bucket { this.bucketName = bucketName; } - getMetadata() { - return new Promise(resolve => { - resolve(''); - }); + async getMetadata() { + if (this.bucketName === 'errorBucket') { + throw Error('Bucket does not exist'); + } + + return ''; } upload(source: string, { destination }) { diff --git a/packages/techdocs-common/__mocks__/aws-sdk.ts b/packages/techdocs-common/__mocks__/aws-sdk.ts index 363662c63c..eb15a218ab 100644 --- a/packages/techdocs-common/__mocks__/aws-sdk.ts +++ b/packages/techdocs-common/__mocks__/aws-sdk.ts @@ -80,10 +80,16 @@ export class S3 { }; } - headBucket() { - return new Promise(resolve => { - resolve(''); - }); + headBucket({ Bucket }) { + return { + promise: async () => { + if (Bucket === 'errorBucket') { + throw new Error('Bucket does not exist'); + } + + return {}; + }, + }; } upload({ Key }: { Key: string }) { diff --git a/packages/techdocs-common/__mocks__/pkgcloud.ts b/packages/techdocs-common/__mocks__/pkgcloud.ts index 5d9f81cda0..dca86238e4 100644 --- a/packages/techdocs-common/__mocks__/pkgcloud.ts +++ b/packages/techdocs-common/__mocks__/pkgcloud.ts @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { EventEmitter } from 'events'; import fs from 'fs-extra'; import os from 'os'; import path from 'path'; -import { EventEmitter } from 'events'; +import { ClientError } from 'pkgcloud'; const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; @@ -37,12 +38,11 @@ class PkgCloudStorageClient { getFile( containerName: string, file: string, - callback: (err: any, file: string) => any, + callback: (err: any, file: any) => any, ) { checkFileExists(file).then(res => { if (!res) { - callback('File does not exist', file); - throw new Error('File does not exist'); + callback('File does not exist', undefined); } else { callback(undefined, 'success'); } @@ -51,13 +51,12 @@ class PkgCloudStorageClient { getContainer( containerName: string, - callback: (err: string, container: string) => any, + callback: (err: ClientError, container: any) => any, ) { if (containerName !== 'mock') { - callback('Container does not exist', containerName); - throw new Error('Container does not exist'); + callback(new Error('Container does not exist'), undefined); } else { - callback('Container does not exist', 'success'); + callback(undefined, 'success'); } } diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index d3281c2645..b0000b6464 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { getVoidLogger } from '@backstage/backend-common'; import { Entity, - EntityName, ENTITY_DEFAULT_NAMESPACE, + EntityName, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import mockFs from 'mock-fs'; import os from 'os'; import path from 'path'; -import * as winston from 'winston'; import { AwsS3Publish } from './awsS3'; import { PublisherBase, TechDocsMetadata } from './types'; @@ -59,9 +59,7 @@ const getEntityRootDir = (entity: Entity) => { return path.join(rootDir, namespace || ENTITY_DEFAULT_NAMESPACE, kind, name); }; -const logger = winston.createLogger(); -jest.spyOn(logger, 'info').mockReturnValue(logger); -jest.spyOn(logger, 'error').mockReturnValue(logger); +const logger = getVoidLogger(); let publisher: PublisherBase; @@ -87,6 +85,39 @@ beforeEach(() => { }); describe('AwsS3Publish', () => { + describe('validateConfiguration', () => { + it('should validate correct config', async () => { + expect(await publisher.validateConfiguration()).toEqual({ + isValid: true, + }); + }); + + it('should reject incorrect config', async () => { + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'awsS3', + awsS3: { + credentials: { + accessKeyId: 'accessKeyId', + secretAccessKey: 'secretAccessKey', + }, + // this bucket name will throw an error + bucketName: 'errorBucket', + }, + }, + }, + }); + + const errorPublisher = AwsS3Publish.fromConfig(mockConfig, logger); + + expect(await errorPublisher.validateConfiguration()).toEqual({ + isValid: false, + }); + }); + }); + describe('publish', () => { beforeEach(() => { const entity = createMockEntity(); diff --git a/packages/techdocs-common/src/stages/publish/awsS3.ts b/packages/techdocs-common/src/stages/publish/awsS3.ts index c4c39898f4..77bb771fb6 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.ts @@ -17,16 +17,21 @@ import { Entity, EntityName } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import aws, { Credentials } from 'aws-sdk'; import { ManagedUpload } from 'aws-sdk/clients/s3'; +import { CredentialsOptions } from 'aws-sdk/lib/credentials'; import express from 'express'; import fs from 'fs-extra'; import JSON5 from 'json5'; import createLimiter from 'p-limit'; -import { CredentialsOptions } from 'aws-sdk/lib/credentials'; import path from 'path'; import { Readable } from 'stream'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; -import { PublisherBase, PublishRequest, TechDocsMetadata } from './types'; +import { + ConfigurationValidationResponse, + PublisherBase, + PublishRequest, + TechDocsMetadata, +} from './types'; const streamToBuffer = (stream: Readable): Promise => { return new Promise((resolve, reject) => { @@ -81,30 +86,6 @@ export class AwsS3Publish implements PublisherBase { ...(endpoint && { endpoint }), }); - // Check if the defined bucket exists. Being able to connect means the configuration is good - // and the storage client will work. - storageClient.headBucket( - { - Bucket: bucketName, - }, - err => { - if (err) { - logger.error( - `Could not retrieve metadata about the AWS S3 bucket ${bucketName}. ` + - 'Make sure the bucket exists. Also make sure that authentication is setup either by ' + - 'explicitly defining credentials and region in techdocs.publisher.awsS3 in app config or ' + - 'by using environment variables. Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', - ); - logger.error(`from AWS client library: ${err.message}`); - throw new Error(); - } else { - logger.info( - `Successfully connected to the AWS S3 bucket ${bucketName}.`, - ); - } - }, - ); - return new AwsS3Publish(storageClient, bucketName, logger); } @@ -149,6 +130,35 @@ export class AwsS3Publish implements PublisherBase { this.logger = logger; } + /** + * Check if the defined bucket exists. Being able to connect means the configuration is good + * and the storage client will work. + */ + async validateConfiguration(): Promise { + try { + await this.storageClient + .headBucket({ Bucket: this.bucketName }) + .promise(); + + this.logger.info( + `Successfully connected to the AWS S3 bucket ${this.bucketName}.`, + ); + + return { isValid: true }; + } catch (error) { + this.logger.error( + `Could not retrieve metadata about the AWS S3 bucket ${this.bucketName}. ` + + 'Make sure the bucket exists. Also make sure that authentication is setup either by ' + + 'explicitly defining credentials and region in techdocs.publisher.awsS3 in app config or ' + + 'by using environment variables. Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', + ); + this.logger.error(`from AWS client library`, error); + return { + isValid: false, + }; + } + } + /** * Upload all the files from the generated `directory` to the S3 bucket. * Directory structure used in the bucket is - entityNamespace/entityKind/entityName/index.html diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts index 9442fb0e37..b67e47c675 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts @@ -16,8 +16,8 @@ import { getVoidLogger } from '@backstage/backend-common'; import { Entity, - EntityName, ENTITY_DEFAULT_NAMESPACE, + EntityName, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import mockFs from 'mock-fs'; @@ -59,12 +59,9 @@ const getEntityRootDir = (entity: Entity) => { return path.join(rootDir, namespace || ENTITY_DEFAULT_NAMESPACE, kind, name); }; -function createLogger() { - const logger = getVoidLogger(); - jest.spyOn(logger, 'info').mockReturnValue(logger); - jest.spyOn(logger, 'error').mockReturnValue(logger); - return logger; -} +const logger = getVoidLogger(); +jest.spyOn(logger, 'info').mockReturnValue(logger); +jest.spyOn(logger, 'error').mockReturnValue(logger); let publisher: PublisherBase; beforeEach(async () => { @@ -85,13 +82,51 @@ beforeEach(async () => { }, }); - publisher = await AzureBlobStoragePublish.fromConfig( - mockConfig, - createLogger(), - ); + publisher = AzureBlobStoragePublish.fromConfig(mockConfig, logger); }); describe('publishing with valid credentials', () => { + describe('validateConfiguration', () => { + it('should validate correct config', async () => { + expect(await publisher.validateConfiguration()).toEqual({ + isValid: true, + }); + }); + + it('should reject incorrect config', async () => { + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'azureBlobStorage', + azureBlobStorage: { + credentials: { + accountName: 'accountName', + accountKey: 'accountKey', + }, + containerName: 'bad_container', + }, + }, + }, + }); + + const errorPublisher = await AzureBlobStoragePublish.fromConfig( + mockConfig, + logger, + ); + + expect(await errorPublisher.validateConfiguration()).toEqual({ + isValid: false, + }); + + expect(logger.error).toHaveBeenCalledWith( + expect.stringContaining( + `Could not retrieve metadata about the Azure Blob Storage container bad_container.`, + ), + ); + }); + }); + describe('publish', () => { beforeEach(() => { const entity = createMockEntity(); @@ -151,6 +186,60 @@ describe('publishing with valid credentials', () => { }); mockFs.restore(); }); + + it('reports an error when bad account credentials', async () => { + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'azureBlobStorage', + azureBlobStorage: { + credentials: { + accountName: 'failupload', + accountKey: 'accountKey', + }, + containerName: 'containerName', + }, + }, + }, + }); + + publisher = await AzureBlobStoragePublish.fromConfig(mockConfig, logger); + + const entity = createMockEntity(); + const entityRootDir = getEntityRootDir(entity); + + mockFs({ + [entityRootDir]: { + 'index.html': '', + }, + }); + + let error; + try { + await publisher.publish({ + entity, + directory: entityRootDir, + }); + } catch (e) { + error = e; + } + + expect(error.message).toContain( + `Unable to upload file(s) to Azure Blob Storage.`, + ); + + expect(logger.error).toHaveBeenCalledWith( + expect.stringContaining( + `Unable to upload file(s) to Azure Blob Storage. Error: Upload failed for ${path.join( + entityRootDir, + 'index.html', + )} with status code 500`, + ), + ); + + mockFs.restore(); + }); }); describe('hasDocsBeenGenerated', () => { @@ -243,156 +332,3 @@ describe('publishing with valid credentials', () => { }); }); }); - -describe('error reporting', () => { - it('reports an error when unable to read container properties', async () => { - const mockConfig = new ConfigReader({ - techdocs: { - requestUrl: 'http://localhost:7000', - publisher: { - type: 'azureBlobStorage', - azureBlobStorage: { - credentials: { - accountName: 'accountName', - }, - containerName: 'bad_container', - }, - }, - }, - }); - - const logger = createLogger(); - - let error; - try { - publisher = await AzureBlobStoragePublish.fromConfig(mockConfig, logger); - } catch (e) { - error = e; - } - - expect(error).toBeInstanceOf(Error); - - expect(logger.error).toHaveBeenCalledWith( - expect.stringContaining( - `Could not retrieve metadata about the Azure Blob Storage container bad_container.`, - ), - ); - }); - - it('reports an error when bad account credentials', async () => { - const mockConfig = new ConfigReader({ - techdocs: { - requestUrl: 'http://localhost:7000', - publisher: { - type: 'azureBlobStorage', - azureBlobStorage: { - credentials: { - accountName: 'failupload', - accountKey: 'accountKey', - }, - containerName: 'containerName', - }, - }, - }, - }); - - const logger = createLogger(); - - publisher = await AzureBlobStoragePublish.fromConfig(mockConfig, logger); - - const entity = createMockEntity(); - const entityRootDir = getEntityRootDir(entity); - - mockFs({ - [entityRootDir]: { - 'index.html': '', - }, - }); - - let error; - try { - await publisher.publish({ - entity, - directory: entityRootDir, - }); - } catch (e) { - error = e; - } - - expect(error.message).toContain( - `Unable to upload file(s) to Azure Blob Storage.`, - ); - - expect(logger.error).toHaveBeenCalledWith( - expect.stringContaining( - `Unable to upload file(s) to Azure Blob Storage. Error: Upload failed for ${path.join( - entityRootDir, - 'index.html', - )} with status code 500`, - ), - ); - - mockFs.restore(); - }); - - describe('fetchTechDocsMetadata', () => { - it('should return tech docs metadata', async () => { - const entityNameMock = createMockEntityName(); - const entity = createMockEntity(); - const entityRootDir = getEntityRootDir(entity); - - mockFs({ - [entityRootDir]: { - 'techdocs_metadata.json': - '{"site_name": "backstage", "site_description": "site_content", "etag": "etag"}', - }, - }); - const expectedMetadata: TechDocsMetadata = { - site_name: 'backstage', - site_description: 'site_content', - etag: 'etag', - }; - expect( - await publisher.fetchTechDocsMetadata(entityNameMock), - ).toStrictEqual(expectedMetadata); - mockFs.restore(); - }); - - it('should return tech docs metadata when json encoded with single quotes', async () => { - const entityNameMock = createMockEntityName(); - const entity = createMockEntity(); - const entityRootDir = getEntityRootDir(entity); - - mockFs({ - [entityRootDir]: { - 'techdocs_metadata.json': `{'site_name': 'backstage', 'site_description': 'site_content', 'etag': 'etag'}`, - }, - }); - - const expectedMetadata: TechDocsMetadata = { - site_name: 'backstage', - site_description: 'site_content', - etag: 'etag', - }; - expect( - await publisher.fetchTechDocsMetadata(entityNameMock), - ).toStrictEqual(expectedMetadata); - mockFs.restore(); - }); - - it('should return an error if the techdocs_metadata.json file is not present', async () => { - const entityNameMock = createMockEntityName(); - - let error; - try { - await publisher.fetchTechDocsMetadata(entityNameMock); - } catch (e) { - error = e; - } - - expect(error.message).toEqual( - expect.stringContaining('TechDocs metadata fetch'), - ); - }); - }); -}); diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts index 155d14fbb5..6ecc2b76cc 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts @@ -26,16 +26,18 @@ import limiterFactory from 'p-limit'; import { default as path, default as platformPath } from 'path'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; -import { PublisherBase, PublishRequest, TechDocsMetadata } from './types'; +import { + ConfigurationValidationResponse, + PublisherBase, + PublishRequest, + TechDocsMetadata, +} from './types'; // The number of batches that may be ongoing at the same time. const BATCH_CONCURRENCY = 3; export class AzureBlobStoragePublish implements PublisherBase { - static async fromConfig( - config: Config, - logger: Logger, - ): Promise { + static fromConfig(config: Config, logger: Logger): PublisherBase { let containerName = ''; try { containerName = config.getString( @@ -78,26 +80,6 @@ export class AzureBlobStoragePublish implements PublisherBase { credential, ); - try { - const response = await storageClient - .getContainerClient(containerName) - .getProperties(); - - if (response._response.status >= 400) { - throw new Error( - `Failed to retrieve metadata from ${response._response.request.url} with status code ${response._response.status}.`, - ); - } - } catch (e) { - logger.error( - `Could not retrieve metadata about the Azure Blob Storage container ${containerName}. ` + - 'Make sure that the Azure project and container exist and the access key is setup correctly ' + - 'techdocs.publisher.azureBlobStorage.credentials defined in app config has correct permissions. ' + - 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', - ); - throw new Error(`from Azure Blob Storage client library: ${e.message}`); - } - return new AzureBlobStoragePublish(storageClient, containerName, logger); } @@ -111,6 +93,37 @@ export class AzureBlobStoragePublish implements PublisherBase { this.logger = logger; } + async validateConfiguration(): Promise { + try { + const response = await this.storageClient + .getContainerClient(this.containerName) + .getProperties(); + + if (response._response.status === 200) { + return { + isValid: true, + }; + } + + if (response._response.status >= 400) { + this.logger.error( + `Failed to retrieve metadata from ${response._response.request.url} with status code ${response._response.status}.`, + ); + } + } catch (e) { + this.logger.error(`from Azure Blob Storage client library: ${e.message}`); + } + + this.logger.error( + `Could not retrieve metadata about the Azure Blob Storage container ${this.containerName}. ` + + 'Make sure that the Azure project and container exist and the access key is setup correctly ' + + 'techdocs.publisher.azureBlobStorage.credentials defined in app config has correct permissions. ' + + 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', + ); + + return { isValid: false }; + } + /** * Upload all the files from the generated `directory` to the Azure Blob Storage container. * Directory structure used in the container is - entityNamespace/entityKind/entityName/index.html diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index 07bc5c06b9..c8cbcb0fda 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -16,8 +16,8 @@ import { getVoidLogger } from '@backstage/backend-common'; import { Entity, - EntityName, ENTITY_DEFAULT_NAMESPACE, + EntityName, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import mockFs from 'mock-fs'; @@ -83,6 +83,35 @@ beforeEach(async () => { }); describe('GoogleGCSPublish', () => { + describe('validateConfiguration', () => { + it('should validate correct config', async () => { + expect(await publisher.validateConfiguration()).toEqual({ + isValid: true, + }); + }); + + it('should reject incorrect config', async () => { + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'googleGcs', + googleGcs: { + credentials: '{}', + bucketName: 'errorBucket', + }, + }, + }, + }); + + const errorPublisher = GoogleGCSPublish.fromConfig(mockConfig, logger); + + expect(await errorPublisher.validateConfiguration()).toEqual({ + isValid: false, + }); + }); + }); + describe('publish', () => { beforeEach(() => { const entity = createMockEntity(); diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index 12ecf45b2d..047518d43f 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -26,13 +26,15 @@ import createLimiter from 'p-limit'; import path from 'path'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; -import { PublisherBase, PublishRequest, TechDocsMetadata } from './types'; +import { + ConfigurationValidationResponse, + PublisherBase, + PublishRequest, + TechDocsMetadata, +} from './types'; export class GoogleGCSPublish implements PublisherBase { - static async fromConfig( - config: Config, - logger: Logger, - ): Promise { + static fromConfig(config: Config, logger: Logger): PublisherBase { let bucketName = ''; try { bucketName = config.getString('techdocs.publisher.googleGcs.bucketName'); @@ -65,21 +67,6 @@ export class GoogleGCSPublish implements PublisherBase { }), }); - // Check if the defined bucket exists. Being able to connect means the configuration is good - // and the storage client will work. - try { - await storageClient.bucket(bucketName).getMetadata(); - logger.info(`Successfully connected to the GCS bucket ${bucketName}.`); - } catch (err) { - logger.error( - `Could not retrieve metadata about the GCS bucket ${bucketName}. ` + - 'Make sure the bucket exists. Also make sure that authentication is setup either by explicitly defining ' + - 'techdocs.publisher.googleGcs.credentials in app config or by using environment variables. ' + - 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', - ); - throw new Error(err.message); - } - return new GoogleGCSPublish(storageClient, bucketName, logger); } @@ -93,6 +80,33 @@ export class GoogleGCSPublish implements PublisherBase { this.logger = logger; } + /** + * Check if the defined bucket exists. Being able to connect means the configuration is good + * and the storage client will work. + */ + async validateConfiguration(): Promise { + try { + await this.storageClient.bucket(this.bucketName).getMetadata(); + this.logger.info( + `Successfully connected to the GCS bucket ${this.bucketName}.`, + ); + + return { + isValid: true, + }; + } catch (err) { + this.logger.error( + `Could not retrieve metadata about the GCS bucket ${this.bucketName}. ` + + 'Make sure the bucket exists. Also make sure that authentication is setup either by explicitly defining ' + + 'techdocs.publisher.googleGcs.credentials in app config or by using environment variables. ' + + 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', + ); + this.logger.error(`from GCS client library: ${err.message}`); + + return { isValid: false }; + } + } + /** * Upload all the files from the generated `directory` to the GCS bucket. * Directory structure used in the bucket is - entityNamespace/entityKind/entityName/index.html diff --git a/packages/techdocs-common/src/stages/publish/local.ts b/packages/techdocs-common/src/stages/publish/local.ts index 3088c1a695..f641c63031 100644 --- a/packages/techdocs-common/src/stages/publish/local.ts +++ b/packages/techdocs-common/src/stages/publish/local.ts @@ -25,6 +25,7 @@ import os from 'os'; import path from 'path'; import { Logger } from 'winston'; import { + ConfigurationValidationResponse, PublisherBase, PublishRequest, PublishResponse, @@ -65,6 +66,12 @@ export class LocalPublish implements PublisherBase { this.discovery = discovery; } + async validateConfiguration(): Promise { + return { + isValid: true, + }; + } + publish({ entity, directory }: PublishRequest): Promise { const entityNamespace = entity.metadata.namespace ?? 'default'; diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts index f3b788916f..67de30245b 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { getVoidLogger } from '@backstage/backend-common'; import { Entity, - EntityName, ENTITY_DEFAULT_NAMESPACE, + EntityName, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import mockFs from 'mock-fs'; import os from 'os'; import path from 'path'; -import * as winston from 'winston'; import { OpenStackSwiftPublish } from './openStackSwift'; import { PublisherBase, TechDocsMetadata } from './types'; @@ -59,9 +59,7 @@ const getEntityRootDir = (entity: Entity) => { return path.join(rootDir, namespace || ENTITY_DEFAULT_NAMESPACE, kind, name); }; -const logger = winston.createLogger(); -jest.spyOn(logger, 'info').mockReturnValue(logger); -jest.spyOn(logger, 'error').mockReturnValue(logger); +const logger = getVoidLogger(); let publisher: PublisherBase; @@ -89,6 +87,43 @@ beforeEach(() => { }); describe('OpenStackSwiftPublish', () => { + describe('validateConfiguration', () => { + it('should validate correct config', async () => { + expect(await publisher.validateConfiguration()).toEqual({ + isValid: true, + }); + }); + + it('should reject incorrect config', async () => { + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'openStackSwift', + openStackSwift: { + credentials: { + username: 'mockuser', + password: 'verystrongpass', + }, + authUrl: 'mockauthurl', + region: 'mockregion', + containerName: 'errorBucket', + }, + }, + }, + }); + + const errorPublisher = OpenStackSwiftPublish.fromConfig( + mockConfig, + logger, + ); + + expect(await errorPublisher.validateConfiguration()).toEqual({ + isValid: false, + }); + }); + }); + describe('publish', () => { beforeEach(() => { const entity = createMockEntity(); diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.ts index 0e60bc5796..ca05cf2ce5 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.ts @@ -15,16 +15,21 @@ */ import { Entity, EntityName } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { storage } from 'pkgcloud'; import express from 'express'; import fs from 'fs-extra'; import JSON5 from 'json5'; import createLimiter from 'p-limit'; import path from 'path'; +import { storage } from 'pkgcloud'; import { Readable } from 'stream'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; -import { PublisherBase, PublishRequest, TechDocsMetadata } from './types'; +import { + ConfigurationValidationResponse, + PublisherBase, + PublishRequest, + TechDocsMetadata, +} from './types'; const streamToBuffer = (stream: Readable): Promise => { return new Promise((resolve, reject) => { @@ -70,25 +75,6 @@ export class OpenStackSwiftPublish implements PublisherBase { region: openStackSwiftConfig.getString('region'), }); - // Check if the defined container exists. Being able to connect means the configuration is good - // and the storage client will work. - storageClient.getContainer(containerName, (err, container) => { - if (container) { - logger.info( - `Successfully connected to the OpenStack Swift container ${containerName}.`, - ); - } else { - logger.error( - `Could not retrieve metadata about the OpenStack Swift container ${containerName}. ` + - 'Make sure the container exists. Also make sure that authentication is setup either by ' + - 'explicitly defining credentials and region in techdocs.publisher.openStackSwift in app config or ' + - 'by using environment variables. Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', - ); - - logger.error(`from OpenStack client library: ${err.message}`); - } - }); - return new OpenStackSwiftPublish(storageClient, containerName, logger); } @@ -102,6 +88,37 @@ export class OpenStackSwiftPublish implements PublisherBase { this.logger = logger; } + /* + * Check if the defined container exists. Being able to connect means the configuration is good + * and the storage client will work. + */ + validateConfiguration(): Promise { + return new Promise(resolve => { + this.storageClient.getContainer(this.containerName, (err, container) => { + if (container) { + this.logger.info( + `Successfully connected to the OpenStack Swift container ${this.containerName}.`, + ); + resolve({ + isValid: true, + }); + } else { + this.logger.error( + `Could not retrieve metadata about the OpenStack Swift container ${this.containerName}. ` + + 'Make sure the container exists. Also make sure that authentication is setup either by ' + + 'explicitly defining credentials and region in techdocs.publisher.openStackSwift in app config or ' + + 'by using environment variables. Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', + ); + + this.logger.error(`from OpenStack client library: ${err.message}`); + resolve({ + isValid: false, + }); + } + }); + }); + } + /** * Upload all the files from the generated `directory` to the OpenStack Swift container. * Directory structure used in the bucket is - entityNamespace/entityKind/entityName/index.html diff --git a/packages/techdocs-common/src/stages/publish/publish.ts b/packages/techdocs-common/src/stages/publish/publish.ts index f70a5f7626..909a4092ac 100644 --- a/packages/techdocs-common/src/stages/publish/publish.ts +++ b/packages/techdocs-common/src/stages/publish/publish.ts @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Logger } from 'winston'; -import { Config } from '@backstage/config'; -import { PluginEndpointDiscovery } from '@backstage/backend-common'; -import { PublisherType, PublisherBase } from './types'; -import { LocalPublish } from './local'; -import { GoogleGCSPublish } from './googleStorage'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { Config } from '@backstage/config'; +import { Logger } from 'winston'; import { AwsS3Publish } from './awsS3'; import { AzureBlobStoragePublish } from './azureBlobStorage'; +import { GoogleGCSPublish } from './googleStorage'; +import { LocalPublish } from './local'; import { OpenStackSwiftPublish } from './openStackSwift'; +import { PublisherBase, PublisherType } from './types'; type factoryOptions = { logger: Logger; @@ -45,7 +45,7 @@ export class Publisher { switch (publisherType) { case 'googleGcs': logger.info('Creating Google Storage Bucket publisher for TechDocs'); - return await GoogleGCSPublish.fromConfig(config, logger); + return GoogleGCSPublish.fromConfig(config, logger); case 'awsS3': logger.info('Creating AWS S3 Bucket publisher for TechDocs'); return AwsS3Publish.fromConfig(config, logger); diff --git a/packages/techdocs-common/src/stages/publish/types.ts b/packages/techdocs-common/src/stages/publish/types.ts index 83fee55133..a4a02ae285 100644 --- a/packages/techdocs-common/src/stages/publish/types.ts +++ b/packages/techdocs-common/src/stages/publish/types.ts @@ -37,6 +37,14 @@ export type PublishResponse = { remoteUrl?: string; } | void; +/** + * Result for the validation check. + */ +export type ConfigurationValidationResponse = { + /** Tells whether the configuration is valid. */ + isValid: boolean; +}; + /** * Type to hold metadata found in techdocs_metadata.json and associated with each site * @param etag ETag of the resource used to generate the site. Usually the latest commit sha of the source repository. @@ -53,6 +61,14 @@ export type TechDocsMetadata = { * It also provides APIs to communicate with the storage service. */ export interface PublisherBase { + /** + * Check if the configuration is valid. This check tries to perform certain checks to see if the + * publisher is configured correctly and can be used to publish or read documentations. + * The different implementations might e.g. use the provided service credentials to access the + * target or check if a folder/bucket is available. + */ + validateConfiguration(): Promise; + /** * Store the generated static files onto a storage service (either local filesystem or external service). * From d541d9fd07e7e2b31488472b4bd8718b0163b941 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 12 Apr 2021 12:02:15 +0200 Subject: [PATCH 100/395] Include review comments Signed-off-by: Dominik Henneke --- .changeset/fluffy-lies-complain.md | 39 ++++++++++++++++--- packages/backend/src/plugins/techdocs.ts | 3 ++ .../packages/backend/src/plugins/techdocs.ts | 3 ++ .../src/stages/publish/awsS3.test.ts | 10 ++--- .../src/stages/publish/awsS3.ts | 8 ++-- .../stages/publish/azureBlobStorage.test.ts | 10 ++--- .../src/stages/publish/azureBlobStorage.ts | 8 ++-- .../src/stages/publish/googleStorage.test.ts | 10 ++--- .../src/stages/publish/googleStorage.ts | 8 ++-- .../src/stages/publish/local.ts | 6 +-- .../src/stages/publish/openStackSwift.test.ts | 10 ++--- .../src/stages/publish/openStackSwift.ts | 8 ++-- .../src/stages/publish/types.ts | 10 ++--- 13 files changed, 84 insertions(+), 49 deletions(-) diff --git a/.changeset/fluffy-lies-complain.md b/.changeset/fluffy-lies-complain.md index addffc2baa..b770928e1c 100644 --- a/.changeset/fluffy-lies-complain.md +++ b/.changeset/fluffy-lies-complain.md @@ -1,9 +1,38 @@ --- -'@backstage/techdocs-common': patch +'@backstage/techdocs-common': minor --- -Move the sanity checks of the publisher configurations to a dedicated `PublisherBase#validateConfiguration()` method instead of throwing an error when doing `Publisher.fromConfig(...)`. -If you want to preserve this check in your application, use the following code: +Move the sanity checks of the publisher configurations to a dedicated `PublisherBase#getReadiness()` method instead of throwing an error when doing `Publisher.fromConfig(...)`. +You should include the check when your backend to get early feedback about a potential misconfiguration: + +```diff + // packages/backend/src/plugins/techdocs.ts + + export default async function createPlugin({ + logger, + config, + discovery, + reader, + }: PluginEnvironment): Promise { + // ... + + const publisher = await Publisher.fromConfig(config, { + logger, + discovery, + }) + ++ // checks if the publisher is working and logs the result ++ await publisher.getReadiness(); + + // Docker client (conditionally) used by the generators, based on techdocs.generators config. + const dockerClient = new Docker(); + + // ... +} +``` + +If you want to crash your application on invalid configurations, you can throw an `Error` to preserve the old behavior. +Please be aware that this is not the recommended for the use in a Backstage backend but might be helpful in CLI tools such as the `techdocs-cli`. ```ts const publisher = await Publisher.fromConfig(config, { @@ -11,8 +40,8 @@ const publisher = await Publisher.fromConfig(config, { discovery, }); -const validation = await publisher.validateConfiguration(); -if (!validation.isValid) { +const ready = await publisher.getReadiness(); +if (!ready.isAvailable) { throw new Error('Invalid TechDocs publisher configuration'); } ``` diff --git a/packages/backend/src/plugins/techdocs.ts b/packages/backend/src/plugins/techdocs.ts index 9883f2afbc..d0387cd15d 100644 --- a/packages/backend/src/plugins/techdocs.ts +++ b/packages/backend/src/plugins/techdocs.ts @@ -48,6 +48,9 @@ export default async function createPlugin({ discovery, }); + // checks if the publisher is working and logs the result + await publisher.getReadiness(); + // Docker client (conditionally) used by the generators, based on techdocs.generators config. const dockerClient = new Docker(); diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts index 0ba08cefaf..231a7e7fd7 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts @@ -34,6 +34,9 @@ export default async function createPlugin({ discovery, }); + // checks if the publisher is working and logs the result + await publisher.getReadiness(); + // Docker client (conditionally) used by the generators, based on techdocs.generators config. const dockerClient = new Docker(); diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index b0000b6464..15da3b7cfc 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -85,10 +85,10 @@ beforeEach(() => { }); describe('AwsS3Publish', () => { - describe('validateConfiguration', () => { + describe('getReadiness', () => { it('should validate correct config', async () => { - expect(await publisher.validateConfiguration()).toEqual({ - isValid: true, + expect(await publisher.getReadiness()).toEqual({ + isAvailable: true, }); }); @@ -112,8 +112,8 @@ describe('AwsS3Publish', () => { const errorPublisher = AwsS3Publish.fromConfig(mockConfig, logger); - expect(await errorPublisher.validateConfiguration()).toEqual({ - isValid: false, + expect(await errorPublisher.getReadiness()).toEqual({ + isAvailable: false, }); }); }); diff --git a/packages/techdocs-common/src/stages/publish/awsS3.ts b/packages/techdocs-common/src/stages/publish/awsS3.ts index 77bb771fb6..9c6684fdca 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.ts @@ -27,9 +27,9 @@ import { Readable } from 'stream'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; import { - ConfigurationValidationResponse, PublisherBase, PublishRequest, + ReadinessResponse, TechDocsMetadata, } from './types'; @@ -134,7 +134,7 @@ export class AwsS3Publish implements PublisherBase { * Check if the defined bucket exists. Being able to connect means the configuration is good * and the storage client will work. */ - async validateConfiguration(): Promise { + async getReadiness(): Promise { try { await this.storageClient .headBucket({ Bucket: this.bucketName }) @@ -144,7 +144,7 @@ export class AwsS3Publish implements PublisherBase { `Successfully connected to the AWS S3 bucket ${this.bucketName}.`, ); - return { isValid: true }; + return { isAvailable: true }; } catch (error) { this.logger.error( `Could not retrieve metadata about the AWS S3 bucket ${this.bucketName}. ` + @@ -154,7 +154,7 @@ export class AwsS3Publish implements PublisherBase { ); this.logger.error(`from AWS client library`, error); return { - isValid: false, + isAvailable: false, }; } } diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts index b67e47c675..c431e924a8 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts @@ -86,10 +86,10 @@ beforeEach(async () => { }); describe('publishing with valid credentials', () => { - describe('validateConfiguration', () => { + describe('getReadiness', () => { it('should validate correct config', async () => { - expect(await publisher.validateConfiguration()).toEqual({ - isValid: true, + expect(await publisher.getReadiness()).toEqual({ + isAvailable: true, }); }); @@ -115,8 +115,8 @@ describe('publishing with valid credentials', () => { logger, ); - expect(await errorPublisher.validateConfiguration()).toEqual({ - isValid: false, + expect(await errorPublisher.getReadiness()).toEqual({ + isAvailable: false, }); expect(logger.error).toHaveBeenCalledWith( diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts index 6ecc2b76cc..1a823c3d19 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.ts @@ -27,9 +27,9 @@ import { default as path, default as platformPath } from 'path'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; import { - ConfigurationValidationResponse, PublisherBase, PublishRequest, + ReadinessResponse, TechDocsMetadata, } from './types'; @@ -93,7 +93,7 @@ export class AzureBlobStoragePublish implements PublisherBase { this.logger = logger; } - async validateConfiguration(): Promise { + async getReadiness(): Promise { try { const response = await this.storageClient .getContainerClient(this.containerName) @@ -101,7 +101,7 @@ export class AzureBlobStoragePublish implements PublisherBase { if (response._response.status === 200) { return { - isValid: true, + isAvailable: true, }; } @@ -121,7 +121,7 @@ export class AzureBlobStoragePublish implements PublisherBase { 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', ); - return { isValid: false }; + return { isAvailable: false }; } /** diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index c8cbcb0fda..7e580b16bc 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -83,10 +83,10 @@ beforeEach(async () => { }); describe('GoogleGCSPublish', () => { - describe('validateConfiguration', () => { + describe('getReadiness', () => { it('should validate correct config', async () => { - expect(await publisher.validateConfiguration()).toEqual({ - isValid: true, + expect(await publisher.getReadiness()).toEqual({ + isAvailable: true, }); }); @@ -106,8 +106,8 @@ describe('GoogleGCSPublish', () => { const errorPublisher = GoogleGCSPublish.fromConfig(mockConfig, logger); - expect(await errorPublisher.validateConfiguration()).toEqual({ - isValid: false, + expect(await errorPublisher.getReadiness()).toEqual({ + isAvailable: false, }); }); }); diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index 047518d43f..28fbb42ece 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -27,9 +27,9 @@ import path from 'path'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; import { - ConfigurationValidationResponse, PublisherBase, PublishRequest, + ReadinessResponse, TechDocsMetadata, } from './types'; @@ -84,7 +84,7 @@ export class GoogleGCSPublish implements PublisherBase { * Check if the defined bucket exists. Being able to connect means the configuration is good * and the storage client will work. */ - async validateConfiguration(): Promise { + async getReadiness(): Promise { try { await this.storageClient.bucket(this.bucketName).getMetadata(); this.logger.info( @@ -92,7 +92,7 @@ export class GoogleGCSPublish implements PublisherBase { ); return { - isValid: true, + isAvailable: true, }; } catch (err) { this.logger.error( @@ -103,7 +103,7 @@ export class GoogleGCSPublish implements PublisherBase { ); this.logger.error(`from GCS client library: ${err.message}`); - return { isValid: false }; + return { isAvailable: false }; } } diff --git a/packages/techdocs-common/src/stages/publish/local.ts b/packages/techdocs-common/src/stages/publish/local.ts index f641c63031..e09473cf60 100644 --- a/packages/techdocs-common/src/stages/publish/local.ts +++ b/packages/techdocs-common/src/stages/publish/local.ts @@ -25,10 +25,10 @@ import os from 'os'; import path from 'path'; import { Logger } from 'winston'; import { - ConfigurationValidationResponse, PublisherBase, PublishRequest, PublishResponse, + ReadinessResponse, TechDocsMetadata, } from './types'; @@ -66,9 +66,9 @@ export class LocalPublish implements PublisherBase { this.discovery = discovery; } - async validateConfiguration(): Promise { + async getReadiness(): Promise { return { - isValid: true, + isAvailable: true, }; } diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts index 67de30245b..6f0aacede0 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts @@ -87,10 +87,10 @@ beforeEach(() => { }); describe('OpenStackSwiftPublish', () => { - describe('validateConfiguration', () => { + describe('getReadiness', () => { it('should validate correct config', async () => { - expect(await publisher.validateConfiguration()).toEqual({ - isValid: true, + expect(await publisher.getReadiness()).toEqual({ + isAvailable: true, }); }); @@ -118,8 +118,8 @@ describe('OpenStackSwiftPublish', () => { logger, ); - expect(await errorPublisher.validateConfiguration()).toEqual({ - isValid: false, + expect(await errorPublisher.getReadiness()).toEqual({ + isAvailable: false, }); }); }); diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.ts index ca05cf2ce5..bff0055402 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.ts @@ -25,9 +25,9 @@ import { Readable } from 'stream'; import { Logger } from 'winston'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; import { - ConfigurationValidationResponse, PublisherBase, PublishRequest, + ReadinessResponse, TechDocsMetadata, } from './types'; @@ -92,7 +92,7 @@ export class OpenStackSwiftPublish implements PublisherBase { * Check if the defined container exists. Being able to connect means the configuration is good * and the storage client will work. */ - validateConfiguration(): Promise { + getReadiness(): Promise { return new Promise(resolve => { this.storageClient.getContainer(this.containerName, (err, container) => { if (container) { @@ -100,7 +100,7 @@ export class OpenStackSwiftPublish implements PublisherBase { `Successfully connected to the OpenStack Swift container ${this.containerName}.`, ); resolve({ - isValid: true, + isAvailable: true, }); } else { this.logger.error( @@ -112,7 +112,7 @@ export class OpenStackSwiftPublish implements PublisherBase { this.logger.error(`from OpenStack client library: ${err.message}`); resolve({ - isValid: false, + isAvailable: false, }); } }); diff --git a/packages/techdocs-common/src/stages/publish/types.ts b/packages/techdocs-common/src/stages/publish/types.ts index a4a02ae285..c2849b8e35 100644 --- a/packages/techdocs-common/src/stages/publish/types.ts +++ b/packages/techdocs-common/src/stages/publish/types.ts @@ -40,9 +40,9 @@ export type PublishResponse = { /** * Result for the validation check. */ -export type ConfigurationValidationResponse = { - /** Tells whether the configuration is valid. */ - isValid: boolean; +export type ReadinessResponse = { + /** If true, the publisher is able to interact with the backing storage. */ + isAvailable: boolean; }; /** @@ -62,12 +62,12 @@ export type TechDocsMetadata = { */ export interface PublisherBase { /** - * Check if the configuration is valid. This check tries to perform certain checks to see if the + * Check if the publisher is ready. This check tries to perform certain checks to see if the * publisher is configured correctly and can be used to publish or read documentations. * The different implementations might e.g. use the provided service credentials to access the * target or check if a folder/bucket is available. */ - validateConfiguration(): Promise; + getReadiness(): Promise; /** * Store the generated static files onto a storage service (either local filesystem or external service). From 18f7345a6c29dcfccef7df081b1708f2bf8f62ff Mon Sep 17 00:00:00 2001 From: David Tuite Date: Mon, 12 Apr 2021 19:11:35 +0100 Subject: [PATCH 101/395] Add borders to docs tables (#5281) --- .changeset/techdocs-dry-starfishes-carry.md | 5 +++++ plugins/techdocs/src/reader/components/Reader.tsx | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .changeset/techdocs-dry-starfishes-carry.md diff --git a/.changeset/techdocs-dry-starfishes-carry.md b/.changeset/techdocs-dry-starfishes-carry.md new file mode 100644 index 0000000000..f5841c6994 --- /dev/null +++ b/.changeset/techdocs-dry-starfishes-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Add borders to TechDocs tables and increase font size. Fixes #5264 and #5276. diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 67b39d0ef7..874ca5e018 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -162,6 +162,16 @@ export const Reader = ({ entityId, onReady }: Props) => { .md-typeset { font-size: 1rem; } .md-nav { font-size: 1rem; } .md-grid { max-width: 90vw; margin: 0 } + .md-typeset table:not([class]) { + font-size: 1rem; + border: 1px solid ${theme.palette.text.primary}; + border-bottom: none; + border-collapse: collapse; + } + .md-typeset table:not([class]) td, .md-typeset table:not([class]) th { + border-bottom: 1px solid ${theme.palette.text.primary}; + } + .md-typeset table:not([class]) th { font-weight: bold; } @media screen and (max-width: 76.1875em) { .md-nav { background-color: ${theme.palette.background.default}; @@ -221,6 +231,7 @@ export const Reader = ({ entityId, onReady }: Props) => { :host { --md-tasklist-icon: url('data:image/svg+xml;charset=utf-8,'); --md-tasklist-icon--checked: url('data:image/svg+xml;charset=utf-8,'); + } `, }), ]); From 695d5534f5a2f787c44f0b51ea49cbdb6331d44c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 04:18:41 +0000 Subject: [PATCH 102/395] chore(deps): bump @types/webpack-node-externals from 2.5.0 to 2.5.1 Bumps [@types/webpack-node-externals](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack-node-externals) from 2.5.0 to 2.5.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack-node-externals) Signed-off-by: dependabot[bot] --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7d4eda4f1c..8c0258711f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6852,11 +6852,11 @@ integrity sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw== "@types/webpack-node-externals@^2.5.0": - version "2.5.0" - resolved "https://registry.npmjs.org/@types/webpack-node-externals/-/webpack-node-externals-2.5.0.tgz#bcd161af84a4960416e5850e06931b35321c6654" - integrity sha512-KaWfhUQlpWknM/CMBKhV7i0vxX/N2xEy3WeaE500s4ZNxC4nLnKB+0F3gD3Fg+5octPq0nn8ZlfFR/P3dSkXpw== + version "2.5.1" + resolved "https://registry.npmjs.org/@types/webpack-node-externals/-/webpack-node-externals-2.5.1.tgz#0f00036bce0f405ceabc092e415b734059fe5505" + integrity sha512-Cwg6+FQogkImRMF5nu5bKsLoZlwNCzpEyvxIzJM0ZgkkuKP7TrmQ3suOvNKKG1O4luxXZroKGo0mMC5EN5gPBA== dependencies: - "@types/webpack" "*" + "@types/webpack" "^4" "@types/webpack-sources@*": version "0.1.6" From f1952337ce3577912a1bcb45cc01f8b1e58b4fc3 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Tue, 13 Apr 2021 10:14:00 +0200 Subject: [PATCH 103/395] Add changeset for create-app Signed-off-by: Dominik Henneke --- .changeset/yellow-snails-hang.md | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .changeset/yellow-snails-hang.md diff --git a/.changeset/yellow-snails-hang.md b/.changeset/yellow-snails-hang.md new file mode 100644 index 0000000000..e908a98aee --- /dev/null +++ b/.changeset/yellow-snails-hang.md @@ -0,0 +1,33 @@ +--- +'@backstage/create-app': patch +--- + +Due to a change in the techdocs publishers, they don't check if they are able to reach e.g. the configured S3 bucket anymore. +This can be added again by the following change. Note that the backend process will no longer exit when it is not reachable but will only emit an error log message. +You should include the check when your backend to get early feedback about a potential misconfiguration: + +```diff + // packages/backend/src/plugins/techdocs.ts + + export default async function createPlugin({ + logger, + config, + discovery, + reader, + }: PluginEnvironment): Promise { + // ... + + const publisher = await Publisher.fromConfig(config, { + logger, + discovery, + }) + ++ // checks if the publisher is working and logs the result ++ await publisher.getReadiness(); + + // Docker client (conditionally) used by the generators, based on techdocs.generators config. + const dockerClient = new Docker(); + + // ... +} +``` From 12390778ee4b27672088e4e421309fdb54cdb561 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Fri, 9 Apr 2021 14:25:03 +0200 Subject: [PATCH 104/395] Add Changeset Signed-off-by: blam --- .changeset/sour-dryers-sort.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sour-dryers-sort.md diff --git a/.changeset/sour-dryers-sort.md b/.changeset/sour-dryers-sort.md new file mode 100644 index 0000000000..ee15655e82 --- /dev/null +++ b/.changeset/sour-dryers-sort.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +chore(deps): bump @asyncapi/react-component from 0.19.2 to 0.22.3 From 06eb4b06e835d6970711949865ad2abc745bba7f Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 13 Apr 2021 10:54:10 +0200 Subject: [PATCH 105/395] chore: add deps word to stlyes Signed-off-by: blam --- .github/styles/vocab.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index b0bcf9c9f7..8d89012020 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -112,6 +112,7 @@ css dataflow deadnaming declaratively +deps destructured dev devops From 4d1617a3e67d05325fa7f1a3168f48ae25a72bc5 Mon Sep 17 00:00:00 2001 From: Pranava Shashank Pindi Date: Fri, 9 Apr 2021 00:49:13 +0530 Subject: [PATCH 106/395] Updated documentation for sonarcloud plugin For a new react developer working with backstage, he gets blocked while installing the sonarcloud plugin in backstage app. He faces the following [issue](https://github.com/backstage/backstage/issues/5141) after following the steps mentioned in the plugin [documentation](https://github.com/backstage/backstage/tree/master/plugins/sonarqube). Hence, this commit adds `yarn install` and `yarn tsc` commands to be run. Also, it adds additional information on how to set the SONARQUBE_AUTH_HEADER environmental header. Signed-off-by: pranava29 Signed-off-by: pranava29 --- plugins/sonarqube/README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/plugins/sonarqube/README.md b/plugins/sonarqube/README.md index 7afc9cc04a..f95a2c6151 100644 --- a/plugins/sonarqube/README.md +++ b/plugins/sonarqube/README.md @@ -71,8 +71,12 @@ proxy: allowedMethods: ['GET'] headers: Authorization: - # Content: 'Basic base64(":")' <-- note the trailing ':' - # Example: Basic bXktYXBpLWtleTo= + # Environmental variable: SONARQUBE_AUTH_HEADER + # Value: 'Basic base64(":")' + # Encode the ":" string using base64 encoder. + # Note the trailing colon (:) at the end of the token. + # Example environmental config: SONARQUBE_AUTH_HEADER=Basic bXktYXBpLWtleTo= + # Fetch the sonar-auth-token from https://sonarcloud.io/account/security/ $env: SONARQUBE_AUTH_HEADER sonarQube: @@ -81,7 +85,14 @@ sonarQube: 5. Get and provide `SONARQUBE_AUTH_HEADER` as env variable (https://sonarcloud.io/account/security or https://docs.sonarqube.org/latest/user-guide/user-token/) -6. Add the `sonarqube.org/project-key` annotation to your catalog-info.yaml file: +6. 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. ```yaml apiVersion: backstage.io/v1alpha1 From c2306f898d2634b2e791e55cb9667ea9318ca3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20A=CC=8Ahsberg?= Date: Mon, 12 Apr 2021 15:04:22 +0000 Subject: [PATCH 107/395] Externalize repository processing for BitbucketDiscoveryProcessor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathias Åhsberg --- .changeset/stale-carpets-poke.md | 30 ++ docs/integrations/bitbucket/discovery.md | 26 ++ .../BitbucketDiscoveryProcessor.test.ts | 350 +++++++++++------- .../processors/BitbucketDiscoveryProcessor.ts | 45 ++- .../BitbucketRepositoryParser.test.ts | 55 +++ .../bitbucket/BitbucketRepositoryParser.ts | 41 ++ .../ingestion/processors/bitbucket/client.ts | 9 + .../ingestion/processors/bitbucket/index.ts | 3 + .../ingestion/processors/bitbucket/types.ts | 28 ++ 9 files changed, 441 insertions(+), 146 deletions(-) create mode 100644 .changeset/stale-carpets-poke.md create mode 100644 plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts create mode 100644 plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts create mode 100644 plugins/catalog-backend/src/ingestion/processors/bitbucket/types.ts diff --git a/.changeset/stale-carpets-poke.md b/.changeset/stale-carpets-poke.md new file mode 100644 index 0000000000..4f39e57b71 --- /dev/null +++ b/.changeset/stale-carpets-poke.md @@ -0,0 +1,30 @@ +--- +'@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/docs/integrations/bitbucket/discovery.md b/docs/integrations/bitbucket/discovery.md index b24734abde..fadb7c9f06 100644 --- a/docs/integrations/bitbucket/discovery.md +++ b/docs/integrations/bitbucket/discovery.md @@ -39,3 +39,29 @@ The target is composed of four parts: - The path within each repository to find the catalog YAML file. This will usually be `/catalog-info.yaml` or a similar variation for catalog files stored in the root directory of each repository. + +## Custom repository processing + +The Bitbucket Discovery Processor will by default emit a location for each +matching repository for further processing by other processors. However, it is +possible to override this functionality and take full control of how each +matching repository is processed. + +`BitbucketDiscoveryProcessor.fromConfig` takes an optional parameter +`options.parser` where you can set your own parser to be used for each matched +repository. + +```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/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts index 5197549d85..73f4281a51 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts @@ -14,13 +14,15 @@ * limitations under the License. */ import { getVoidLogger } from '@backstage/backend-common'; -import { - BitbucketDiscoveryProcessor, - readBitbucketOrg, -} from './BitbucketDiscoveryProcessor'; +import { BitbucketDiscoveryProcessor } from './BitbucketDiscoveryProcessor'; import { ConfigReader } from '@backstage/config'; import { LocationSpec } from '@backstage/catalog-model'; -import { BitbucketClient, PagedResponse } from './bitbucket'; +import { + BitbucketClient, + BitbucketRepositoryParser, + PagedResponse, +} from './bitbucket'; +import { results } from './index'; function pagedResponse(values: any): PagedResponse { return { @@ -30,11 +32,6 @@ function pagedResponse(values: any): PagedResponse { } describe('BitbucketDiscoveryProcessor', () => { - const client: jest.Mocked = { - listProjects: jest.fn(), - listRepositories: jest.fn(), - } as any; - afterEach(() => jest.resetAllMocks()); describe('reject unrelated entries', () => { @@ -81,137 +78,236 @@ describe('BitbucketDiscoveryProcessor', () => { }); describe('handles repositories', () => { + const processor = BitbucketDiscoveryProcessor.fromConfig( + new ConfigReader({ + integrations: { + bitbucket: [{ host: 'bitbucket.mycompany.com', token: 'blob' }], + }, + }), + { logger: getVoidLogger() }, + ); + it('output all repositories', async () => { - const target = - 'https://bitbucket.mycompany.com/projects/*/repos/*/catalog.yaml'; - - client.listProjects.mockResolvedValue( - pagedResponse([{ key: 'backstage' }, { key: 'demo' }]), - ); - client.listRepositories.mockResolvedValueOnce( - pagedResponse([ - { - slug: 'backstage', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/backstage/browse', - }, - ], - }, - }, - ]), - ); - client.listRepositories.mockResolvedValueOnce( - pagedResponse([ - { - slug: 'demo', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/demo/repos/demo/browse', - }, - ], - }, - }, - ]), - ); - - const actual = await readBitbucketOrg(client, target); - expect(actual.scanned).toBe(2); - expect(actual.matches).toContainEqual({ - type: 'url', + const location: LocationSpec = { + type: 'bitbucket-discovery', target: - 'https://bitbucket.mycompany.com/projects/backstage/repos/backstage/browse/catalog.yaml', + 'https://bitbucket.mycompany.com/projects/*/repos/*/catalog.yaml', + }; + + jest + .spyOn(BitbucketClient.prototype, 'listProjects') + .mockResolvedValue( + pagedResponse([{ key: 'backstage' }, { key: 'demo' }]), + ); + jest + .spyOn(BitbucketClient.prototype, 'listRepositories') + .mockResolvedValueOnce( + pagedResponse([ + { + slug: 'backstage', + links: { + self: [ + { + href: + 'https://bitbucket.mycompany.com/projects/backstage/repos/backstage/browse', + }, + ], + }, + }, + ]), + ); + jest + .spyOn(BitbucketClient.prototype, 'listRepositories') + .mockResolvedValueOnce( + pagedResponse([ + { + slug: 'demo', + links: { + self: [ + { + href: + 'https://bitbucket.mycompany.com/projects/demo/repos/demo/browse', + }, + ], + }, + }, + ]), + ); + const emitter = jest.fn(); + + await processor.readLocation(location, false, emitter); + + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://bitbucket.mycompany.com/projects/backstage/repos/backstage/browse/catalog.yaml', + }, + optional: true, }); - expect(actual.matches).toContainEqual({ - type: 'url', - target: - 'https://bitbucket.mycompany.com/projects/demo/repos/demo/browse/catalog.yaml', + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://bitbucket.mycompany.com/projects/demo/repos/demo/browse/catalog.yaml', + }, + optional: true, }); }); it('output repositories with wildcards', async () => { - const target = - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-*/catalog.yaml'; - - client.listProjects.mockResolvedValue( - pagedResponse([{ key: 'backstage' }]), - ); - client.listRepositories.mockResolvedValueOnce( - pagedResponse([ - { slug: 'backstage' }, - { - slug: 'techdocs-cli', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-cli/browse', - }, - ], - }, - }, - { - slug: 'techdocs-container', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-container/browse', - }, - ], - }, - }, - ]), - ); - - const actual = await readBitbucketOrg(client, target); - expect(actual.scanned).toBe(3); - expect(actual.matches).toContainEqual({ - type: 'url', + const location: LocationSpec = { + type: 'bitbucket-discovery', target: - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-cli/browse/catalog.yaml', + 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-*/catalog.yaml', + }; + + jest + .spyOn(BitbucketClient.prototype, 'listProjects') + .mockResolvedValue(pagedResponse([{ key: 'backstage' }])); + jest + .spyOn(BitbucketClient.prototype, 'listRepositories') + .mockResolvedValueOnce( + pagedResponse([ + { slug: 'backstage' }, + { + slug: 'techdocs-cli', + links: { + self: [ + { + href: + 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-cli/browse', + }, + ], + }, + }, + { + slug: 'techdocs-container', + links: { + self: [ + { + href: + 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-container/browse', + }, + ], + }, + }, + ]), + ); + const emitter = jest.fn(); + await processor.readLocation(location, false, emitter); + + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-cli/browse/catalog.yaml', + }, + optional: true, }); - expect(actual.matches).toContainEqual({ - type: 'url', - target: - 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-container/browse/catalog.yaml', + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-container/browse/catalog.yaml', + }, + optional: true, }); }); it('filter unrelated repositories', async () => { - const target = - 'https://bitbucket.mycompany.com/projects/backstage/repos/test/catalog.yaml'; - - client.listProjects.mockResolvedValue( - pagedResponse([{ key: 'backstage' }]), - ); - client.listRepositories.mockResolvedValue( - pagedResponse([ - { slug: 'abstest' }, - { slug: 'testxyz' }, - { - slug: 'test', - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/backstage/repos/test', - }, - ], - }, - }, - ]), - ); - - const actual = await readBitbucketOrg(client, target); - expect(actual.scanned).toBe(3); - expect(actual.matches).toContainEqual({ - type: 'url', + const location: LocationSpec = { + type: 'bitbucket-discovery', target: 'https://bitbucket.mycompany.com/projects/backstage/repos/test/catalog.yaml', + }; + + jest + .spyOn(BitbucketClient.prototype, 'listProjects') + .mockResolvedValue(pagedResponse([{ key: 'backstage' }])); + jest + .spyOn(BitbucketClient.prototype, 'listRepositories') + .mockResolvedValue( + pagedResponse([ + { slug: 'abstest' }, + { slug: 'testxyz' }, + { + slug: 'test', + links: { + self: [ + { + href: + 'https://bitbucket.mycompany.com/projects/backstage/repos/test', + }, + ], + }, + }, + ]), + ); + + const emitter = jest.fn(); + await processor.readLocation(location, false, emitter); + + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'url', + target: + 'https://bitbucket.mycompany.com/projects/backstage/repos/test/catalog.yaml', + }, + optional: true, + }); + }); + }); + + describe('Custom repository parser', () => { + const customRepositoryParser: BitbucketRepositoryParser = async function* customRepositoryParser({}) { + yield results.location( + { + type: 'custom-location-type', + target: 'custom-target', + }, + true, + ); + }; + + const processor = BitbucketDiscoveryProcessor.fromConfig( + new ConfigReader({ + integrations: { + bitbucket: [{ host: 'bitbucket.mycompany.com', token: 'blob' }], + }, + }), + { parser: customRepositoryParser, logger: getVoidLogger() }, + ); + + it('use custom repository parser', async () => { + const location: LocationSpec = { + type: 'bitbucket-discovery', + target: + 'https://bitbucket.mycompany.com/projects/backstage/repos/test/catalog.yaml', + }; + + jest + .spyOn(BitbucketClient.prototype, 'listProjects') + .mockResolvedValue(pagedResponse([{ key: 'backstage' }])); + jest + .spyOn(BitbucketClient.prototype, 'listRepositories') + .mockResolvedValue(pagedResponse([{ slug: 'test' }])); + + const emitter = jest.fn(); + await processor.readLocation(location, false, emitter); + + expect(emitter).toHaveBeenCalledTimes(1); + expect(emitter).toHaveBeenCalledWith({ + type: 'location', + location: { + type: 'custom-location-type', + target: 'custom-target', + }, + optional: true, }); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts index f3dae9c112..f92a5c6f7c 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts @@ -21,15 +21,24 @@ import { ScmIntegrations, } from '@backstage/integration'; import { LocationSpec } from '@backstage/catalog-model'; -import { BitbucketClient, paginated } from './bitbucket'; +import { + Repository, + BitbucketRepositoryParser, + BitbucketClient, + defaultRepositoryParser, + paginated, +} from './bitbucket'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; -import { results } from './index'; export class BitbucketDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrationRegistry; + private readonly parser: BitbucketRepositoryParser; private readonly logger: Logger; - static fromConfig(config: Config, options: { logger: Logger }) { + static fromConfig( + config: Config, + options: { parser?: BitbucketRepositoryParser; logger: Logger }, + ) { const integrations = ScmIntegrations.fromConfig(config); return new BitbucketDiscoveryProcessor({ @@ -40,9 +49,11 @@ export class BitbucketDiscoveryProcessor implements CatalogProcessor { constructor(options: { integrations: ScmIntegrationRegistry; + parser?: BitbucketRepositoryParser; logger: Logger; }) { this.integrations = options.integrations; + this.parser = options.parser || defaultRepositoryParser; this.logger = options.logger; } @@ -73,18 +84,18 @@ export class BitbucketDiscoveryProcessor implements CatalogProcessor { const startTimestamp = Date.now(); this.logger.info(`Reading Bitbucket repositories from ${location.target}`); + const { catalogPath } = parseUrl(location.target); + const result = await readBitbucketOrg(client, location.target); for (const repository of result.matches) { - emit( - results.location( - repository, - // Not all locations may actually exist, since the user defined them as a wildcard pattern. - // Thus, we emit them as optional and let the downstream processor find them while not outputting - // an error if it couldn't. - true, - ), - ); + for await (const entity of this.parser({ + client: client, + repository: repository, + path: catalogPath, + })) { + emit(entity); + } } const duration = ((Date.now() - startTimestamp) / 1000).toFixed(1); @@ -100,7 +111,7 @@ export async function readBitbucketOrg( client: BitbucketClient, target: string, ): Promise { - const { projectSearchPath, repoSearchPath, catalogPath } = parseUrl(target); + const { projectSearchPath, repoSearchPath } = parseUrl(target); const projects = paginated(options => client.listProjects(options)); const result: Result = { scanned: 0, @@ -116,12 +127,8 @@ export async function readBitbucketOrg( ); for await (const repository of repositories) { result.scanned++; - if (repoSearchPath.test(repository.slug)) { - result.matches.push({ - type: 'url', - target: `${repository.links.self[0].href}${catalogPath}`, - }); + result.matches.push(repository); } } } @@ -152,5 +159,5 @@ function escapeRegExp(str: string): RegExp { type Result = { scanned: number; - matches: LocationSpec[]; + matches: Repository[]; }; diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts new file mode 100644 index 0000000000..ab5080f446 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts @@ -0,0 +1,55 @@ +/* + * 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 { defaultRepositoryParser } from './BitbucketRepositoryParser'; +import { Project, Repository } from './types'; +import { BitbucketClient } from './client'; +import { results } from '../index'; + +describe('BitbucketRepositoryParser', () => { + describe('defaultRepositoryParser', () => { + it('emits location', async () => { + const browseUrl = + 'https://bitbucket.mycompany.com/projects/project-key/repos/repo-slug/browse'; + const path = '/catalog-info.yaml'; + const expected = [ + results.location( + { + type: 'url', + target: `${browseUrl}${path}`, + }, + true, + ), + ]; + const actual = await defaultRepositoryParser({ + client: {} as BitbucketClient, + repository: { + project: {} as Project, + slug: 'repo-slug', + links: { + self: [{ href: browseUrl }], + }, + } as Repository, + path: path, + }); + + let i = 0; + for await (const entity of actual) { + expect(entity).toStrictEqual(expected[i]); + i++; + } + }); + }); +}); diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts new file mode 100644 index 0000000000..f786b6dac8 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts @@ -0,0 +1,41 @@ +/* + * 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 { Repository } from './types'; +import { CatalogProcessorResult } from '../types'; +import { results } from '../index'; +import { BitbucketClient } from './client'; + +export type BitbucketRepositoryParser = (options: { + client: BitbucketClient; + repository: Repository; + path: string; +}) => AsyncIterable; + +export const defaultRepositoryParser: BitbucketRepositoryParser = async function* defaultRepositoryParser({ + repository, + path, +}) { + yield results.location( + { + type: 'url', + target: `${repository.links.self[0].href}${path}`, + }, + // Not all locations may actually exist, since the user defined them as a wildcard pattern. + // Thus, we emit them as optional and let the downstream processor find them while not outputting + // an error if it couldn't. + true, + ); +}; diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/client.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/client.ts index c3c27aedfc..601461dcf5 100644 --- a/plugins/catalog-backend/src/ingestion/processors/bitbucket/client.ts +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/client.ts @@ -41,6 +41,15 @@ export class BitbucketClient { ); } + async getRaw( + projectKey: string, + repo: string, + path: string, + ): Promise { + const request = `${this.config.apiBaseUrl}/projects/${projectKey}/repos/${repo}/raw/${path}`; + return fetch(request, getBitbucketRequestOptions(this.config)); + } + private async pagedRequest( endpoint: string, options?: ListOptions, diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts index 7e70bcfe7a..ba2a2b3afe 100644 --- a/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/index.ts @@ -15,3 +15,6 @@ */ export { BitbucketClient, paginated } from './client'; export type { PagedResponse } from './client'; +export * from './types'; +export type { BitbucketRepositoryParser } from './BitbucketRepositoryParser'; +export { defaultRepositoryParser } from './BitbucketRepositoryParser'; diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/types.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/types.ts new file mode 100644 index 0000000000..75dd372faa --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/types.ts @@ -0,0 +1,28 @@ +/* + * 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 type Project = { + key: string; +}; + +export type Repository = { + project: Project; + slug: string; + links: Record; +}; + +export type Link = { + href: string; +}; From 88d62cad736da437cb0967efd8a2ab7bd577064e Mon Sep 17 00:00:00 2001 From: Omer Farooq Date: Sun, 11 Apr 2021 15:50:30 +1200 Subject: [PATCH 108/395] feat(techradar-plugin) add markdown support in techradar entry description Signed-off-by: Omer Farooq --- .../src/components/RadarDescription/RadarDescription.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/tech-radar/src/components/RadarDescription/RadarDescription.tsx b/plugins/tech-radar/src/components/RadarDescription/RadarDescription.tsx index 20c489f630..3ac4f153be 100644 --- a/plugins/tech-radar/src/components/RadarDescription/RadarDescription.tsx +++ b/plugins/tech-radar/src/components/RadarDescription/RadarDescription.tsx @@ -19,6 +19,7 @@ import Dialog from '@material-ui/core/Dialog'; import DialogTitle from '@material-ui/core/DialogTitle'; import { Button, DialogActions, DialogContent } from '@material-ui/core'; import LinkIcon from '@material-ui/icons/Link'; +import { MarkdownContent } from '@backstage/core'; export type Props = { open: boolean; @@ -43,7 +44,9 @@ const RadarDescription = (props: Props): JSX.Element => { {title} - {description} + + + {url && ( - } - /> - - -); - -const cicdCard = ( - - - - - - - - - - - - - - - - - - - -); - -const errorsContent = ( - - - - - - - - - -); - -const overviewContent = ( - - - - - - - - - - - - - - - - - - {cicdCard} - - - Boolean(isGithubInsightsAvailable(e))}> - - - - - - - - - - - - - - - - - - - - Boolean(isGithubPullRequestsAvailable(e))}> - - - - - - - - - - -); - -const serviceEntityPage = ( - - - {overviewContent} - - - - {cicdContent} - - - - {errorsContent} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); - -const websiteEntityPage = ( - - - {overviewContent} - - - - {cicdContent} - - - - - - - - {errorsContent} - - - - - - - - - - - - - - - - - - - - - - -); - -const defaultEntityPage = ( - - - {overviewContent} - - - - - - - - - - -); - -const componentPage = ( - - - {serviceEntityPage} - - - - {websiteEntityPage} - - - {defaultEntityPage} - -); - -const apiPage = ( - - - - - - - - - - - - - - - - - - - - - - - - - -); - -const userPage = ( - - - - - - - - - - - - -); - -const groupPage = ( - - - - - - - - - - - - - - - -); - -const systemPage = ( - - - - - - - - - - - - - - - - - - -); - -const domainPage = ( - - - - - - - - - - - - -); - -export const entityPage = ( - - - - - - - - - {defaultEntityPage} - -); From 77a2335997f0956006a4d4c099430794a0b6759f Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 16:23:46 +0200 Subject: [PATCH 226/395] Delete EntityPage.tsx Signed-off-by: Brett Wright --- .../app/src/components/catalog/EntityPage.tsx | 261 ------------------ 1 file changed, 261 deletions(-) delete mode 100644 packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx diff --git a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx deleted file mode 100644 index a302bb6dd7..0000000000 --- a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx +++ /dev/null @@ -1,261 +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 { Button, Grid } from '@material-ui/core'; -import { EmptyState } from '@backstage/core'; -import { - EntityApiDefinitionCard, - EntityConsumedApisCard, - EntityConsumingComponentsCard, - EntityHasApisCard, - EntityProvidedApisCard, - EntityProvidingComponentsCard, -} from '@backstage/plugin-api-docs'; -import { - EntityAboutCard, - EntitySystemDiagramCard, - EntityHasComponentsCard, - EntityHasSystemsCard, - EntityLayout, - EntitySwitch, - isComponentType, - isKind, -} from '@backstage/plugin-catalog'; -import { - isGithubActionsAvailable, - EntityGithubActionsContent, -} from '@backstage/plugin-github-actions'; -import { - EntityUserProfileCard, - EntityGroupProfileCard, - EntityMembersListCard, - EntityOwnershipCard, -} from '@backstage/plugin-org'; -import { EntityTechdocsContent } from '@backstage/plugin-techdocs'; - -const cicdContent = ( - // This is an example of how you can implement your company's logic in entity page. - // You can for example enforce that all components of type 'service' should use GitHubActions - - - - - - - - Read more - - } - /> - - -); - -const overviewContent = ( - - - - - -); - -const serviceEntityPage = ( - - - {overviewContent} - - - - {cicdContent} - - - - - - - - - - - - - - - - - -); - -const websiteEntityPage = ( - - - {overviewContent} - - - - {cicdContent} - - - - - - -); - -const defaultEntityPage = ( - - - {overviewContent} - - - - - - -); - -const componentPage = ( - - - {serviceEntityPage} - - - - {websiteEntityPage} - - - {defaultEntityPage} - -); - -const apiPage = ( - - - - - - - - - - - - - - - - - - - - - - - - - -); - -const userPage = ( - - - - - - - - - - - - -); - -const groupPage = ( - - - - - - - - - - - - - - - -); - -const systemPage = ( - - - - - - - - - - - - - - - - - - -); - -const domainPage = ( - - - - - - - - - - - - -); - -export const entityPage = ( - - - - - - - - - {defaultEntityPage} - -); From 66cd739fec8eeae4c7c02f066e33e6a3cc184104 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 18:58:16 +0200 Subject: [PATCH 227/395] Revert "Delete EntityPage.tsx" This reverts commit 59eda628a87dc470ae1c5d2b7b46ced129fea289. Signed-off-by: Brett Wright --- .../app/src/components/catalog/EntityPage.tsx | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx diff --git a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx new file mode 100644 index 0000000000..a302bb6dd7 --- /dev/null +++ b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx @@ -0,0 +1,261 @@ +/* + * 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 { Button, Grid } from '@material-ui/core'; +import { EmptyState } from '@backstage/core'; +import { + EntityApiDefinitionCard, + EntityConsumedApisCard, + EntityConsumingComponentsCard, + EntityHasApisCard, + EntityProvidedApisCard, + EntityProvidingComponentsCard, +} from '@backstage/plugin-api-docs'; +import { + EntityAboutCard, + EntitySystemDiagramCard, + EntityHasComponentsCard, + EntityHasSystemsCard, + EntityLayout, + EntitySwitch, + isComponentType, + isKind, +} from '@backstage/plugin-catalog'; +import { + isGithubActionsAvailable, + EntityGithubActionsContent, +} from '@backstage/plugin-github-actions'; +import { + EntityUserProfileCard, + EntityGroupProfileCard, + EntityMembersListCard, + EntityOwnershipCard, +} from '@backstage/plugin-org'; +import { EntityTechdocsContent } from '@backstage/plugin-techdocs'; + +const cicdContent = ( + // This is an example of how you can implement your company's logic in entity page. + // You can for example enforce that all components of type 'service' should use GitHubActions + + + + + + + + Read more + + } + /> + + +); + +const overviewContent = ( + + + + + +); + +const serviceEntityPage = ( + + + {overviewContent} + + + + {cicdContent} + + + + + + + + + + + + + + + + + +); + +const websiteEntityPage = ( + + + {overviewContent} + + + + {cicdContent} + + + + + + +); + +const defaultEntityPage = ( + + + {overviewContent} + + + + + + +); + +const componentPage = ( + + + {serviceEntityPage} + + + + {websiteEntityPage} + + + {defaultEntityPage} + +); + +const apiPage = ( + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const userPage = ( + + + + + + + + + + + + +); + +const groupPage = ( + + + + + + + + + + + + + + + +); + +const systemPage = ( + + + + + + + + + + + + + + + + + + +); + +const domainPage = ( + + + + + + + + + + + + +); + +export const entityPage = ( + + + + + + + + + {defaultEntityPage} + +); From 47b4c33c1f60da9dbf4fa936289b2f77be73bb83 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:00:51 +0200 Subject: [PATCH 228/395] Revert "Delete EntityPage.tsx" This reverts commit 157318b7b261541758c353482d98e0372a4369ce. Signed-off-by: Brett Wright --- .../app/src/components/catalog/EntityPage.tsx | 494 ++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 packages/app/src/components/catalog/EntityPage.tsx diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx new file mode 100644 index 0000000000..d4db2b0e63 --- /dev/null +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -0,0 +1,494 @@ +/* + * 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, { ReactNode, useMemo, useState } from 'react'; +import BadgeIcon from '@material-ui/icons/CallToAction'; +import { EmptyState } from '@backstage/core'; +import { + EntityApiDefinitionCard, + EntityConsumingComponentsCard, + EntityHasApisCard, + EntityProvidingComponentsCard, + EntityProvidedApisCard, + EntityConsumedApisCard, +} from '@backstage/plugin-api-docs'; +import { EntityBadgesDialog } from '@backstage/plugin-badges'; +import { + EntityAboutCard, + EntityHasComponentsCard, + EntityHasSubcomponentsCard, + EntityHasSystemsCard, + EntityLayout, + EntityLinksCard, + EntitySystemDiagramCard, + EntitySwitch, + isComponentType, + isKind, +} from '@backstage/plugin-catalog'; +import { + EntityCircleCIContent, + isCircleCIAvailable, +} from '@backstage/plugin-circleci'; +import { + EntityCloudbuildContent, + isCloudbuildAvailable, +} from '@backstage/plugin-cloudbuild'; +import { + EntityGithubActionsContent, + EntityRecentGithubActionsRunsCard, + isGithubActionsAvailable, +} from '@backstage/plugin-github-actions'; +import { + EntityJenkinsContent, + EntityLatestJenkinsRunCard, + isJenkinsAvailable, +} from '@backstage/plugin-jenkins'; +import { EntityKafkaContent } from '@backstage/plugin-kafka'; +import { EntityKubernetesContent } from '@backstage/plugin-kubernetes'; +import { + EntityLastLighthouseAuditCard, + EntityLighthouseContent, + isLighthouseAvailable, +} from '@backstage/plugin-lighthouse'; +import { + EntityGroupProfileCard, + EntityMembersListCard, + EntityOwnershipCard, + EntityUserProfileCard, +} from '@backstage/plugin-org'; +import { + EntityPagerDutyCard, + isPagerDutyAvailable, +} from '@backstage/plugin-pagerduty'; +import { + EntityRollbarContent, + isRollbarAvailable, +} from '@backstage/plugin-rollbar'; +import { EntitySentryContent } from '@backstage/plugin-sentry'; +import { EntityTechdocsContent } from '@backstage/plugin-techdocs'; +import { EntityTodoContent } from '@backstage/plugin-todo'; +import { Button, Grid } from '@material-ui/core'; +import { + EntityBuildkiteContent, + isBuildkiteAvailable, +} from '@roadiehq/backstage-plugin-buildkite'; +import { + EntityGithubInsightsContent, + EntityGithubInsightsLanguagesCard, + EntityGithubInsightsReadmeCard, + EntityGithubInsightsReleasesCard, + isGithubInsightsAvailable, +} from '@roadiehq/backstage-plugin-github-insights'; +import { + EntityGithubPullRequestsContent, + EntityGithubPullRequestsOverviewCard, + isGithubPullRequestsAvailable, +} from '@roadiehq/backstage-plugin-github-pull-requests'; +import { + EntityTravisCIContent, + EntityTravisCIOverviewCard, + isTravisciAvailable, +} from '@roadiehq/backstage-plugin-travis-ci'; + +const EntityLayoutWrapper = (props: { children?: ReactNode }) => { + const [badgesDialogOpen, setBadgesDialogOpen] = useState(false); + + const extraMenuItems = useMemo(() => { + return [ + { + title: 'Badges', + Icon: BadgeIcon, + onClick: () => setBadgesDialogOpen(true), + }, + ]; + }, []); + + return ( + <> + + {props.children} + + setBadgesDialogOpen(false)} + /> + + ); +}; + +export const cicdContent = ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + Read more + + } + /> + + +); + +const cicdCard = ( + + + + + + + + + + + + + + + + + + + +); + +const errorsContent = ( + + + + + + + + + +); + +const overviewContent = ( + + + + + + + + + + + + + + + + + + {cicdCard} + + + Boolean(isGithubInsightsAvailable(e))}> + + + + + + + + + + + + + + + + + + + + Boolean(isGithubPullRequestsAvailable(e))}> + + + + + + + + + + +); + +const serviceEntityPage = ( + + + {overviewContent} + + + + {cicdContent} + + + + {errorsContent} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const websiteEntityPage = ( + + + {overviewContent} + + + + {cicdContent} + + + + + + + + {errorsContent} + + + + + + + + + + + + + + + + + + + + + + +); + +const defaultEntityPage = ( + + + {overviewContent} + + + + + + + + + + +); + +const componentPage = ( + + + {serviceEntityPage} + + + + {websiteEntityPage} + + + {defaultEntityPage} + +); + +const apiPage = ( + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const userPage = ( + + + + + + + + + + + + +); + +const groupPage = ( + + + + + + + + + + + + + + + +); + +const systemPage = ( + + + + + + + + + + + + + + + + + + +); + +const domainPage = ( + + + + + + + + + + + + +); + +export const entityPage = ( + + + + + + + + + {defaultEntityPage} + +); From de00581391ca8e85f3dd8c3951d5af66e2215c36 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:00:57 +0200 Subject: [PATCH 229/395] Revert "Delete configure-app-with-plugins.md" This reverts commit ce16cd5233779e0dbe24b2756027de83484ead84. Signed-off-by: Brett Wright --- .../configure-app-with-plugins.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 docs/getting-started/configure-app-with-plugins.md diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md new file mode 100644 index 0000000000..b2f3a37d90 --- /dev/null +++ b/docs/getting-started/configure-app-with-plugins.md @@ -0,0 +1,99 @@ +--- +id: configure-app-with-plugins +title: Configuring App with plugins +description: Documentation on How Configuring App with plugins +--- + +Backstage plugins customize the app for your needs. There is a +[plugin marketplace](https://backstage.io/plugins) with plugins for many common +infrastructure needs - CI/CD, monitoring, auditing, and more. + +## Adding existing plugins to your app + +The following steps assume that you have +[created a Backstage app](./create-an-app.md) and want to add an existing plugin +to it. We are using the +[CircleCI](https://github.com/backstage/backstage/blob/master/plugins/circleci/README.md) +plugin in this example. + +1. Add the plugin's npm package to the repo: + +```bash +yarn workspace app add @backstage/plugin-circleci +``` + +Note the plugin is added to the `app` package, rather than the root +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: + +```diff + // packages/app/src/components/catalog/EntityPage.tsx ++import { ++ EntityCircleCIContent, ++ isCircleCIAvailable, ++} from '@backstage/plugin-circleci'; + +... + const cicdContent = ( + + ... ++ ++ ++ ; + + ); +``` + +This is just one example, but each Backstage instance may integrate content or +cards to suit their needs on different pages, tabs, etc. Note that stand-alone +plugins that are not "attached" to the Software Catalog would be added outside +the `EntityPage`. + +4. [Optional] Add proxy config: + +```yaml +// app-config.yaml +proxy: + '/circleci/api': + target: https://circleci.com/api/v1.1 + headers: + Circle-Token: ${CIRCLECI_AUTH_TOKEN} +``` + +### Adding a plugin page to the Sidebar + +In a standard Backstage app created with +[@backstage/create-app](./create-an-app.md), the sidebar is managed inside +`packages/app/src/components/Root/Root.tsx`. The file exports the entire +`Sidebar` element of your app, which you can extend with additional entries by +adding new `SidebarItem` elements. + +For example, if you install the `api-docs` plugin, a matching `SidebarItem` +could be something like this: + +```tsx +// Import icon from MUI +import ExtensionIcon from '@material-ui/icons/Extension'; + +// ... inside the AppSidebar component +; +``` + +You can also use your own SVGs directly as icon components. Just make sure they +are sized according to the Material UI's +[SvgIcon](https://material-ui.com/api/svg-icon/) default of 24x24px, and set the +extension to `.icon.svg`. For example: + +```ts +import InternalToolIcon from './internal-tool.icon.svg'; +``` From 5d01971dd33c3d49852e1886cc2f46046419d9a9 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:01:00 +0200 Subject: [PATCH 230/395] Revert "Delete sour-plums-enjoy.md" This reverts commit 7d9de03c4432d82ffad10937f39243f6fa4fcce8. Signed-off-by: Brett Wright --- .changeset/sour-plums-enjoy.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/sour-plums-enjoy.md diff --git a/.changeset/sour-plums-enjoy.md b/.changeset/sour-plums-enjoy.md new file mode 100644 index 0000000000..ef68166255 --- /dev/null +++ b/.changeset/sour-plums-enjoy.md @@ -0,0 +1,7 @@ +--- +'@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 `` for the `/diagram` path from the `groupPage` down into the `systemPage` element. From 766533df4b95c133953263621e1dd142eb4b7c5f Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:01:03 +0200 Subject: [PATCH 231/395] Revert "Move diagram to system page" This reverts commit 876a468740f25b69d6dc7737586d7d64348daf6a. Signed-off-by: Brett Wright --- .changeset/sour-plums-enjoy.md | 7 ------- packages/app/src/components/catalog/EntityPage.tsx | 7 ++++--- .../packages/app/src/components/catalog/EntityPage.tsx | 7 ++++--- 3 files changed, 8 insertions(+), 13 deletions(-) delete mode 100644 .changeset/sour-plums-enjoy.md 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 `` for the `/diagram` path from the `groupPage` down into the `systemPage` element. diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index d4db2b0e63..d6f91957a9 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -441,6 +441,10 @@ const groupPage = ( + + + + ); @@ -459,9 +463,6 @@ const systemPage = ( - - - ); diff --git a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx index a302bb6dd7..f1aba46c52 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx @@ -208,6 +208,10 @@ const groupPage = ( + + + + ); @@ -226,9 +230,6 @@ const systemPage = ( - - - ); From 4949915fb32edd6d31bb5b24e1559cf517494bce Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:01:07 +0200 Subject: [PATCH 232/395] Revert "chore(deps): bump diff from 4.0.2 to 5.0.0" This reverts commit 2213de5068443f5036f1ea5a899867086266dc52. Signed-off-by: Brett Wright --- packages/cli/package.json | 2 +- yarn.lock | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 251b2ab076..db7ac2774c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -62,7 +62,7 @@ "commander": "^6.1.0", "css-loader": "^3.5.3", "dashify": "^2.0.0", - "diff": "^5.0.0", + "diff": "^4.0.2", "esbuild": "^0.8.56", "eslint": "^7.1.0", "eslint-config-prettier": "^6.0.0", diff --git a/yarn.lock b/yarn.lock index 2fe64c785d..1f76456d00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11527,16 +11527,11 @@ diff@1.4.0: resolved "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" integrity sha1-fyjS657nsVqX79ic5j3P2qPMur8= -diff@^4.0.1: +diff@^4.0.1, diff@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" From f77db9572d05d835154461e5e86a6907f2731d67 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:01:10 +0200 Subject: [PATCH 233/395] Revert "Clarify example" This reverts commit 72eaf17eaa408af347db07881ef6a8b7619c7adf. Signed-off-by: Brett Wright --- .../configure-app-with-plugins.md | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index b2f3a37d90..428f768a82 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -36,22 +36,17 @@ export { plugin as CircleCi } from '@backstage/plugin-circleci'; 3. Register the plugin in the entity pages: -```diff - // packages/app/src/components/catalog/EntityPage.tsx -+import { -+ EntityCircleCIContent, -+ isCircleCIAvailable, -+} from '@backstage/plugin-circleci'; +```jsx +// packages/app/src/components/catalog/EntityPage.tsx +import { + EntityCircleCIContent, + isCircleCIAvailable, +} from '@backstage/plugin-circleci'; -... - const cicdContent = ( - - ... -+ -+ -+ ; - - ); +// Then somewhere inside + + +; ``` This is just one example, but each Backstage instance may integrate content or From 314b8bf1e9e786bdbb31d107aa58ee44ee5eb1ee Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:01:11 +0200 Subject: [PATCH 234/395] Revert "Fix pluginname" This reverts commit cb287be816d8149153cd72df5d6318efe04b04d4. Signed-off-by: Brett Wright --- docs/getting-started/configure-app-with-plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index 428f768a82..1753676e19 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -31,7 +31,7 @@ CircleCI is a frontend UI plugin, it goes in `app` rather than `backend`. ```js // packages/app/src/plugins.ts -export { plugin as CircleCi } from '@backstage/plugin-circleci'; +export { plugin as Circleci } from '@backstage/plugin-circleci'; ``` 3. Register the plugin in the entity pages: From 50c5808b624bc7f6de4d79587a461ad3c48c6361 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:01:14 +0200 Subject: [PATCH 235/395] Revert "Update plugin example for composability" This reverts commit 7ca780442219d2ec85fb296c3d1584c0d3aab1db. Signed-off-by: Brett Wright --- .../configure-app-with-plugins.md | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index 1753676e19..cdef932127 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -34,25 +34,23 @@ CircleCI is a frontend UI plugin, it goes in `app` rather than `backend`. export { plugin as Circleci } from '@backstage/plugin-circleci'; ``` -3. Register the plugin in the entity pages: +3. Register the plugin router: ```jsx // packages/app/src/components/catalog/EntityPage.tsx -import { - EntityCircleCIContent, - isCircleCIAvailable, -} from '@backstage/plugin-circleci'; + +import { Router as CircleCIRouter } from '@backstage/plugin-circleci'; // Then somewhere inside - - -; +} +/>; ``` -This is just one example, but each Backstage instance may integrate content or -cards to suit their needs on different pages, tabs, etc. Note that stand-alone -plugins that are not "attached" to the Software Catalog would be added outside -the `EntityPage`. +Note that stand-alone plugins that are not "attached" to the Software Catalog +would be added outside the `EntityPage`. 4. [Optional] Add proxy config: From 4c89acec0e6d62cdbfda4137d626af82dc52a9ab Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 19 Apr 2021 19:44:36 +0200 Subject: [PATCH 236/395] change patch to minor Signed-off-by: Brett Wright --- .changeset/tiny-ears-love.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tiny-ears-love.md b/.changeset/tiny-ears-love.md index 2f7502fad7..52218e2ecc 100644 --- a/.changeset/tiny-ears-love.md +++ b/.changeset/tiny-ears-love.md @@ -1,5 +1,5 @@ --- -'@backstage/cli': major +'@backstage/cli': minor --- Added support for Datadog rum events From 909eb5ecc66bedbddd948bf15684c887dd254b96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Apr 2021 19:13:40 +0000 Subject: [PATCH 237/395] chore(deps): bump ssri from 6.0.1 to 6.0.2 Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/npm/ssri/releases) - [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md) - [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2) Signed-off-by: dependabot[bot] --- yarn.lock | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/yarn.lock b/yarn.lock index b3efdedbd4..9233744570 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13145,9 +13145,9 @@ fetch-readablestream@^0.2.0: integrity sha512-qu4mXWf4wus4idBIN/kVH+XSer8IZ9CwHP+Pd7DL7TuKNC1hP7ykon4kkBjwJF3EMX2WsFp4hH7gU7CyL7ucXw== figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== figures@^1.7.0: version "1.7.0" @@ -18619,14 +18619,7 @@ minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: safe-buffer "^5.1.2" yallist "^3.0.0" -minipass@^3.0.0, minipass@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" - integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w== - dependencies: - yallist "^4.0.0" - -minipass@^3.1.0, minipass@^3.1.3: +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== @@ -24080,20 +24073,13 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: figgy-pudding "^3.5.1" -ssri@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808" - integrity sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA== - dependencies: - minipass "^3.1.1" - -ssri@^8.0.1: +ssri@^8.0.0, ssri@^8.0.1: version "8.0.1" resolved "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== From 9b9a8f39b60ba68aa21b518f012e6878c51a76af Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 19 Apr 2021 20:35:56 -0400 Subject: [PATCH 238/395] 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 ac6025f63afce4b964c528803543e414befe8692 Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" Date: Mon, 19 Apr 2021 18:07:49 +0800 Subject: [PATCH 239/395] techdocs-plugin: add feedback link for Github/Gitlab source repos Signed-off-by: Chongyang Adrian, Ke --- .changeset/techdocs-eight-camels-hear.md | 8 ++ .../techdocs/src/reader/components/Reader.tsx | 6 +- .../transformers/addGitFeedbackLink.test.ts | 115 ++++++++++++++++++ .../reader/transformers/addGitFeedbackLink.ts | 86 +++++++++++++ .../techdocs/src/reader/transformers/index.ts | 1 + 5 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 .changeset/techdocs-eight-camels-hear.md create mode 100644 plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts create mode 100644 plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts diff --git a/.changeset/techdocs-eight-camels-hear.md b/.changeset/techdocs-eight-camels-hear.md new file mode 100644 index 0000000000..0d6c16f725 --- /dev/null +++ b/.changeset/techdocs-eight-camels-hear.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-techdocs': minor +--- + +Add feedback link icon in Techdocs Reader that directs to Gitlab or Github repo issue page with prefilled 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. edit_uri will need to be specified for self-hosted Gitlab/Github with different hostnames. +Gitlab or Github detection checks for 'gitlab' or 'github' in hostname of source in repo_url; +additionally 'techdocs.feedback.gitlab' and '.github' in app config can be used to specify hostnames that should be recognised as the respective Git hosting for the feedback link. diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index feed758caa..ff4f47dca0 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 } from '@backstage/core'; +import { useApi, configApiRef } from '@backstage/core'; import { BackstageTheme } from '@backstage/theme'; import { useTheme } from '@material-ui/core'; import { Alert } from '@material-ui/lab'; @@ -31,6 +31,7 @@ import transformer, { rewriteDocLinks, sanitizeDOM, simplifyMkdocsFooter, + addGitFeedbackLink, } from '../transformers'; import { TechDocsNotFound } from './TechDocsNotFound'; import TechDocsProgressBar from './TechDocsProgressBar'; @@ -52,6 +53,7 @@ export const Reader = ({ entityId, onReady }: Props) => { const [loadedPath, setLoadedPath] = useState(''); const [atInitialLoad, setAtInitialLoad] = useState(true); const [newerDocsExist, setNewerDocsExist] = useState(false); + const configApi = useApi(configApiRef); const { value: isSynced, @@ -142,6 +144,7 @@ export const Reader = ({ entityId, onReady }: Props) => { rewriteDocLinks(), removeMkdocsHeader(), simplifyMkdocsFooter(), + addGitFeedbackLink(configApi), injectCss({ css: ` body { @@ -313,6 +316,7 @@ export const Reader = ({ entityId, onReady }: Props) => { name, newerDocsExist, isSynced, + configApi, ]); // docLoadError not considered an error state if sync request is still ongoing diff --git a/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts new file mode 100644 index 0000000000..cc451c3a25 --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts @@ -0,0 +1,115 @@ +/* + * 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 { createTestShadowDom } from '../../test-utils'; +import { addGitFeedbackLink } from './addGitFeedbackLink'; + +const configApi = { + getOptionalString: function getOptionalString(key: string) { + return key === 'gitlab' ? 'gitlab.com' : 'github.com'; + }, +}; + +describe('addGitFeedbackLink', () => { + it('adds a feedback link when a Gitlab source edit link is available', () => { + const shadowDom = createTestShadowDom( + ` + + +
+

HeaderText

+ +
+ + `, + { + preTransformers: [addGitFeedbackLink(configApi)], + postTransformers: [], + }, + ); + + expect(shadowDom.querySelector('#git-feedback-link')).toBeTruthy(); + expect( + (shadowDom.querySelector('#git-feedback-link') as HTMLLinkElement)!.href, + ).toEqual( + 'https://gitlab.com/reponame/username/issues/new?issue[title]=Documentation%20Feedback%3A%20HeaderText&issue[description]=Page%20source%3A%0Ahttps%3A%2F%2Fgitlab.com%2Freponame%2Fusername%2Fdocs%2FTestDoc.md%0A%0AFeedback%3A', + ); + }); + + it('adds a feedback link when a Github source edit link is available', () => { + const shadowDom = createTestShadowDom( + ` + + + + + `, + { + preTransformers: [addGitFeedbackLink(configApi)], + postTransformers: [], + }, + ); + + expect(shadowDom.querySelector('#git-feedback-link')).toBeTruthy(); + expect( + (shadowDom.querySelector('#git-feedback-link') as HTMLLinkElement)!.href, + ).toEqual( + 'https://github.com/reponame/username/issues/new?title=Documentation%20Feedback%3A%20HeaderText&body=Page%20source%3A%0Ahttps%3A%2F%2Fgithub.com%2Freponame%2Fusername%2Fdocs%2FTestDoc.md%0A%0AFeedback%3A', + ); + }); + + it('does not add a feedback link when no source edit link is available', () => { + const shadowDom = createTestShadowDom( + ` + + + + + `, + { + preTransformers: [addGitFeedbackLink(configApi)], + postTransformers: [], + }, + ); + + expect(shadowDom.querySelector('#git-feedback-link')).toBeFalsy(); + }); + + it('does not add a feedback link when a Gitlab or Github source edit link is not available', () => { + const shadowDom = createTestShadowDom( + ` + + +
+

Conveyor Pipelines

+ +
+ + `, + { + preTransformers: [addGitFeedbackLink(configApi)], + postTransformers: [], + }, + ); + + expect(shadowDom.querySelector('#git-feedback-link')).toBeFalsy(); + }); +}); diff --git a/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts new file mode 100644 index 0000000000..d19d90228c --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts @@ -0,0 +1,86 @@ +/* + * 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 type { Transformer } from './index'; +import FeedbackOutlinedIcon from '@material-ui/icons/FeedbackOutlined'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +// requires repo +export const addGitFeedbackLink = (configApi: any): Transformer => { + return dom => { + // attempting to use selectors that are more likely to be static as MkDocs updates over time + const sourceAnchor = dom.querySelector( + '[title="Edit this page"]', + ) as HTMLAnchorElement; + + // don't show if edit link not available in raw page + if (!sourceAnchor || !sourceAnchor.href) { + return dom; + } + let gitHost = ''; + + const sourceURL = new URL(sourceAnchor.href); + const githubHosts = configApi + .getConfigArray('integrations.github') + .map((integration: any) => integration.data.host); + const gitlabHosts = configApi + .getConfigArray('integrations.gitlab') + .map((integration: any) => integration.data.host); + + // don't show if can't identify edit link hostname as a gitlab/github hosting + if ( + githubHosts.includes(sourceURL.hostname) || + sourceURL.origin.includes('github') + ) { + gitHost = 'github'; + } else if ( + gitlabHosts.includes(sourceURL.hostname) || + sourceURL.origin.includes('gitlab') + ) { + gitHost = 'gitlab'; + } else { + return dom; + } + + // topmost h1 only contains title for whole page + const title = (dom.querySelector('article>h1') as HTMLElement).childNodes[0] + .textContent; + const issueTitle = encodeURIComponent(`Documentation Feedback: ${title}`); + const issueDesc = encodeURIComponent( + `Page source:\n${sourceAnchor.href}\n\nFeedback:`, + ); + const repoPath = sourceURL.pathname.split('/').slice(0, 3).join('/'); + + const feedbackLink = sourceAnchor.cloneNode() as HTMLAnchorElement; + switch (gitHost) { + case 'gitlab': + feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?issue[title]=${issueTitle}&issue[description]=${issueDesc}`; + break; + case 'github': + feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?title=${issueTitle}&body=${issueDesc}`; + break; + default: + return dom; + } + ReactDOM.render(React.createElement(FeedbackOutlinedIcon), feedbackLink); + feedbackLink.style.paddingLeft = '5px'; + feedbackLink.title = 'Leave feedback for this page'; + feedbackLink.id = 'git-feedback-link'; + sourceAnchor?.insertAdjacentElement('beforebegin', feedbackLink); + return dom; + }; +}; diff --git a/plugins/techdocs/src/reader/transformers/index.ts b/plugins/techdocs/src/reader/transformers/index.ts index 4da4cb3add..a005ad470b 100644 --- a/plugins/techdocs/src/reader/transformers/index.ts +++ b/plugins/techdocs/src/reader/transformers/index.ts @@ -15,6 +15,7 @@ */ export * from './addBaseUrl'; +export * from './addGitFeedbackLink'; export * from './rewriteDocLinks'; export * from './addLinkClickListener'; export * from './removeMkdocsHeader'; From 2b440c06055e37a05bfc019bcd28caf108da9fc6 Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" Date: Tue, 20 Apr 2021 13:32:34 +0800 Subject: [PATCH 240/395] add git feedback link: update FAQ and unit testing Signed-off-by: Chongyang Adrian, Ke --- .changeset/techdocs-eight-camels-hear.md | 3 +- docs/features/techdocs/FAQ.md | 12 ++++++ .../transformers/addGitFeedbackLink.test.ts | 37 ++++++++++++++++--- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/.changeset/techdocs-eight-camels-hear.md b/.changeset/techdocs-eight-camels-hear.md index 0d6c16f725..5c3df10c89 100644 --- a/.changeset/techdocs-eight-camels-hear.md +++ b/.changeset/techdocs-eight-camels-hear.md @@ -4,5 +4,4 @@ Add feedback link icon in Techdocs Reader that directs to Gitlab or Github repo issue page with prefilled 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. edit_uri will need to be specified for self-hosted Gitlab/Github with different hostnames. -Gitlab or Github detection checks for 'gitlab' or 'github' in hostname of source in repo_url; -additionally 'techdocs.feedback.gitlab' and '.github' in app config can be used to specify hostnames that should be recognised as the respective Git hosting for the feedback link. +To identify issue URL format as Github or Gitlab, the hostname 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/docs/features/techdocs/FAQ.md b/docs/features/techdocs/FAQ.md index 5ce71ebfad..3b479f2a15 100644 --- a/docs/features/techdocs/FAQ.md +++ b/docs/features/techdocs/FAQ.md @@ -45,3 +45,15 @@ metadata annotation is used in the build process of TechDocs. But when annotation should still be present in entity descriptor file (e.g. `catalog-info.yaml`) for Backstage to know that TechDocs is enabled for the entity. + +#### Is it possible for users to suggest changes or provide feedback on a TechDocs page? + +This is supported for TechDocs sites whose source code is hosted in either +GitHub or GitLab. In order to add "edit this page" and "leave feedback" buttons +on a TechDocs page, be sure that you have `repo_url` and `edit_uri` values in +your `mkdocs.yml` files per +[MkDocs instructions](https://www.mkdocs.org/user-guide/configuration). + +If the hostname of your source code hosting URL does not include 'github' or +'gitlab', an `integrations` entry in your `app-config.yaml` pointed at your +source code provider is also needed (only the `host` key is necessary). diff --git a/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts index cc451c3a25..4c9ea04fe9 100644 --- a/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts +++ b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.test.ts @@ -18,8 +18,10 @@ import { createTestShadowDom } from '../../test-utils'; import { addGitFeedbackLink } from './addGitFeedbackLink'; const configApi = { - getOptionalString: function getOptionalString(key: string) { - return key === 'gitlab' ? 'gitlab.com' : 'github.com'; + getConfigArray: function getConfigArray(key: string) { + return key === 'integrations.github' + ? [{ data: { host: 'self-hosted-git-hub-provider.com' } }] + : []; }, }; @@ -80,7 +82,7 @@ describe('addGitFeedbackLink', () => { `, @@ -99,8 +101,8 @@ describe('addGitFeedbackLink', () => { `, @@ -112,4 +114,29 @@ describe('addGitFeedbackLink', () => { expect(shadowDom.querySelector('#git-feedback-link')).toBeFalsy(); }); + + it('adds a feedback link when a Gitlab or Github source edit link is not available but hostname matches an integrations host', () => { + const shadowDom = createTestShadowDom( + ` + + + + + `, + { + preTransformers: [addGitFeedbackLink(configApi)], + postTransformers: [], + }, + ); + + expect(shadowDom.querySelector('#git-feedback-link')).toBeTruthy(); + expect( + (shadowDom.querySelector('#git-feedback-link') as HTMLLinkElement)!.href, + ).toEqual( + 'https://self-hosted-git-hub-provider.com/reponame/username/issues/new?title=Documentation%20Feedback%3A%20HeaderText&body=Page%20source%3A%0Ahttps%3A%2F%2Fself-hosted-git-hub-provider.com%2Freponame%2Fusername%2Fdocs%2FTestDoc.md%0A%0AFeedback%3A', + ); + }); }); From 0604a3a9e71931f82b6377eb74030bfa8e1fc914 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Tue, 20 Apr 2021 08:16:30 +0200 Subject: [PATCH 241/395] 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 242/395] 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 9b8f596aefb956a0109872f05bd187ea1a833a98 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Tue, 20 Apr 2021 08:29:27 +0200 Subject: [PATCH 243/395] Changed to patch as its a nonbreaking change Signed-off-by: Brett Wright --- .changeset/tiny-ears-love.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tiny-ears-love.md b/.changeset/tiny-ears-love.md index 52218e2ecc..9c3d1613a5 100644 --- a/.changeset/tiny-ears-love.md +++ b/.changeset/tiny-ears-love.md @@ -1,5 +1,5 @@ --- -'@backstage/cli': minor +'@backstage/cli': patch --- Added support for Datadog rum events From 40d1e11cf36f83ee62b5e5e285dd3e629dfabebc Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 19 Apr 2021 19:58:47 +0200 Subject: [PATCH 244/395] 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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

%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 e7532b96ed30ea25cce34402b857c7ab87587140 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 20 Apr 2021 10:11:57 +0200 Subject: [PATCH 245/395] Fix typos Signed-off-by: Johan Haals --- plugins/catalog-backend/src/next/LocationStoreImpl.ts | 2 +- .../catalog-backend/src/next/ProcessingStateManagerImpl.ts | 2 +- .../src/next/database/ProcessingDatabaseImpl.ts | 6 +++--- plugins/catalog-backend/src/next/database/types.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-backend/src/next/LocationStoreImpl.ts b/plugins/catalog-backend/src/next/LocationStoreImpl.ts index 1b9e9bd92c..f970234f09 100644 --- a/plugins/catalog-backend/src/next/LocationStoreImpl.ts +++ b/plugins/catalog-backend/src/next/LocationStoreImpl.ts @@ -78,7 +78,7 @@ export class LocationStoreImpl implements LocationStore { return this.db.transaction(async tx => { const location = await this.db.location(id); if (!location) { - throw new ConflictError(`No location found with with id: ${id}`); + throw new ConflictError(`No location found with id: ${id}`); } await this.db.removeLocation(tx, id); this.notifyDeletion(location); diff --git a/plugins/catalog-backend/src/next/ProcessingStateManagerImpl.ts b/plugins/catalog-backend/src/next/ProcessingStateManagerImpl.ts index 6cd846d791..522a7a327c 100644 --- a/plugins/catalog-backend/src/next/ProcessingStateManagerImpl.ts +++ b/plugins/catalog-backend/src/next/ProcessingStateManagerImpl.ts @@ -33,7 +33,7 @@ export class ProcessingStateManagerImpl implements ProcessingStateManager { errors: JSON.stringify(result.errors), state: result.state, relations: result.relations, - deferedEntities: result.deferredEntities, + deferredEntities: result.deferredEntities, }); }); } diff --git a/plugins/catalog-backend/src/next/database/ProcessingDatabaseImpl.ts b/plugins/catalog-backend/src/next/database/ProcessingDatabaseImpl.ts index 7c56fcd259..7e9bf78691 100644 --- a/plugins/catalog-backend/src/next/database/ProcessingDatabaseImpl.ts +++ b/plugins/catalog-backend/src/next/database/ProcessingDatabaseImpl.ts @@ -76,7 +76,7 @@ export class ProcessingDatabaseImpl implements ProcessingDatabase { state, errors, relations, - deferedEntities, + deferredEntities, } = options; const refreshResult = await tx('refresh_state') @@ -93,7 +93,7 @@ export class ProcessingDatabaseImpl implements ProcessingDatabase { // Schedule all deferred entities for future processing. await this.addUnprocessedEntities(tx, { - entities: deferedEntities, + entities: deferredEntities, id, type: 'entity', }); @@ -183,7 +183,7 @@ export class ProcessingDatabaseImpl implements ProcessingDatabase { .select() .where('next_update_at', '<=', tx.fn.now()) .limit(request.processBatchSize) - .orderBy('next_update_at', 'desc'); + .orderBy('next_update_at', 'asc'); await tx('refresh_state') .whereIn( diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index d89a3b23bf..22e9e90c8e 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -32,7 +32,7 @@ export type UpdateProcessedEntityOptions = { state?: Map; errors?: string; relations: EntityRelationSpec[]; - deferedEntities: Entity[]; + deferredEntities: Entity[]; }; export type RefreshStateItem = { From 6c4aaa849508e2a1fdf05862737bb3e3d5769e2f Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 20 Apr 2021 10:56:47 +0200 Subject: [PATCH 246/395] use Default instead of Impl Signed-off-by: Johan Haals --- ...l.ts => DefaultCatalogProcessingEngine.ts} | 2 +- ...> DefaultCatalogProcessingOrchestrator.ts} | 2 +- ...onStoreImpl.ts => DefaultLocationStore.ts} | 2 +- ...pl.ts => DefaultProcessingStateManager.ts} | 2 +- ...cationServiceImpl.ts => DefaultService.ts} | 2 +- .../src/next/NextCatalogBuilder.ts | 20 +++++++++---------- plugins/catalog-backend/src/next/Stitcher.ts | 2 +- ...seImpl.ts => DefaultProcessingDatabase.ts} | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) rename plugins/catalog-backend/src/next/{CatalogProcessingEngineImpl.ts => DefaultCatalogProcessingEngine.ts} (97%) rename plugins/catalog-backend/src/next/{CatalogProcessingOrchestratorImpl.ts => DefaultCatalogProcessingOrchestrator.ts} (99%) rename plugins/catalog-backend/src/next/{LocationStoreImpl.ts => DefaultLocationStore.ts} (98%) rename plugins/catalog-backend/src/next/{ProcessingStateManagerImpl.ts => DefaultProcessingStateManager.ts} (96%) rename plugins/catalog-backend/src/next/{LocationServiceImpl.ts => DefaultService.ts} (97%) rename plugins/catalog-backend/src/next/database/{ProcessingDatabaseImpl.ts => DefaultProcessingDatabase.ts} (99%) diff --git a/plugins/catalog-backend/src/next/CatalogProcessingEngineImpl.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts similarity index 97% rename from plugins/catalog-backend/src/next/CatalogProcessingEngineImpl.ts rename to plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 41ad2bef8e..934ab3a1cc 100644 --- a/plugins/catalog-backend/src/next/CatalogProcessingEngineImpl.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -27,7 +27,7 @@ import { Logger } from 'winston'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { Stitcher } from './Stitcher'; -export class CatalogProcessingEngineImpl implements CatalogProcessingEngine { +export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { private subscriptions: Subscription[] = []; private running: boolean = false; diff --git a/plugins/catalog-backend/src/next/CatalogProcessingOrchestratorImpl.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts similarity index 99% rename from plugins/catalog-backend/src/next/CatalogProcessingOrchestratorImpl.ts rename to plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts index a8e9b924d0..f97d86a75a 100644 --- a/plugins/catalog-backend/src/next/CatalogProcessingOrchestratorImpl.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts @@ -82,7 +82,7 @@ function toAbsoluteUrl( } } -export class CatalogProcessingOrchestratorImpl +export class DefaultCatalogProcessingOrchestrator implements CatalogProcessingOrchestrator { constructor( private readonly options: { diff --git a/plugins/catalog-backend/src/next/LocationStoreImpl.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts similarity index 98% rename from plugins/catalog-backend/src/next/LocationStoreImpl.ts rename to plugins/catalog-backend/src/next/DefaultLocationStore.ts index f970234f09..b21fe9da02 100644 --- a/plugins/catalog-backend/src/next/LocationStoreImpl.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -26,7 +26,7 @@ export type LocationMessage = | { all: Location[] } | { added: Location[]; removed: Location[] }; -export class LocationStoreImpl implements LocationStore { +export class DefaultLocationStore implements LocationStore { private subscribers = new Set< ZenObservable.SubscriptionObserver >(); diff --git a/plugins/catalog-backend/src/next/ProcessingStateManagerImpl.ts b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts similarity index 96% rename from plugins/catalog-backend/src/next/ProcessingStateManagerImpl.ts rename to plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts index 522a7a327c..91090bc139 100644 --- a/plugins/catalog-backend/src/next/ProcessingStateManagerImpl.ts +++ b/plugins/catalog-backend/src/next/DefaultProcessingStateManager.ts @@ -22,7 +22,7 @@ import { ProcessingStateManager, } from './types'; -export class ProcessingStateManagerImpl implements ProcessingStateManager { +export class DefaultProcessingStateManager implements ProcessingStateManager { constructor(private readonly db: ProcessingDatabase) {} async setProcessingItemResult(result: ProcessingItemResult) { diff --git a/plugins/catalog-backend/src/next/LocationServiceImpl.ts b/plugins/catalog-backend/src/next/DefaultService.ts similarity index 97% rename from plugins/catalog-backend/src/next/LocationServiceImpl.ts rename to plugins/catalog-backend/src/next/DefaultService.ts index 4125f96ed1..3935f6e4d0 100644 --- a/plugins/catalog-backend/src/next/LocationServiceImpl.ts +++ b/plugins/catalog-backend/src/next/DefaultService.ts @@ -26,7 +26,7 @@ import { CatalogProcessingOrchestrator, } from './types'; -export class LocationServiceImpl implements LocationService { +export class DefaultLocationService implements LocationService { constructor( private readonly store: LocationStore, private readonly orchestrator: CatalogProcessingOrchestrator, diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index b196d63897..c3e0a6bd9c 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -64,12 +64,12 @@ import { } from '../ingestion/processors/PlaceholderProcessor'; import { defaultEntityDataParser } from '../ingestion/processors/util/parse'; import { LocationAnalyzer } from '../ingestion/types'; -import { CatalogProcessingEngineImpl } from '../next/CatalogProcessingEngineImpl'; -import { CatalogProcessingOrchestratorImpl } from '../next/CatalogProcessingOrchestratorImpl'; -import { ProcessingDatabaseImpl } from '../next/database/ProcessingDatabaseImpl'; +import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; +import { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; +import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; import { DatabaseLocationProvider } from '../next/DatabaseLocationProvider'; -import { LocationStoreImpl } from '../next/LocationStoreImpl'; -import { ProcessingStateManagerImpl } from '../next/ProcessingStateManagerImpl'; +import { DefaultLocationStore } from './DefaultLocationStore'; +import { DefaultProcessingStateManager } from './DefaultProcessingStateManager'; import { CatalogProcessingEngine } from '../next/types'; import { NextEntitiesCatalog } from './NextEntitiesCatalog'; import { Stitcher } from './Stitcher'; @@ -259,10 +259,10 @@ export class NextCatalogBuilder { }); const db = new CommonDatabase(dbClient, logger); - const processingDatabase = new ProcessingDatabaseImpl(dbClient, logger); - const stateManager = new ProcessingStateManagerImpl(processingDatabase); + const processingDatabase = new DefaultProcessingDatabase(dbClient, logger); + const stateManager = new DefaultProcessingStateManager(processingDatabase); const integrations = ScmIntegrations.fromConfig(config); - const orchestrator = new CatalogProcessingOrchestratorImpl({ + const orchestrator = new DefaultCatalogProcessingOrchestrator({ processors, integrations, logger, @@ -271,10 +271,10 @@ export class NextCatalogBuilder { }); const entitiesCatalog = new NextEntitiesCatalog(dbClient); - const locationStore = new LocationStoreImpl(db); + const locationStore = new DefaultLocationStore(db); const dbLocationProvider = new DatabaseLocationProvider(locationStore); const stitcher = new Stitcher(dbClient, logger); - const processingEngine = new CatalogProcessingEngineImpl( + const processingEngine = new DefaultCatalogProcessingEngine( logger, [dbLocationProvider], // entityproviders stateManager, diff --git a/plugins/catalog-backend/src/next/Stitcher.ts b/plugins/catalog-backend/src/next/Stitcher.ts index fe7a378338..3e5e3ac24b 100644 --- a/plugins/catalog-backend/src/next/Stitcher.ts +++ b/plugins/catalog-backend/src/next/Stitcher.ts @@ -22,7 +22,7 @@ import { DbRefreshStateReferences, DbRefreshStateRow, DbRelationsRow, -} from './database/ProcessingDatabaseImpl'; +} from './database/DefaultProcessingDatabase'; import { Entity, parseEntityRef } from '@backstage/catalog-model'; import { createHash } from 'crypto'; import stableStringify from 'fast-json-stable-stringify'; diff --git a/plugins/catalog-backend/src/next/database/ProcessingDatabaseImpl.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts similarity index 99% rename from plugins/catalog-backend/src/next/database/ProcessingDatabaseImpl.ts rename to plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 7e9bf78691..cf2d4e121c 100644 --- a/plugins/catalog-backend/src/next/database/ProcessingDatabaseImpl.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -59,7 +59,7 @@ export type DbRefreshStateReferences = { // enough to get the speed benefits. const BATCH_SIZE = 50; -export class ProcessingDatabaseImpl implements ProcessingDatabase { +export class DefaultProcessingDatabase implements ProcessingDatabase { constructor( private readonly database: Knex, private readonly logger: Logger, From cf101c539c0fabbc22e0c6605402d929c520e352 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 20 Apr 2021 11:15:25 +0200 Subject: [PATCH 247/395] tsconfig: skip adding catalog v2 migrations Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 6139c4a7f0..d6cb6f4c96 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,7 @@ "packages/*/src", "plugins/*/src", "plugins/*/dev", - "plugins/*/migrations", - "plugins/catalog-backend/migrationsv2" + "plugins/*/migrations" ], "compilerOptions": { "outDir": "dist-types", From b2adf03b584f8d690a0e1b0db5b558943d1c6cda Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 20 Apr 2021 11:15:47 +0200 Subject: [PATCH 248/395] catalog-backend: review feedback, reduce scope of `handled` Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../src/next/DefaultCatalogProcessingOrchestrator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts index f97d86a75a..1880b5d17e 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingOrchestrator.ts @@ -210,7 +210,7 @@ export class DefaultCatalogProcessingOrchestrator for (const processor of this.options.processors) { if (processor.readLocation) { try { - handled = await processor.readLocation( + const read = await processor.readLocation( { type, target, @@ -220,7 +220,7 @@ export class DefaultCatalogProcessingOrchestrator emitter.emit, this.options.parser, ); - if (handled) { + if (read) { break; } } catch (e) { From bd6b2eefb5798d04c281c9f89922e33d326ffb0b Mon Sep 17 00:00:00 2001 From: David Tuite Date: Tue, 20 Apr 2021 11:10:33 +0100 Subject: [PATCH 249/395] Add Datadog plugin to marketplace Signed-off-by: David Tuite --- microsite/data/plugins/datadog.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 microsite/data/plugins/datadog.yaml diff --git a/microsite/data/plugins/datadog.yaml b/microsite/data/plugins/datadog.yaml new file mode 100644 index 0000000000..7d47906a68 --- /dev/null +++ b/microsite/data/plugins/datadog.yaml @@ -0,0 +1,9 @@ +--- +title: Datadog +author: roadie.io +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=datadog +category: Monitoring +description: Embed Datadog graphs and dashboards in Backstage. +documentation: https://roadie.io/backstage/plugins/datadog +iconUrl: https://roadie.io/images/logos/datadog-white-background.png +npmPackageName: '@roadiehq/backstage-plugin-datadog' From 9fba7470d793bb249e067ea89b328677750663b1 Mon Sep 17 00:00:00 2001 From: David Tuite Date: Tue, 20 Apr 2021 11:24:39 +0100 Subject: [PATCH 250/395] Add utm params to roadie marketplace links Signed-off-by: David Tuite --- microsite/data/plugins/argo-cd.yaml | 4 ++-- microsite/data/plugins/aws-lambda.yaml | 4 ++-- microsite/data/plugins/buildkite.yaml | 4 ++-- microsite/data/plugins/datadog.yaml | 2 +- microsite/data/plugins/firebase-functions.yaml | 4 ++-- microsite/data/plugins/github-insights.yaml | 4 ++-- microsite/data/plugins/github-pull-requests.yaml | 4 ++-- microsite/data/plugins/jira.yaml | 4 ++-- microsite/data/plugins/security-insights.yaml | 4 ++-- microsite/data/plugins/travis-ci.yaml | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/microsite/data/plugins/argo-cd.yaml b/microsite/data/plugins/argo-cd.yaml index ca753f682a..121c833cb4 100644 --- a/microsite/data/plugins/argo-cd.yaml +++ b/microsite/data/plugins/argo-cd.yaml @@ -1,10 +1,10 @@ --- title: Argo CD author: roadie.io -authorUrl: https://roadie.io +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=argo-cd category: CI/CD description: View Argo CD status for your projects in Backstage. -documentation: https://roadie.io/backstage/plugins/argo-cd +documentation: https://roadie.io/backstage/plugins/argo-cd/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=argo-cd iconUrl: https://roadie.io/images/logos/argo.png npmPackageName: '@roadiehq/backstage-plugin-argo-cd' tags: diff --git a/microsite/data/plugins/aws-lambda.yaml b/microsite/data/plugins/aws-lambda.yaml index cc3d59d188..f20cc0d393 100644 --- a/microsite/data/plugins/aws-lambda.yaml +++ b/microsite/data/plugins/aws-lambda.yaml @@ -1,9 +1,9 @@ --- title: AWS Lambda author: roadie.io -authorUrl: https://roadie.io +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=aws-lambda category: Infrastructure description: View AWS Lambda functions for your components in Backstage. -documentation: https://roadie.io/backstage/plugins/aws-lambda +documentation: https://roadie.io/backstage/plugins/aws-lambda/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=aws-lambda iconUrl: https://roadie.io/images/logos/lambda.png npmPackageName: '@roadiehq/backstage-plugin-aws-lambda' diff --git a/microsite/data/plugins/buildkite.yaml b/microsite/data/plugins/buildkite.yaml index 16c6960898..4e9b1594d3 100644 --- a/microsite/data/plugins/buildkite.yaml +++ b/microsite/data/plugins/buildkite.yaml @@ -1,10 +1,10 @@ --- title: Buildkite author: roadie.io -authorUrl: https://roadie.io +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=buildkite category: CI/CD description: View Buildkite CI builds for your service in Backstage. -documentation: https://roadie.io/backstage/plugins/buildkite +documentation: https://roadie.io/backstage/plugins/buildkite/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=buildkite iconUrl: https://roadie.io/images/logos/buildkite.png npmPackageName: '@roadiehq/backstage-plugin-buildkite' tags: diff --git a/microsite/data/plugins/datadog.yaml b/microsite/data/plugins/datadog.yaml index 7d47906a68..266627009c 100644 --- a/microsite/data/plugins/datadog.yaml +++ b/microsite/data/plugins/datadog.yaml @@ -4,6 +4,6 @@ author: roadie.io authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=datadog category: Monitoring description: Embed Datadog graphs and dashboards in Backstage. -documentation: https://roadie.io/backstage/plugins/datadog +documentation: https://roadie.io/backstage/plugins/datadog/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=datadog iconUrl: https://roadie.io/images/logos/datadog-white-background.png npmPackageName: '@roadiehq/backstage-plugin-datadog' diff --git a/microsite/data/plugins/firebase-functions.yaml b/microsite/data/plugins/firebase-functions.yaml index 9a1777754a..0b98948f88 100644 --- a/microsite/data/plugins/firebase-functions.yaml +++ b/microsite/data/plugins/firebase-functions.yaml @@ -1,9 +1,9 @@ --- title: Firebase Functions author: roadie.io -authorUrl: https://roadie.io/ +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=firebase-functions category: Infrastructure description: View Firebase Functions details for your service in Backstage. -documentation: https://roadie.io/backstage/plugins/firebase-functions +documentation: https://roadie.io/backstage/plugins/firebase-functions/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=firebase-functions iconUrl: https://roadie.io/images/logos/firebase.png npmPackageName: '@roadiehq/backstage-plugin-firebase-functions' diff --git a/microsite/data/plugins/github-insights.yaml b/microsite/data/plugins/github-insights.yaml index f127f88a3c..3515065916 100644 --- a/microsite/data/plugins/github-insights.yaml +++ b/microsite/data/plugins/github-insights.yaml @@ -1,9 +1,9 @@ --- title: GitHub Insights author: roadie.io -authorUrl: https://roadie.io +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=github-insights category: Source Control Mgmt description: View GitHub Insights for your components in Backstage. -documentation: https://roadie.io/backstage/plugins/github-insights +documentation: https://roadie.io/backstage/plugins/github-insights/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=github-insights iconUrl: https://roadie.io/images/logos/insights.png npmPackageName: '@roadiehq/backstage-plugin-github-insights' diff --git a/microsite/data/plugins/github-pull-requests.yaml b/microsite/data/plugins/github-pull-requests.yaml index 4172cdff6b..8fc0dd5a6e 100644 --- a/microsite/data/plugins/github-pull-requests.yaml +++ b/microsite/data/plugins/github-pull-requests.yaml @@ -1,9 +1,9 @@ --- title: GitHub Pull Requests author: roadie.io -authorUrl: https://roadie.io/ +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=github-pull-requests category: Source Control Mgmt description: View GitHub pull requests for your service in Backstage. -documentation: https://roadie.io/backstage/plugins/github-pull-requests +documentation: https://roadie.io/backstage/plugins/github-pull-requests/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=github-pull-requests iconUrl: https://roadie.io/images/logos/github.png npmPackageName: '@roadiehq/backstage-plugin-github-pull-requests' diff --git a/microsite/data/plugins/jira.yaml b/microsite/data/plugins/jira.yaml index c32455c7d5..3342a2594c 100644 --- a/microsite/data/plugins/jira.yaml +++ b/microsite/data/plugins/jira.yaml @@ -1,9 +1,9 @@ --- title: Jira author: roadie.io -authorUrl: https://roadie.io +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=jira category: Agile Planning description: View Jira summary for your projects in Backstage. -documentation: https://roadie.io/backstage/plugins/jira +documentation: https://roadie.io/backstage/plugins/jira/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=jira iconUrl: https://roadie.io/images/logos/jira.png npmPackageName: '@roadiehq/backstage-plugin-jira' diff --git a/microsite/data/plugins/security-insights.yaml b/microsite/data/plugins/security-insights.yaml index 4f34f79027..1761bdf30a 100644 --- a/microsite/data/plugins/security-insights.yaml +++ b/microsite/data/plugins/security-insights.yaml @@ -1,9 +1,9 @@ --- title: Security Insights author: roadie.io -authorUrl: https://roadie.io/ +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=security-insights category: Security description: View Security Insights for your components in Backstage. -documentation: https://roadie.io/backstage/plugins/security-insights +documentation: https://roadie.io/backstage/plugins/security-insights/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=security-insights iconUrl: https://roadie.io/images/logos/github.png npmPackageName: '@roadiehq/backstage-plugin-security-insights' diff --git a/microsite/data/plugins/travis-ci.yaml b/microsite/data/plugins/travis-ci.yaml index a6b8c6ebd7..7cb108a5d8 100644 --- a/microsite/data/plugins/travis-ci.yaml +++ b/microsite/data/plugins/travis-ci.yaml @@ -1,9 +1,9 @@ --- title: Travis CI author: roadie.io -authorUrl: https://roadie.io/ +authorUrl: https://roadie.io/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=travis-ci category: CI/CD description: View Travis CI builds for your service in Backstage. -documentation: https://roadie.io/backstage/plugins/travis-ci +documentation: https://roadie.io/backstage/plugins/travis-ci/?utm_source=backstage.io&utm_medium=marketplace&utm_campaign=travis-ci iconUrl: https://roadie.io/images/logos/travis.png npmPackageName: '@roadiehq/backstage-plugin-travis-ci' From 295589e13672b40a27fc4a2b45076121ae93a175 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Tue, 20 Apr 2021 14:00:21 +0200 Subject: [PATCH 251/395] Satisfy vale linter. Signed-off-by: Eric Peterson --- .changeset/techdocs-eight-camels-hear.md | 6 +++--- docs/features/techdocs/FAQ.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.changeset/techdocs-eight-camels-hear.md b/.changeset/techdocs-eight-camels-hear.md index 5c3df10c89..8f2479f6bd 100644 --- a/.changeset/techdocs-eight-camels-hear.md +++ b/.changeset/techdocs-eight-camels-hear.md @@ -2,6 +2,6 @@ '@backstage/plugin-techdocs': minor --- -Add feedback link icon in Techdocs Reader that directs to Gitlab or Github repo issue page with prefilled 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. edit_uri will need to be specified for self-hosted Gitlab/Github with different hostnames. -To identify issue URL format as Github or Gitlab, the hostname 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. +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/docs/features/techdocs/FAQ.md b/docs/features/techdocs/FAQ.md index 3b479f2a15..117471f749 100644 --- a/docs/features/techdocs/FAQ.md +++ b/docs/features/techdocs/FAQ.md @@ -54,6 +54,6 @@ on a TechDocs page, be sure that you have `repo_url` and `edit_uri` values in your `mkdocs.yml` files per [MkDocs instructions](https://www.mkdocs.org/user-guide/configuration). -If the hostname of your source code hosting URL does not include 'github' or -'gitlab', an `integrations` entry in your `app-config.yaml` pointed at your +If the host name of your source code hosting URL does not include `github` or +`gitlab`, an `integrations` entry in your `app-config.yaml` pointed at your source code provider is also needed (only the `host` key is necessary). 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 252/395] 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 253/395] 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 254/395] 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 255/395] 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 256/395] 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 257/395] 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 258/395] 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 259/395] 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 260/395] 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 261/395] 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 262/395] 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 263/395] 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 264/395] 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 zfPn)$Kmk9Q+ibo0UimO!jUn4~EP%s!vy-8V-#skhAgO<-WP5;0{!1F5k_*5nl9#a& zf38zEJBePsH*)dgP)p#v<)5UQX}~Qs%K-klk93p&kzNg`W}PO>?{Z_U)*AzI9K?XF z(xa5_nr8?cc|RIqlbC$sRVVfJ?oOc)4oRzUE5{$?;P0Sl_NWphi{jS$ysQ(2+{q!m zN3kYQcRAZ&P7#thL&|u+Exz{6K;cLyd{EL_0XmO{PpDu@eOd}i@h^zM} zEU-Q-3C)T5Qyk(?(BIRxXMfk`Ztu|#(g@hqjk%baC4;5YG|un+A9;G#MEBnxEu}JF z;<@WGt!$df`zl7fa(B*JJu!$ifh@B(qkZ3Ag1k0KA0~rc-L7pvIcd#rF$qXI6$=O0 zGpB+iwz>xkOp6$?*!Rx7<7tFSV;S%mg^H;!#k{{N+iR@xi=}PU{Q*>d9l9o&+VqX{ zSSQBB(SVnm2w_oyPTqjBmCIk^Ye7l`v zDq=HWT23z=A24;9$@u`!*U9$V;neRb{MV#nk04D)7VL#l_r8@irzBn%7|nsj-uQtJx7^|-F5E_=}H3$X`k z%-M5HyLjZQ(Sn?|W1dxo8)~6QK8Le(c$k5smGo6r&z75znzAQ4;|tbCn(N-+uMvrq z7z7V~xlc?|yxvSy093sWGX$S0289Xyg_#rGkW@!s*kGDKJaPR7(++YHF{2L&PQ6oc zM3=vDL+nX-V^PIGyn;fF%E6VJzow0WvXpZ^9689&rkwYJ_CK z*o@i#3XS;@vjWD|_4UdOdH^T%*TP#AKR^HOU|7e_;Ef<)9WedsOq%BOVr&g2Yz;zu znDl!N;|Dqlx9c%^_#8gYo!jP(<`ag8g&`EwS*+5~@1;WspgkvIhc=(=;&N58&!Vv+jnw$=d>j7U{-i{tjyJ;hsD}1w zV@8I@_pkE)$79delf@ID>e!-KU&(&+@UytxW~KRA`qssrTgDM16f4=+OUd>*QZCMe zs~!~)muvQ~fYzWJKTq@(9Z$*tM_eisZo409Ff^}eV=4E*yK-9wJo=XAVAsti%wU~N1NNvj?wXBLBGz1(7 zUM?g@{;CL0IMqkd`eLI^o6+Lf^gaaX0pj$kIMERYHL7Fl!0j=Ut|?D%xPR>S6a-bHVH0b#9OcSlMP z1iCfZn~C#BTz|Pb|NW%!z}Yk#{ytxnlR(jV0yrh>ddT&>yS-x!qNMrrMC{1F*|fAP z$HTc6Q?f>nM81-q@jVYU#gw%4icRd3Web8k_lTfsTc%@lR2g zY(rN2`CmM3=Wk)l z&1qO>_iYqOrf-!&L##vyh0BfW+HBN_!|iM6{=4H1x;I_~lZO>rSP6oVZ;4>UdX70= zFEW)ZZ>FPUc^fG7)$H)Sd(lnP^>q)wzo<#VBpRriv_Ha@6UAnUQ{gvGqZ4_0iIC6mDTkMS`f zw?L(21k^%#?kp2{25|N=gD%JQL7KgW!{SdPelRT1%#Z~m}RHW9Tu7%z(UXg5G>It2nN6Y&kqScxjh!0#(4sbjAPc#YNi%sv9ED zx#1;jI(AFI!aaH0rP_&|R6NCnDq&gmR2Y@}XiJ#-v?t_n^bO}C5iE8N@IX4V)!Xe{aJYdvamv|lyjH9=Fs(+O+#v{+@-*^-+C_mD!;#_@|^`qCidV^DgEP+V2Z>xo|PIArbHcu$JpA zPon)rRZp3Zy}hozXHHhG7*ktf4<3-{;>=9nf;z47j@R^prk$Ck31qm5ZgV)RP+gs} zv(VEA$#Zl09@KYCe*7|DU|B6^-$ODzbQ5Txl?5{Zg{%bCwo6XS*V2;6Gx`_398upl zShL^m)|-GdWnS-$AJ&B@bN2uE9!uxmgT6yqNHO9o}1=Wh&KE&4lN9#ma(3m8|)8LZ5{efCS{AvuYr3#6%dcilw4 ziAriCv?BHZjo#RwtwVfasG@3n&9JQF*$0TV zZmJu`^!boB^7#F<#!EoC=L}B+HIX?b0us8UOY!k>n2NH=( zO~>Y*^KTlWHM*eQM`P0D9(Z_%T#;~o36s|nYo@TpSOcD)iXU%GA6lLb;3dqPO+umOn25R9EX9adxz{|pB z+IUqIE_6vlCs#;hcgS(g%%`!}7gJkvQ?1iMi>W2B{A&dU7fh+0!HOyF zQAI6QzfK`UuD%}0Kpp*C%3yNM^q059ldkO;D6hSVE}PZII#ynwvnW>nd2>@#IIh^c zIiQYY#(Zm4_a)+sh>VS4bP)Em#rtIRuY;f)J`hZM==_&uBu@JCONysVb?NrGEHhV6 zQRbs~)<-L5C?)1nmYkJNKWNzbh01J$4s@!(tG+-j{dG5gmc#v6#CHf$qmFld@ zu_S8jV?glr9Nx^=KTcIzLDw*(g>5W5fF8$41S>M*r2ybX;au~m;>}G{Sk*~%*I|4XTGKvg9MD53IJ=*641Gul69C9?ERC&8A8qf%eGc0sMR23 zUtHGg%UVbQPDZ;tpj+mXvyK~(^FbZDjnhR6e@n9i%I{i)4gN$XOn|vdnwwx+g_$~x ztpd6H<)1K99bobM;9y5^v2!HF!4%WX7!xI-fI3MX8uNb`wsNP=&(!A0KM;1*`Ut0W z1#iU~cj)_1EQ*(ZEwx7hC{Y48aHD3gCOJz&^ye-ZR|B8dRH1L>dVc8l<2Hw1TSn|{ zf3S*;OH=f5y!`h5qIdYF5WV%DTMGFYLaa_Kd&C7p06A1RDo8qEb==9hEy|Y&4qKUb ze0lS>!w(^ zGL*VQ5z@`+KCbpmyY17vgvBqBq$CcqYDtjFMs`>%PY@uFc;umK8T||Lb>X#sZv=kr z2tuzGYNZ_!*^p7=TwRPfyv8^=gb!#zj1mLJD3z(@Uv~H>M87VIFEolQQ>e{v>qGVt zVJzx093k{v!GuRiDXOQ}o}#MlD!&q?Q^pNmQsvE*40`_Uu2e`mygai=R2Org(7>H< zg_xbv)>vv#h;AUm&b55NR$D93tat14Fw494yT!CS46D1`nDvS3g0C@07W=y_U1VM# zkIx;M&~cRsAP#Urf34X8-z_!x^7pa16JIh*zx4%oMI5yBs5p?irogap& ziR*lzq`XHhw3ac8pT zQI3378Q)_6U8&TNk(wwSk7O`gZSWFZfD~7I0}ec>dV>3-&4|Xq@2m1gE##a2edud_ z9*~b)Oe7@oW}RotpupzvBN|$7?G{2Y>v-cO0dwFmPfLtF`n0r+KtTJ`%C+{U#Ahu! z^y{qDD5*AxL;zp5z?>g9%mCHdP9^)MqKzgLDsq>z??2kYXg{nRzU^k7ffg)>UxxT5 z!l6apn7N(TLAjeUS~}$o9vQy&={eK-i7ATX%i%L_dA6lJF_+@{pI`s@sXcGO*ok@5 z(PR!OqWs+hSu%qT#|K7Yuv2Sk%UHU7Y*vFw@MI|tBe`G5?-u_R=krY6 z@>F<*88d_S^2C#svcdc+5}ylQm&`uLNt$(At0#>;uO`@7V-zK~wd-OL(sG!net2LE84>w!*@S*|D;8Lz=pS%z_TYMobZjZgiA z)9Pa8kCpdhI#a|ojFf`J?bKxUFF`02vdF?|K^I?SmKdO+0e2+K?OQFrXZzIab&6T976VRg&h z(w?i^ItXj{i37DxTgQ83nhmF2b{n95IKe~vGO|#zBAVfQ7Z{;K-vh_`?ba#I;hxib z)R>9UA`7c}TQWIG9X~y^*9=Nt9OItnLrlm_gmi#(e5IYT{b?E!1}b`c@rM0%HWOX$ zdfZF)yZ0ME7=HK_m6=p4NObIN{5Kw%61o-Il+3IbXkTZik|oyE4V0UF-{Kq5ew{32 zhDWa0Z1N|(b#)xCq3%z*%XE)IbF#pk=8dA%V*OvXiS<*@n-9}rSL9n)4?e;tTWdRv zZojP{9bNu1f1y60IjvP}wr%ID#*`eDt)CYq4KHi}=J8{YI}b~x+d#OJ?YX8;e<>01rD>ej3D`cw%` zum*EqW0JG@^t!>Im*|Np;6__kNcWqmy%eyo=nc1+XH$po0XS7N`^xi*01kKJ(B18f z(50RNGZ`1DTBE*+%kInaPJ=t&6BiQBw2=H)x1wXR6}*T;cT-B&sb+Py>jybIES8(< z#V{@1=?-(&CH(k@!f~Qg?T%iNw_I~*url%t9toYlHEl5U7nArD#aQ6ctp5?P!VqFS zW2=Y{`H+qj1mv})w{kSMIhPhPg;5g*my=;KOzv2x?{rUsb6qaYMk>H7QlGS(&=7Y6 zZ#gem%K65A3#a#~bUZUzS~3pb0AIrIhwXz$QSp+Qe#mf6kf#uCo<7#Q>h(|pb_;z& zNoiSuIAM5|Vyec4;Aoh*t8JU4v~>gV#Nr40Sj8msEhx+aeucLy+59AWfML+_LZYTy z?2W47(sdkHXO(4-Y-;%jthg-oeEBtAU~PX(G5K$HgZ|ySJH4Cz%d%)cKbVq32ls~f z#e>P0I)alp_CZ+w^VblZ;>5mX@jT9CBY*^kAl01bZ!hDJMic#P5Mn z5KoGWgfLD!ooeNaUG7+0cpK{)NYx44ZH3R*SvozLzuHrjIjmrcpR5V|5gck#_G&aF z>goISRXc>IL&zr9SQe|i z_yl&k-v#Q4AZ*Lh=fx>Q(%TtQUqi$Kpi1_ptnvvk(dAlDWRHgM#>~`QUOP_H%XE5S zO^G3%_0lAM)*z!*Z8%rr^IhUYMThF;k?G=4jrFm4KBbw{#KRGTv*zN;UG$l#;fr*S zo2TF~p+VR}uA&W)1WlHAZf-}Wcmv;O0c}$k5Z^Dp zaSWso>Q4L<@==*17T|Zm!B-!M>rjnE!K`a#^VQWCcON&tTV4uk`Sq+^-o$M2Q`VCg?%%(mT0Rsm!+;2N`&Nzhcv)Eb!(x`_i}jxn%H9lDYV*y>-jH3IQuj`-UsFTAWo$Bp=DsKMH0oDi zAJ=xjICE10LgS4PEg5$c!gXKz9=igF0qtx*w+o3vbr7t;SIXk~B|@S!~hG; z9=cdX26~#|)%UZ#Z;_yPrk#+xVxdGh;sSrSN36}~ok9tN>Z-9XFX8%SUY0k!(=<`L z9CLbH9sd5!>0zUPd?a6oT=g6tj?gz((tlyf$%fi*DdelDo~o zhbD`8sV@$ebpu}$xLTb1$DV$)0#$Utt{{`1a#mETzQUl{7}}f^?_F=0?;t&4tKF|n zVX+!jw&I2<^hP&^vhPa-1(;;)NHRODV*BU14xBO%=KUm~b81R3IB95+st%@Z#8w)Oe%JYiu9l2Z&hfrlz?A0LU*>w4U|RsfxJD$=BEuk#ZELyZ~kG8<_OE`mdY3k|A4& zph*7399s6ueWUdkeT#Ok6lAB;dZX5VjZ+j{l-}i*w%n1$i1O-85|p4B&zzqmiMA7wJaokwBv=VHWK167ZQCy>JYKnjT{F}@Ol1*lGlfdfWx zg6Uj-Sq>>M@?Q9YSz@OumMzVCryVM80aUBdqWIz}tRj!Ep5D+_KS=cRj&gY~sx%|s zEgewU9{gQ>U9t;ZaRYv4_`k~?i$3e*?-92IJ>_+ct3&4nWy%_r)m%`l!@65%ZHzaE zQ_nCxWke@Xh&91ZDic!Nb9EV7Hz43M{1PI1M4K42aU?-(U+gXP-N6?N9k-4bI(X3* z-OD&$f>(71ShA@yS^{k!d2f@?etj{ro69icnQzDahZUmr`@v_f_zZ?p)>H4HW@tn> zhrR25e9$H0&WS0ysLiHC!EO;@bqGL;-gaeO3*-6c=MK&p+}kq|PyhrDdmK`1>>4_k zskvXjSp_UHE+$B6<3C|(@DgUsCnOUIELXY6_qgkZA^^IYFK;GC68dt6^KCngUDBhg zwzT2Kyvm|JV(wW032KF8rnqU+7pCT|B+L$e^Z?D$zJpJEJ8RygGUvSza)p-*FPboU zbv*eXP-O& znM3Inh+H9|VL8i!cf{xO4Yw^Fmxii`c*33jC-YumEo8jmHcl1D6A}Kt^*3K@QstQo zgO`Wdn>dCQ8=*KGf%uN#k1uSE6k_(j^&BIvXEjJTQoQ9)+9D2Ofcq zQu%}GZJe6P~%MN>LE^E6SE#IBb4=p z=gO}e*xciPL;sC2jz|<5w^NYJhb8^)SlkX{x)!)u#llKmz4ObE)s$qzXj+x7QBuk$ zZ>R{xTBH{W-fC2`?zigW(J59B4hFzsXj=tq zqf$zCU47c}Dspb|BFa|+U%j)ZPrlsOrOq!c*;n13`^McBd)pFzFOdw?!kHO~5J?G! z(opSBCi(`a?2>(LZxpzFKNu^4)45i8Sd^yBzR=4FLLGFvyo7omm2zTQu^>4THAb|# zs&xHUk!d(8BwY8kgjGP_fnr@+a1n-FWbGP~F>TD+A2cbXWG;%?9C)20VEumVcq|^W zRul8)nmb9E%cK&xpEHTqMp;B2_|GL;x&&Rgvyz&4?k9i3uH0hw|#b0C>;fDdU0|)tHSIrJHvC+`cC>n`5q5;u)a4~rxQ5>jZ+U2{tHvz%y z4jZv89PnQpu$Si5Zhkgtw)xu9QX8rzoO>}(nD|+XmiIaJ>ho=H3h>#t;w05M{4Ac5* zGR%4%0LYeE5(z6^(F7s+IG>v$Ulf3pPN3AYF%f~)XF_Y;!fL5|Qyi0W6oH+3rdo}8 zUhb%U4nju3Q+twST&$b8H|StS;Rk^o&hlnjF`|**ohN(Z5iafnJz(ys8uI>&5KvMm zs;?4!xvwhqVs2xuwxec1*1NI%a4~&4r7NN&Iy0j(@k_N#(;IHpg5CT89tUvx zx8KjoSUmsqQqshxHvFC`E2(qwgtJ({gWN>bbJ9LlQuMi&`uxs0#m|8NS+q$AV$|+&n>{5nWS){!Y<6l83&F-NM=b3^-BzHD9rY-$z zhqVxHn-MTIy_qCAVIL_Nj6MbrEPjZ+o4EL{>&H}0TNOKkjQRTWRdtQdNemkDb4Ne5 zjPi-20Wn<*e2WYktvRm#n!l=}|GCA+-eHh)0aDhPL-i3Agi6;(&ODNTWb)`t>i*w8 zUp06t7pS9>KBu4li+wMcReZpHx;bQN|CW5ubLbTi{k}Vk)$xAOc$Sft;NjJOlEj}Y z?jE$u0#BqazfE;bH@BPMAW3+jRZ-Usf9Q=9vuq~ZQO2BKlrYAMXeUN}BYt#s^?S{% zB562Stl?(eRF!D{t1=fMg78Q5yyAr&JqXG-Qy*4-NwGXiL|XPj`+BLXJM5|!*unD8 zAX<3Jcw=_4LsX%rz+RgKuA!?7WL={@-C0c7$X2Mixcj8>-SLE%aUUy(VsT0;0>45_QB<#2w*ny z?lLe22U!js;B}F!wEH2#FAjoy5trne=|{(0qv{+=X$c`1uS;&HxoU@)L>YTKqTbi_ z=bR1Op`u`ry9f*DW+|xb&G$vy} z+zLVJkDVC0r1ujl zN>}@d+DD`0^a#s7u-QIgh==zVGn&|D5_qQEW>?v_2u3sUl~`{x3ng*#J2?J z-8<9ztK4FD(zb4v?P+T2l%@hly@xe_zMll%Ccw2&%i>5&@4IY4d89%yC|)5r61uCb>!@u7bHk zKHzEg0ph4<3P5@^96Q~3ZDB`z2MKV6v~oOD^qUp1>*h|q58%@;+2BP5mT?nD8llet zP?2op>U6?p* zUhKg!5(se-gCQ*5|MK5EbWWM%J%WS{l3dOg!CXX!JF}@k<%f53#2TN-c zoeD9s{b?h!B@fm!`LrhvlFUn~L%h1zk}#v7z!g>xT)NLh^?g`oKAyTdIMI`Z_kf)j z@H#4L$wV+;nix!rWXgHUB^ErYdrTFDV`tBH3U^bzVa_2@VQ>AbJmvPeXjU9Vl7 zIqV1;{|DV`zY{vwenvwZO5+v1>-Z4_Ll?ZJt(^mnD47>BPG}xsoLt6fpDlgvkw2xGIgi%)6?1{=t{HjW>C$V?Wq*~iLyh@AtF ze9W5kOvrs{W;`ee;=ot;Y8p(*(gdwyXa1PtUdf|_#{R6!QU^{f)fuopUHxG|FBSzz zun`7f;dkroCg7vV40zwVd8gh`+ewWKgi;M+$UxZP*s_0egf3B)8>(~pk?8J5^M@+n zV2Imr%1>s)Dsy6(K!f2&&OgJmKenWd=GVeGcA`s%K!jRaxkgss4T#{WyFL)Yjf*N} zd9CZrV=#rut;AeM%L>)+pA)5hW$x(hZfpc}xQui~RgZsC-L4EL5w~7YQ$u)XM2~Eh z`rzg!oN~mBw*dIZ9y~GVyvfo=a%wQm!Gc{K6t@cQy}v%d>Yg*UNZh&4VUIa!%QNp# zh9Q@9@b4#T_6luVY-@mDV$4qSz3{xYMuFYKkMlj$n6{Vf=eu#+48|r{pQI3!XgPGR zLUh5bhkj)H;*4jext6lmEoM_dI5MwIwUUE%b_*oKM`kKHe-u6uw9kq1FQi=x-^sLJ zan%yf9-A?5Zhm3?rl}cPL#-XI)b%De#G?mp@IE?ieF+(m$lyW4uje_y`Heqfd!v9t zlPLvsFAN5CtFsrizO-B4$4K#V4odL=5wBf53En~h7Gz4~& z&)n5YZLyPctg?GKs_KpfNvL|D(@JIy3B4vilUu_IEInUWk#T{H0DArm`@ zB$Y>n#R;HqFKSwMW%BObs*{Xd&GgT?1{KsN*XA3JAbK{z`8oWMs69?B5sT_Xd{t&E ztQ2Oq&Og$RsqtET>vLH5T=J1tBGEOp=?Cq!EEP`LX25}$80E7&ZuL{&gzkSC#q%S% z-mBlcO1k#AtEkdL$(Ryfjxx+joIAXLxOXVXeGjVa~sY$&C5}yB?-n3txWmk7weyz}ES<4d=NcK4#1H>lQWjp(R!IKyp14 zf9|3D{BK-IgTB-AN}HJnW9+1bMb{I8RuF=lIJd#?FSF$Kc{#Dm$bFvRNNoXrjnfX`meil_aZ*GWYLsgxgG{;d+Kg8 zx#_Rr#wRPkAfUcF=l-1bpJR2YbRBw>c zI$01eIdMr6#PbJ|nZN_m&Eh9x*clUPeVBAum)7cm)L4l#QdhbRgMY&AK

_8v1 znyU5bT}(i?oFj(1fNGjZX0o1e0ST)cyjNfQ1|=mhvL&3VQ$ZQLUL%>dT`=WYplsys z{INQL#GB=?f;6g`l7qR(t?6h!Y6_v+5mp>`<tOC~`qQ;6`CHNn=?kn^a6+sz<!T>6 z?~k&4E6G3n>DF62O5>NlGA&XL=)r}$G}qa;&n#Ler;a;d-hqf$)6c(Tic*-Eeh>;Q zgOgQ1c{L32vNJHpL<n<K3aVU=y^=|97xntEad=3Utvu2#;dG|DK)Tb*^W%&nPA_X& zHd9WRc=&zMx`zK$x#>XiD+B+GomL8U{yR_m`mU>Zpa9%IT$EJ07bxDIPH(%s5w4N* zZR#@*Acc)={VZ(CjNCz|Ak@3^=cJU4``Mxrfg$4l;s~@^Dj_G?+&g5)yr1++Xo}qv zYB9<M30_b20vXMJW=BiMnZNfJ9sXRQXwADGBo^@VFr^>H?K3pJ-S)AyzccHS7uSw! z%Fh;pq7pyHRaD8YUx&Z0hE`5OH_t{~G5WQ(aO`F132No-Nb0bzR2)75X{~g*bG^(W zOQK~`?%|^|ghB>$-Kui@ayHyiPx-70QH(zj)yOnf8z_>ze6YB}@yB;1s=qq=5<aH$ zhAObWaBYUAF{CbUJKx|2SwXaa_u`lFv6y!sPELDmP#-gTK~tx#4ZAZIo#A7gzj@2w zTf*XuWWe)F=l{p|mYZA3gA{<2%t|S!lj61=pzJ0fJ;?I@)JoF1I3E+%A4^N9b#&-+ zz)DS2dkRih>6j`gtXy=DgiRI#KFiMr80qQA_zp#d-Ex%I^hw|dYq~u&NtSQObos~) zJfpt|swPKjYz!1YX0I#&Ec4z{Lnb7-7(yLLr^(uTk$*Q&{Z?qdAW!@n^-C*NZ&MM( zU85B+xI@n!(hr)Zs9+f2P<$<%zvuz}fyg?$H==g)qLq?Nn`Qlb$+lVd6O54rP6q@P zwCtM!Y0azshsS&R@z4AK8iU1L2>r5pWeUf&cYG?Oz#BL4_ccbQB<e0Rr$G5$joNfy z3<T|W)Ro3&tf;H#G`Mi8bvQbEq9Zk-86T2S-dbp^B&35tP=GkEKfpPzKjnF(L+qQ+ zm#r}vK44j;6?aS?c%=6+pLQn99;8Ri7n+=KcDu&g0ZeY^SuZ4O;Emj&Med$b<(|xF zzQuiZNM>uS9HM=Dj|Eptf&g)|8YMz3U^csK^L?m6r@995-xL?V=HVW*)jBEkSMEsv zX(V+59AUE@G47TCthfN^e8atOL47Yx3*NoC8~b=viESGG-Kv`Yxtp3C`AbAtNXT_z z-)<hP&P2*GzzjU`z`_gl`n9r#_Kni|Vo43Hx2l7gx9Ekr^gth~dcZRsI_KNrd3u&9 z%a?h5&_$8yIssqSI#R@Y+Ksgo@SSxkME{I|)IksrGpAAA0b@VUIvM(5c+joIK~_dC zK&S8XX?@rzH5Md9TN=o8qL)q6YjWqVwc*D?k&%$1-R%Z`9Exvd=;OfG22O{PreUqi zD4Ns|6jKF`VJVw<oBEP4H!iMOP2(imP{U&#o78~!q&irM7Hx+9z6hhdivqvRqMc@4 zcX`DTI$2xBdf=Dad>?;rd9z>|+TV!xX05k{b>xm5EauwT>}gf9zG#V71}w4#37Q$e zPNYFT>(~(go+r!!-$)wm{n@YT&zZ1vFwY)rMK;4E&VAA#;m1AAbu~6%9c-_W;Oyhr zT(0_YH&M<f<hf5UW^}HjKdH>1p~x?k+3#Cl*jP)Ieck?ifq&O;Z^B~Q&ajuf_3%FD zbEN3T@y|iHb(>2=E*#Q&E(`EJ!k511a@u_i6s{#jqgBj5{`@>Fl+O23W?@H%N8LX~ z5qyN(*o$JpVl`2eAvx(bF*v08@SOVykEMJ5k`hKA8Bn=>&(b%}D+8_X(yO<<E!hf# zos<YT9GW9Xn8_|8VQ*0g4Cvw)hd!o0=-;H@4e12{J6m)TZCq<o(`qXcpO^|+eu&4f z!UeKowodhkFUD4G5uIC~aNbs`pu2*}g-L0@C39f9Xsj|`%ODi9kN|qQ;T`T96+4Hz zf~i~*I$p5y?<@|K3M{~9ZXdwQb8#0d?xyX6^4dTrKcv~`;chXu^3c}3diiyh(ENJd z0#P|`bn#8!cyx}xPx!T}w+Q@|<+l-nb=HGu%GRzgv%KI^cyE>27p$y<tBf%*<P}JD zjt&PZ4`Jojt^;m$R*b9~yWm>KZ(qA|MJnxjA76pG#F``;N@u`BqZ3lg<B_>Yoz30E z&4S$b2Lmv*LcbpbP}cuZzYn9{Cm+%8=^0tj*HFbO<WqXqiwk#=;&o;O<a#R8gWf1k zk34IXXYSc>!T4cWfLIVTvIHd9m=5UObRS*R+&N}blP6{J;GSUJZJcPQ3>138G7+6^ zO_#}4zMI!}%-tlh;pI?Hug#h$oVBppqhEgcEBE;8i?wHCZYRU1IvkeXt(!9K_10M? z!4@wdiCoAhJ}J(RVgtqDLc9LNQ0bk&Q-O^lzrEKI^g9llK)>Kr^6i;S)Bj@uJeY4} zncUEYO!!%#gBM6O23;w)uh0c}gN0|Hpo2k&t2-}@*G_FD)9R@IImq3d|K~YZkIvC* zwQW1ogJ`wg{k3=zFn@f*x-LrBV%oQtd3kI%+gU_XmKX{m-fGdZoS(jG(%F4>1=A^Y zoB^=Fc<#rha&VSQHCQUHqFgIY$8t?(gZ-7U(-YDrb5>^L6kzhPbWWb?lo65&uW(~+ zu}|{a`$nB?PX2(5;?0uuw@Bwx`IE2A&rGnIcQ2E_5wNAW$bfOSdLS0kK}U7UIRO3Z zB?*K@(}*7YtQ(VrSKoBVZ4C)X1TQmWGAv%w-jXU`Q{DQDKx+wLf5?`J)C$x7x8j~Z z)8~r)pkuAYRX#5f7Z7y&t+V+?0M6>yRuJ0$h|>pbe#8VCZM=PXA*0VEVY+6*L|^P< zmx-^&T=tvWA20bWSK7OP?r)PJJ9ib_XPGsrqYR3!FBT0`no6!I<k)E~*HHK5K(+sY zNMO?HR=_iMZhhv6W}?w_^IeaEydY~V%AwBwlXH@;r4b&pjAJ{!sk~H!*x!?{u`+tL z(b7M`Sy_t~8CotTUrFYv=v{t*xtsR;g1F63CdPU3#BGC4y>V6e1)Z9ViJ^o{`@DS^ zthEhq?J5O6&sw)*qG7TJQ81jdF*ZZJM)wva)qBOy_j`-(PTz0gGzxGLWekyezEQ{E zddU-V5jP4(BrWegIO%fN+Mcyzy=i=lA8=xAlffDqMV<wpj5{L*Pamcln>UyN?*cE; z5>(n&p~hL5h^WlW$v?i|)K8u~A>r_q%(fjX64F{Ka<R6i^`HS1aJruR!1A0&|BxKb z-s5iuY;FfZ96eaq{7Y0~<1{9WbE{-=hYg7RI;~Y091LeA@ly#EWFPR$d)uBBl-XTb zo*QEWIl;H=<0&|?P9ZB*;RWM*F#}%~^M_tNP12`<iLT)j+!uzOKWd+CMUDsbLjnoQ z?0uzIh)GB*OvFvgvs!#lv|g7P8tV62z`tOGY1A!3b>U>hF;tZ%GIp15n8NKN!ZWuL zVlqV)s#oARl^0jr&(^{~_0<nGA9v{hc?%gS{v8vJ{<%0UxP9a6v-PNb)(FH$@wwa( zqZJSiqBzlQQiFRv0fULQB;(6X_?2ANr~D||SJ%OXOsn~S9++X8$jg3<I$m|A9T}9z z(0{Gu3jW7zq$%4EZhhyjyUlvvh*D|h4)4I9(R_vI3Ue1KX6MrDe-Z8q;r{jdVKdKo zlp0!{9n&FijF5!N{UYY)O-dn+F<)*eNeJH*Ngxtrlegclr?!JuePV?qic4k-tV}7X z%0lQ<vHfdTnOJ$~U_4PD-ciw2y49NkY8WLYqXz+FQ1;qgI`NSbhVuUkvVB6o)n2!C z<>v@(Yf3Q5ss=ZOfun3&q9_}-={bx4%>qc_qk_Y_Tak#hdbF(X?#*oTAYH_wH1DNk zr&@S{ue4-dwNnPDHdhJUonD{&`tw;L5?h+s@0+?@A*GGldOMz4^+kwDE^|rMC(9a0 z^bl;Aj%VxA64T`1=|YX7j97G`^Yrp{fwh)C3RxDK-4dc?5vzXrzC{KZD?!C0$4z$J zhjHui{YK{fWjxPuecOxfddc=&j7b2i)Y{`pX#wFX2yIiBWP;`%va}TQzRTrDSr2JK z<ZH8*qucJnSZpxk+tH$75!1*kfHu}0b0quQ)YeI1QK4^Jg`sQiOv&{|mxl$js+~y6 zOhqw$<8S6kS&(EUzx8@8u&W1sba&e>hh=o!CcDA%BY*hdc>th?x5UoiOSE$zYPzXW zJqfs_8ei@_3(to6%9C^(S?(-RW!a;hQ7P(JAxUE>>*d1~lcuXDoXdoBF_L#7o^n;B z4!{8C3TV6WLH@@XU?*=aBp@h~I`8TnsY0#jrcV~P8?P54myS<XFehVd)~EE>024q= zxR6Cd;}8}70y*+q2Pp?Su+l77rqko08Ts-Z?d`J+H0bxUPT*}q9*D3AzHVdbcF2;> zB3)Lq$QS6DhVlD$+)Z-k27^~Hl17Og`{A7gCk*I(1`w8?==9Xhq|PpWJ+%o0#E1Mp zJiU83)Bhj;|L*kG2}LE5IYkIHO2U?$b1Ew2uyRO3nDb#<XGGYXb67d%kmV3L?kzbC zS&nncip{XG%wcS{{a$^(zwh@Smp@#t%Vn?U>+!rl?)Te$|5ZRhmFFsg0V;B{;Jnjo zcEDB)RvSP%BbJ1=4{UH1&(?+4H6u6Z?6L|n`U~(l+w!bADL^n|a~HN{pTU#=ytswg zpkf!41j3T#be(58Y~vCgw0G+yP$S!Wa4`XgrNw`8Fr1Gp0#w~Ww)F&XY?EYlO122$ z@jYjP14X}=HQCcD*7aVEc*!(a7Ji`h`%}kET4~$<8_Bob;yuB-!MAOkbMDlTc@4Bg z0Htqg8ZMQ!hU{U||0`C_uB>oT_O`Iy;iX2}lMM1z8!eMWQ-Y~QnYyK3JbygYR97#& zy)Y+FH{Fk4>F3(JLHSx=*st5{q1)K~1Db35c`ZFDqHf%-^q)|CH7oCwpw;}e3ldAW zkGg<@{M+)ZH7U)RyxZCE+nv<+xytp)IE_)IkBUYU+)VUk(|R381*pG;uETHUtKQYg zz{P{7eO~7kPxA;p+Ul9`k58j0ZiB>)dQl7HL87gzptTIXu0U%kasI*o9#CFX1m}fY zfI`KdB<(Z|OVXuFpp8`k5C3hix&FjZi1Qiohc##m@!uMbG}0&I)caHks|5hLJm`Ku zuc;heI2m~WrSbjVMY}J+g<;x+*RsS<4S`2IbQ2wadC5~lFQ``BQ+)JB?`?qwXK=Z_ z3U!@3coPbo?|d{W=5oHw*=rK1O%Jr{eM56Z^@ffyPIfSw4Y}bj^>I3x%bcGjqr1@+ zjryLTeqDj^MDp{!GJ0*HwE{=XF*j^}ZKhJNBn_8Om37+npBD{Z;$%$gINfKsh4I8y z!55;QF-4_@hd(052(CW|0?61WYZ8;YhH41^4%t?vHn80A*shwPf#~`G-JPwu1SRHS zy1;dr1P(Tt+RoW{RiYJOP?noD9%-CxTg}%k(x-3DF2}0W+<wEj_yh9L!tK?c%t!(A zH}y;&?u53tGI+%fBYn&lD&thaL82)igE*x*E01fcaQ8L;xv<~oj4zY8z&lif`2qVY zo}$J!1^ToJX&&AU9|^09za-;xeaQ?{?@oQszG=ffFr+lgrc*xN=QIqY0+zHMH-jm& zzlo;Ct$>Tq5PRperiM31`M@f9ngyi`R$ePe#JODR{wy~il5Q^#yZX;~_FRbR`&<gx zEHc$aF1pNxu#r3Ik=heQ!VTSeq?}gN^FfAeM)4x`ywBM}9?Vud7J2-2Vv1tzNKeBE zkVGJIX0VBS7v-PFcqv%x!*_K(ZS(x3feu0RJT$^-Qe#re!{V)uC&YZcd_l>gQnT?8 z@8g@pmtJ@(F+ovR741QiXm39&d$gmB<R0RCQAx(&=y3zLexFu1dkxHOIm>GMFP6>G z4I6`*R-r-`H^o;-KODaDBx*+TlzlhOSW{nD5>J=m`!;^_%JT|c_WpKF)x9t<*LmDk zJ!5?uZWHVgGF95sb?rp(a)V_NJ;i(^6Ki0|PD(EHWE_#CD2=g=dM;1_s2A*Y+v~RL zs9;K?>$0e=v~<~eg0fKTrIXcf)`z_HZEG}P;*k|Z{+>;vw@HZQib|#u%jT3tFWU4P z@B*t$ON}>M!q9<Yz}SAW;gvl{bxl@S(TGXFSdawdhsd8+`>3tP(R(8MdiSuFix~~V zjex_fD23{ty$?R2gPyoLY1@dZpYY(0;~cu267uRr9@rlw7y*V|Pfcx!TC2}K=j<tI zyaK~bD-k!WwR(I)o{?<fX%XF~x+qynq?wY*N0Ms9cKhg=)yo~rh1vb1zyMs%n-(rk zslR;amF-d!;Bqr}G3xRBzdGyh$h8QOp%a|KH2WUA>dg+OnT31;n$T2<4^C~MZ0IaD zi$+?GiHb>}G=R3%<^`ikg~x{g@fG|3#Me$>Nk!hdouN2K3+bk0C65J9M?7vIR7b&M z^0`4=_C%OqBNrdHzsbbR<oup^xtK&MqwPD^V^!?R{Nq&c`Og&$noU5{iVIna&JVAi z0lU3`r>-SoXZ8x84iBCFwsEB<tBrq2Hw??C0r3B7OXwjQlF3F+RF16&BFip4xSh1N zKfWTy#ssP}1o=wQCdqhEzptg%Zy(Cc#1}lBs@in~8;C8dQ83XhJ#rGyk-6y9d&IOC z9p(!1i)(W{w-}>aN~0Z`HTO5(%1|)(q;9RR9&O!PpBZSNxiSN&oL=tx7Es^Luad5( z&!4O0$w&_q2IWrI+Gh&wUdsdjyOn?WPv*p$jZ<lR<2&L_e?EI0zW{i<f`yMxqI${# za`qj0B1wzBmv`;ePCkmKyCF}~eBJWi&Nrm@+BgR>Mm)LEMDO<v@2SR)c@o3U3w>lB zDND>d6Np0eZMR%lUzu_Zp1h6V{yDi}8t<Jw8EpdCdXaQ>e{b=(5#71Oizb?f?helZ zjycDH=BZ`_8ty`uCLW(uonI2_rWe*Dl2+TwC5qcP=+eCrNA{Qr{{<Smn8BbP`oxI` zmh{CJTUqv+VaN`iwzoisYstTK&!+Xo=1=$-DmCmQAY^sLSsI4}|K`u+^#`BF3D&!3 zCr+EW6=CB3@F0}jY0rGfQ9b{oVzQx)bwQIJF1?NMZvGn$uF0?g<5M<jI@tr~2o<<Q zb5JBizTrmxF~aEcV;Rql$CPV~Finm#;G@D3Qzs$;K;mO~%lOOHc2L01s=D!sR3HZ? z>8S#=xS5r&ZjIdjS5iH!?Ho}K1WbTnAC*RIINEUF>vkEK^VdF(R=mI(|G|=`)Lg1@ zlz>lo*yM$T`Xts49O#<C2hIGnbplL@yp1zvPg~OIJA1|K9pJ-ND11usX8yS|gd4g4 z?qNccVi=Z5v)jmlHD5HPfZu$zT-8(MbbNG<`CV1JoZ(YacH`DPmXkxHqsLt<9oDNm zU5cNcrBu+BVaul^mnpxVKvozs)}jx>cuj}s!*YtR5iR@!);^X}ZwJ%H>fXysAksE( zaE!>SzZU+a3_OSp35%)pw?4fobZzr{mO+uNQe0N6(}S@ai>C~@O?5=eX#L*bEzejt z9*B*Zk$G>9fkkpbc0FdY%BwY2ULF^HP6VS%7@UFe(j0Rql_K?eGRIS6q?>-d6;?Ey zA3Nr2)Z_dZFK44cw}&?5obpK+u9wnV{sFIJclBTB5*hI(tD0u5arfk&iy3mxfv6LN zv;U3Yf%8(n>%TJ(Y^fX!yEKK2?v)#I0C69mt2OG$pDqPL-<7->I!;!FDjQG@ndsKg zo(Yi;cv|_=YOgTm;{orqUx%Tm7j|9xn6s+ks~C{YS=F=d?(57Q$UKyuel7L$C%1&u zzeeOQyVka?6*cN4DzWySk2ODek8j?8HqQovD$n<RW^rsqfOE?8p{BKG4TK()(r^#z zBOkOO7Yi71=|pP?aDpy&PZ<8sdpm8)wGW~I$I)}`Ka&k@x+lxtNvLr&)AqELP2Ya# zdp-xs)ud<QX3|1APlI0);(yvfv}x>6EHk(9>Z?^as|HdToH=70>$l<2TP^hA!~~<o z6BxP_K6BEW_iNImJ5#TpTRJWI(9!081!~x=$qjF^Za$LnQ{j8g@QmEkPeOWbyeN@? z6W(4s=S|OF4!TS`g4zk}Dy&=eSlAk7$4J~1lMw*!dPX<kh6VZKQ9tK$g7bwF1E#(F ziU$6`ThD4O`uTr&pW#~M5F82OosZ)DHJ13_$@sF+MLxg1u#(mRfRL?!vy&A}e%{i} zPYu@4(yDXT!mF|iA51qaMb_NRf3voNi$c}xlz2+qcW8BUNe&ZphsRy0YP=ET;kV~z zL0SddWiWZ{$;GauVMx92<>;4y?eI?5j!Q227KB{60Iz;W%RF=i_VJdmU)o65#Utf) ziFiAt-o{#QG<$KT9SxUvr^$K$RDlng`H1R_f~K#D)h<3loufLprgU>{6JaJ$8>nsI zWM_xb72PXI1LWdX+bUSD>qBYa0)y-2>jiC|^2MKgh!3*4C#x##jD5){G=#tLeRtpe zX3;bT{iE&pY7aW~)g;!4t`#-_&n(RQ%;`n)R0B!!FIaWh6y!5c6<gGI>Xq*~iuNj) z(*h@N-1tU^<hjq%3+E^P;Sl7aD<5grH{D-WHlA61YnGdqG0x|$dI8kF<<EfIHDBwx zm$Z3{;B2<Y_vCKq@ybKol8oi8hgyFWGjO4k#?ftPe_nQ<Pv@WgBs^t{n%lm_qXCiR zZimc}_UM`~f{$VIv(WltT7AQN=*Q9Ll5LPzynpDvJttud{)<+85C1`t^ql&72UyS0 zI~oO+9G)WI@X@Iq!{r65`&{1`=4?Fwc6<sNpU&NcT0iOaC1?3x0&)@ttUDz<A1>#D zkGbJ5@Y?&ywdJ2k)}+ogu1CYqwp+l!7NP(QY+`6j4S7$+xN|^su&uP=TdjzSs7X`L z?Zfg=cm1&&jn4X`7WZ9jEA?OC(%C{_`y>yk33^o~O)2BeO>CmJN9jdxzw<Vyy0X6u zq{+TlfWl48(IeoRg)6;zT2i^`pSFh0j{LaFUn5w2fk8?#k}vXK^t{mR*1_|~BX$wj z>RCrl=ow$?zkuXaEJNmSs5Zq+f_aS`Rn87*)x9t@W}V4hh928a2XxQq;YBOmcniCC zDE?gEq1jG#ycy-oUP)qM8a>E)6J(s$H4iF|v6H*`^Ix9sTus8+O{QfA7u^|mer&+% zwphBB*f#|<Z_NnZ+wjo^Q|#F^1Bghrzz<*cR*?8jBWIoy%07rK%~)d}A@mlhMe<$G zF`FUxN~;n&pUG5ZgjBnj0vhVOL=(FVxb@{JWnRm#t*m^5R`0wozxt2M?|ORVxPnPK z+&ZO6nDhH*+G3cU-1BW>Lz)CH#0NB<S36KpfLQk3?lMVNEd@uSn(rXBa|RbzF90w8 zq2GRE1U@+&dH;Ff6r)rXQ82T^h_b3KWmjX1$CW*Nx+gbbz!mkIqJ_<CbdVjRqk6-) zYC}17(;HaF8+8-vuFWsiwt0yW{I1;Idp2^NU?-<s7}z**SjSVP9u^yaRl`xDsA{SD z<1~7zgU0R?WQ`11cUby>AdP8L*|_d3q(@O>8qW*`5}~7f1S=loP@B7tVWyL|vE#8u z%Y9YQ<Lmz&o&AAoPK%9u1Q)y`@lEOw&HQfzF5;JiBF)wlN?5?{`<o*9_D0Xf>b8r_ z5-f1`HM-fIDvHxs`0Z|3vC%6gaNl&cn8%O-l);q)woK)|Q2)el#n1AsK1tyAY)5V@ zR%IcSH``JbmHGJr-uk&#1Z8W&>cx;YftzqTm$+xy76Nq%z;j%oXo`Af#!b9{`?rZm zjvh>_q|Qi90*n98pBHuR$Seuj35=FRi%EMUEyV~;3$bJ(9CoNiG2rJu?hPOfw$w&d z{p%GuD(^s=?y_#IFV?!XgC>|uY<~~xqoYkmfvNkIJG(Rxr+WJRl#91+{*((QI@kWN z`MoH+qg*KmXee=GYwbWotZJjxICwWj>PTR@VlF2#`c_q<m<CVcd;@1c#_@ajfBk2? zJQH_j`03nZZj146uAY-Psb~Si%;wx#p~d0so(z&*T1SJ<<B>*q%{}j1ew;OY)HnkS zqXN<78_RR4ZpR2gxa;64Iv=OB40lOLhK-u!Du(;85)>mlm&^orH8MjW_=0Wt8F-N; zI9<Bbt}my%;m20#lw~w`Jd+J0Z^Bjrpz}J2{D3^G+aHT%78!|RQG@3!ZvJNdn4N-> z(ZyH)990C>A6H}DQo$|l%HkGaUHw3z;M*Izql8<=;sXa8x~i|&!?6y1bZkQ=J<^lE zJvY8KJi?K1wq9~Cty<fs7Ye*6_y0dlm9x@>%)fHED3csr!#`LjJ{X56NOLg1dQts2 z?-(zl=)(}?#lP1DUsm}Sih;<H%phU)D4<K-kx8-bI-sW@oFf<^I7cpbgtG3qao+}z zmYVPw7J_!ny_R<XChPZ#t>)mfdTa8(Pl(AXTfGb;&6qY@R=F?!I_HrZo7C>nk8iDf ztuR4ry|-|b;V~)Mr`7D`h7F9i@@W9xSPy}|E)(%DEQVl<qQ0naPbm6T+<a)l`}EU^ z;?6myKd>tX6M8YN<#Q68fPQ4o-F#<ehPH!3^wVFr&qV679NcwNpFI$#9=mf!XnunH zY$l`Pc%CM0{TIAS%6b`>!)t7_tv>3xbe|5pD?XSQmpoOLDftaE`U3g8Ki6?3IT=Ez z>f;;R3)b?Eb$`Ha08}&!%n8rP7h1O}rJ0&(waD_Y!xs5Vn=uI1Sk#r({VtJRn)H!< ztPDS)(^IjG?yA-v?tlk=wVT}h01C_}M{@?7$-KuLG-&(i6+OK|own6COR!A*-%UXC z49o0z#wW|9jT-}ul3YgM15Ey`t7nSec&hlo4XZ8;{JKcgWl4*g6BG^IrQ<V0R<AsC zm#2_8+sHVVlHmT1Y?IXPV{gY@epU4#;EfF?X}``a4}DqO|FJctRLio`y=K7kiv6NW z_NP?U=MgWNrM)|>MD%}(l73jqkw&XxPVE3Z6rPo6+@#V-j5s16zdh%?6mcPBCxu2! z*@(c)DTOw!BBiqxj$VLRfXAzPPD%jDu-TrjW7$)!uh&;sm~cp`nM39#Pu9ZDqzY5K zX$XodN~e_OWEi1a7Hs48H~ZHpn*INng(rJEyByp2t^m_m#iF3epJn}>bQN+Ik5fQP zOnrtg0kE{8=biG`-(rsDnT*YOoT~|ySnuE-#Ko{wOuX*bB-tkYpFu?9dg*%X5a@9* z>T>q!p~c^5`OsBtEp`og4a&WXF{s%C+*AP_D3v?j?XmgsQnU-O>%%{P-a)7E5BTeU zO;%KR>6udT2{o5m>BsAh>`QUCI*)cCb_4m<uWTbQPSEheN@dcivSQj3wg864@&lpP z9EJ|r>{REK>_cH@bOfp6P;art2p965s}$8XV+Q?emg3&Grs@k`x}Awsi>=H(D(teW z=#q*D)(F#hjn#X_doe1<GbJPB)MYcbN0>puDnd`jPupoSGg69_WY!g1iJMN#-uq{l zeyM3T+c|5xa}FclAUToJ;FyHoV-HD2H|`L<xcLD(SANdM82VCw6zc?@i3cc;BEV`( ziB^7ZP1rCAUH=Y*moEAUwAXB&yexFR=GN=OLnnG}K_V+`W{2qCPpYV`M^Dd$yfyY0 zJnQFVD1Jzzr{nQprltc5AS_U$ya2`Y3G!7X-bqx}|EakWRgQ#pCR?sayG94Kw_{pH zyZQgHPBerA$fTK?xsM0$%=mM=9Z3$-jrz>WWaN6`dMb1~b-fVEDGUh;y16<PwK?IP z4uDD!gA#*_i#`>$B-bEH)Uq?#Z#6$-ugAak*=x<djR}rFo(GZEeDgW=&-Pb8Oz!RQ z8C)0s)&twztgOvw`OV8Tl$j%7zDN4yica$^YaC{BzlwM`ZKNgfkY~GNGU);Ou;1aI zf!r_D^iuE*=*RoV%|yU9Gr1%F9D<#jT&AR5_RS}XnNGSuH+DIRu>ZjYy3D7z!xMRM z;jk1+HDIe1*{Y_~;V6B#ClPVoLb{<l3sWdp<0J)@w?|!4hCPdHQH{i{vrHlro3QbE zKvVN!`v+g0uZdwi4|?ec?!l2aM4U|+rl|C1itFAK3%!R!<(Cg%a<0gd_Nu%S_D>3> z$gV2U$OL+K&!vJpfU(E|8VXL6Gt4HF)8Q87vm3ci?--1o4=%8{ozUPl2kgj3VB@Xi z?&71Brtku8I$UzQg6jH%s7B0x7u^!XOnt7XQrcqzEk=CVzOyJ=44t0k2VTzmK^Uxt zFI~BOd4Gyo^LOa8O#>!RXQXW*w>hMi;VX!r$h?QLvjH10Ld!OBr*0A^HDi~Pw>)tN z3FV~-ZO?!|1ZPIwMPrds*con!FKP&K7%@KOP^2OZ?RgKXk@9-CccVe{6$3VwZRr{~ z$$9ryvVC0VdoXLNApk|CeJCf^p%$3XJ7R;zaRHkzr|cecGq+{>7%oro@8=HnfRQCH zayPg|g|Bh2Dt<uTVtJ8z1t{lciFc!Q$A0&zAN;bs1Q$V?CoYiZ(02w9HWnXU2&l_^ zH6uDXp-kjl^u*s9fXJ$LPI|jHLLpU+qRzCBfA|kb@XOy-hM>OSXx=31NvtbCMwrF$ zbpDcmd@y&bHZJx!KLnX$vwUNowk_{;6nR&UV#gtWS^@!sYC4I30{{elM1hvgI?)Mn zGXg$aO{j|9LNj>0I{gPv<THqOL|kz(RJB5KlUkC?>z?8slb`x)!7+HXi3%e7jL%{C zK?`4V&-N6cX6ch$kxax&13J=9;UzqUXvb7e%Lk`P=~JV#(i%JC);@u*ACyXnxwPK& zb|4wuzmwZv?J}*iu^ozOe`R{21k;X@Kbjt#)2A+sxqF>*q=B7gUg*jY!1dE?K6xZ& z8WB8o46iXP#pcX!DFqwkuRXgXHClJm)J%1`U^-JjRDy8B$ijhZZZovFC;Ptz`NY?` zwjhMXt#I_Q(e#*5dwR77dO~*$MP<)YUSIT&8$RhYWLVJhUikaN>z7fPo^H><W%Ng% z3zF66^{n$xsj<Y+Wn4!=f-P|&dwBTTtg2$oHTN|Z@fd6Dr)<C~HzISUv^m1StX9$> zDCU|n<43XilC$L!Yq?cr^MhRWZVXuRWX*LDx4aI--CR%-Ya5BJ>n<H{L`3=iUoQaJ zJsWDbsrJ_V`Z#Q{mjA?{gwVEIPprq=m6FDZtyH!%e*lEY5JD-y5=bp}dSr%M2du}3 zTF66rdxgL!0JXYO%ttn2!q2{>cN*)isL6mi)}+btihC^P9AY`YtduNVD?z@{8-_d^ zQ<TmFjU36dCXXlamh%1++6hVTN_t#md@RvlcEb<)^y%6!3FTj#*}bcbzKS{BG@q#r z!>JX0l%uF4^X0@Orv5JYSx4;b{|`IY;s(IZZD8&(c^j-)1@XikL&%C7gN8<|F%4HC zQY?ML*;$$_pr6L35U$S7BCK5k0LbK8X*6h?(>k2wVvgN<DjFk8cxs7Uyoigm)?S{? z3!-pJbj*VDOXsU(=AvKE)92gLU6=#*Fyfo;EuPG+shc<j<3EoQrWZ$5T2d#MlG91S zX3Ye*VZ^!tF>01%?qziGQ!`CxanR(oPiuFun?rCN`89LZ{i|u>LwU(Ap_n$!xtA?7 zw<hqYFt<N3A*rMr&6oJaZlZ}U)@C|x3;#7u?PP*y3dov(1xp`a(D^7d=e9dj7_AHz zE4B_hs`l6}sq-GWP|5P?ky}Y7pa#6bldTtFSXDi{V}qWiBW5-Tz(e`-&BmyI%)ln^ zK}?N3HJ8~iZv5=@_y2Jd-mE8BEnRyNtovB0xj0!OH}^+^4fa!xJA$T5)z5>-m&$y~ ze>2(~KxIWGRC+wJ>t+_<KD8D7G+PQL_l8d-T{OrV5*IQHfrl6iY2{h}6ZRpC*C~pW z@qm;t+{Kk%QL3X~F-CQTm61G;g$^=IvKR?%ePGj>)pYAqM$*OpsKjNxH>;5|^zieq zj*j?i8IG6-X0L;QZ9+NJ9-sUM#3)J)jakig`sJBj+q%WwJ*A?%`<OYzDEY7UD&usp zMt?S(lYv`H+#{-qTWFufjF;WO<HjY`1XmI-Z|}p4k!0Ue4LI~C)l(h=97L;MiLvY> z>J?6u<Xq#xCFi@g%HO(kqpG=$(@^lHeNNVYo%-JXOpUdt+@}}Tkx~rP@Bws%3c{UC zuspjw3%o5kl!lm>y%rk5x!sg1^ms<@Z`-Bs8qK|u{_v_&J_LmgcJ9kvarH_8%+RwQ zR28%oqUXK}(EO9jmSv6SZYl{yq$c)&ay+JtZG4En%R2?~a{5*)Ddz7kSUfEA#A#6S zFTtHEca+TaF?;9De$}D7-O*mMfCnM;6!e@|tO|*W@Jc{k^3ksC9nQXPtD84)R>dyh zN-ae#2BcVdsqv7LuV2AL7NzFakRyrRnMGy}38v%~1_l0}C;a0TgwGIs9Vj;x&!)aT z&tF6QLaatya9BJMi^&aJ-no`BloQtwZ#9~Ec%L09G!G?VaSI{e+$}BW+XzwCv;?Qc zKoEqRt`_$G<jkVO+q@~Op(mq(Fv59#v!=h`%P13~ro^|$6s}d(Dc~}hP*hc#oV<9( zc6!QbXi5X)^LQ;H_%!FS6yCB?WGDeGk$`MkEcHj;?5*H13X-GEltW?yuX>wx_aYZk zn_{x3v>4uHo5hOJIdXIB)eXhta<QK7<^(_VwaM2Lq?}DPPGzh+_ae}Tc7%08{P$-A z|H92uIC`X-{G20OyY?>w*0C87@>Zt-YoB>B{h#*bcgJ6NjpwW)l<8LTh7*NSU+MxU zrBrW=G;mjd!Yx!06W3_)$eXCKY+yQn5dFo@+!>Sj`4C_!?LL_eSd~1<>D-skH;E%i zxrXpo%|4#FShc&SMhsDtTuB0+087>*48l&L<%QwO_4H+aX5$L=kqO{Lh~l%p2G0*E zo?ajTsEHouEy$F_{ebTlGe8qVy?1Pny^*=KHLx02Je%@4uodE?rVIoPK)OB7pUkw; zUpOfpaJn;Q;4!A<<tBWJA?Gno1kR=??i6_j_-MjPHHutgXnN#{hS#lEnBgk&4lB9j z4!BI;kJCAGI+#=!>)uh%YvN52;C3*-GBI~N&;|_aNgtjv@q2i#=#73&{>D4{{Alu9 ziW;N50=mvc4y=~IrGC2y$cnAjbWnTGKB1|ZyZRShkeF2n2o!i3NRB34Ed{CTVMxe~ z=KYt7`m`-R>l);K{m|SA&*T#G)|}^y+R&WVRdn9SNe^a^m+2*8;|wz+HHEpgDm*Or zrimV|{*7o&%tFNA9T<sDSmljIStrjs)ZP7<cGOz))m5<{H3|-maBDkof&+VBZPq@Y z^0bOh#Q*fuu*6}=c>E*qob|InUd?oG7Bp_HTQ%HMCAf8#?WId(Cw?XzcF8KGVqr^9 zt4DBe`c3f1)4cjP=)6-QZ~qJAqN#T-edjjyE^~!RbY2@g<10w1*JSKe&j(TKrMJV| zukxBQq6Y2{-+D4qJbdRDE=}Q$8Iq?T8DWn55{|DHtaR+OwcvZX&Hb?6osa$G$B+3@ zm-GH!&Hw6CewXZjUg+kWc?1}*<n#>&4NH=W3cYj?z8c}}Wp63PLzJ>to&on#q-#if zD>6Ohx7W~cvn!{(1%@j`N69sBsY+2hw{axJ{MjgL<AJr7NY_PTYF^7_bp<|!xuG8Z z0(YOT*NlBJ|9$gKCEdGr&;yHF*>r3W&{~i%=u&o9ob&$)H0@pM`N1a+6fj~QW$K!S z3E#-n)5}2n@A20lSL$fzHLf{{EE6Yq**$!(OjhMw!cT{w&EWI{ojZ+(<z#KMtyIbY zxPgy15Z`;XVe5kr@{w}otu4O-c<@6VoiTqn!}W)beCg+Y*yQiZuJq7NMj6cn)Sw)_ zFY6(xRrogO07;Z}#}9Sx^E3)nIWBj(mUpjy;z!h#+ZzwEVJDTZkx-wtilRW<Yne04 zM$9Rz{_XuI`n;g+Tl>K$`Z^)Q-yxv@<Eq6ecssyUIA%zv&B7XU!D)W3J;YQ^E3)fd z9P1wCWqekgiOuEY@j%Z`NP4q1O4LJ*6#=MI*+fQD-|uQrf;PcP28g&`cC^^+y}6<{ z_i~Bdm)$>SrYd{wX)*>F+&W^-A6yyoG~#a~i_)zEln7UKTvy2W7V@zPJknD2(Jxm8 zJGHKkwkkN*B||KdMB`?qUAN25(eH?>+hgWd>5hJs+k8)PEg7@kX>-p?KPN&_3u=ey z%d5858{SZ7MkD-5Ak}U}uL8#s%Q~`H;VS@fc~4j4$<E1u(<Vljop?+`{jmHS%1sRJ zdSh>b*qQsq3*EX>FE=#%fR<)j8C4E`OwVw8W4!0;s%~5ORBu2O{|*wiod4hThYAWF zk<YqMg7UP`3H|FRSO&M~@DZyzE&IG<zcXXaHNuPaO*1gLQ5N~C)X^A2?gy;8|HH35 zkFT#t2mF<sO>|z`lR8XtM_%qHI2L)Tkd9JaH-h1T=D3*IHk&u09diNOyc~q!I8TD- z(Wce4Q(lK_9&XDT2@Hw&Fr*>#U4+rnR)#2^OderJ9r<F%KwV&E)OoyOWFp@Jxodn| z-kk@tPg)<v@j&f=AdLt20%1}eew#ScNY^eSY-Sb?To0C>4WHNq@He=6x>QZu=J2lT zJP~K?<cF9D@`M88hY`y{>2r8BZq#cBusBuoiXGqnm&TJz`EqU1`aUWx>~_z4I7;xU zuQ9J-IU%H4@YN|HS*TX!W8zwdKvyrg`W(U84)q>xmNEG+kp}k)XAgbY1}qvy>Qw7Z z->|>_QA>yx7!q)<Vc>4k!ah5Rq-y@idSmcVdFt1zdwrJ#4t+1-^8n*)nL_}ID2BR! zZ~s@NMmEDtkK9^$_ThB)pFr@(lrNkSX6iddLtxzGjEa6S=j|7BU>M{TfUw3&-Qf#n zRov!E6oPd^&%Zq~Az6h)ORc_DB2TX@US?Z!nD%(=CDsk}<TPa0|Dd!_Yfpd%A(SnW z2_6#JGVZMeEFr*GF8=H+&+73q7`LVvKZF<M-rh}Z8}L+oF+#J>=&mAT8KVRk#`uha z+Gc~xAi~#o-<(RGigM)2^o9qiG^hvCNU*+MF>t-ftD6%qthgFjS#4snMAHo}j9niO zIn6@O&MBU<VMuZ9WyZ_^TC@C4NRgWXO9)GT2LF6^xJX0dzK6VTzsJYa=B78v{xp(; z<_5Ewj`pk$Y-|C@PR@}r(oF_TAykXgx&KM6)JG~kcV(py4580}0I~n<lrV3EaBGxi zuWWzRIzlx3jYqm4^{-hK8lZ_Y?lq%<8fpQi;ZZ7I;nETh$-h{WcA<XUJjAey^+v0A zzelexw&P*y4L3PUg3nt;wRBcF04`iNzO<=RfE>R7hroUmZeV1Hnc5B_FxeZoEpBZP zEw>*O4BviKST^G93N@=$X=O3mCIdB@%7$Q7Ce3*pS(Qp{`UvaW<{CiNh)fQaygDeC z*DtcLzU4?%RizZn^Bt;(6YrrarovAz;t7zGwTJX*lA0&K<yejq7^Cq()HLtkJmFDv z;;GY6Txu&TDVfi=d-z&6M9`z$7rOzj<Z(HYg~-qM?G05%!^b&k+-%jRb$nFwLAvdg zW<vjY-QM8(;An(Q#r?zFHs)S!Q(h(M!ul-TyRTYDcAx*f0HH`r8RuRD)>zo3zY6C( z84!CpTN@FL@66ULn;dZk^wLw2eM_ASyFAUe8)emX5qCCd$*`tY%1;<;BefQJSN!M{ z;0lbOs2{0U^sz+F+*$EHXyHm;+6esLnf$k0B0SBr=01o0yzn;k)HsB)?Z&tq>MAH* z=mz1tKH!(Pr%PC~J)sh<IPi>?cq5!5D{69mOLyRA+XcsIS4{9UUNL>5CpzKyCG=Lb ztisU0`3)*y_*Vs5O!;)07UGKkKv|nDRW`jbcXjfC9JNY!wtJ^7QCbQpRoQ3fRNg;l za!$;~w5_<u6-5?6%&s-|oc14)bhe4lT{1e@caxc>uy8m&A>PH+)7a*^-2^1HPqC~r zA(6e$9H8z=(X`*2nwlo7tgS`0WT{PS%fA6|(`Gg86J};F80FIPwicKX|I}_j5b383 zbBXzMU6EkZtQ6a0r}Y+NTi)~$o_Owzg@wr&r5G_J(E!6rf35(FSN*_mMFphx+unm< zhhsh$&@zJG)<SC}o}NlL+!<4x=6lV-3Zx&v+frTuyw24&-XVL|zBhA_njDSgkLwL| z7&&8gK5F@Z9of%W-{TtTx7=x&PiujB(=(m<V)6}Z+n*fXw-At{-Bn|qG9TDx{RsHM z4|^rE6|ZH>rTAPc_R{KjnA56zM}&*$fj~WD?&k24Z#>AH@VxFa;3IC&j=cek`}UIa z2|wJ;|Gi#_wf~#f=iGj4bNqHPpH@IukL)x4$wm*hO&qYAstBEb@wzqaYdbyAjuB?n zJAT1SURa0_PA2Y>JVcB2Oeq;b9^{Bm;!}d!mO=TaN0o!N2eM>^oQBfm_%A)jVr@F& zHlNkKPWtmQ=v*<RO+>&>H%Nb;X}Ea_OgF<cMV!3nEpj=yxCg0}J&v?Z1X5ithS|^C zZ@>L^B~s0_XX)DPb-6%`-M4G>vwuAAI~4WB<%j#{8cxP$puVQXor45f%hfds{C^Ho zm5pu1v)G*%9E8}h&F~-rZz+8FrXXJ-5C8^XIXUZcfXQ@>4T(Gy_0Q8o@J!kPUQ%&D zN<H8nr33EKiiFnZIBd7_xR5N+$&6TEPW{rmeb{WMJ+u?8R%k!$TDg=u!#e&*jF9TO zV-lR3qgh8)%tVWG&(=bK&r}IW%i>Yr0nK1ANdezPjgiq)Mtneq%|El2$nx46cbqu; zL8j5eZRH9Tmsw&MF{!t1KcCC`xh@q2d7n!K*L-t>z_a?|lz{;MixC-suQW70_dIBK za<gjlkqeO>&2oJ`4ac%A9*4!8cYKhuHhB({hb;HhJXg>R>|bw1p_z%hQof5HLAziQ z$6Q5tZX|km^p~jW*Z3<FexkkG+c~>xY(%t*&IdmaWsUz?wNMYk-QRJk%m_h7T3B{z zSPZ2_8y<vb{ti{nAQ5hK=^n-<e^xa5Y1OEByX*<U0D*UP;Hq#Mx3_KI9Ns6E=F`?} z_gG<B(dV_04EC_1#Z?mx&cyG{`@{QZLwC_Wolaej!2teY<Wn~E#49*INSG>ppx4G# zT7~ySnBmv=0bN>GeHc~jf@v)0ME+$U@dqvPzJ&^}^|`F=$(wgdxms=ZXg;~PB?rlv zOI`>d^;Scw>G7wXp=tDC<6o?p#}9Z-70b+ssH>%B-61g%MWv@71m9HuIDzr%`SS^X zSJxe8q2X||TCRqFo||er+j~DbVL~AiYl4TyPGsK4vzMoIm-oEq?F*Z!VTy_~$POaQ z-INx72~U{1_Bc;6MR?HjN;|jov$TyyMACy<_v6pv`+vZj<+OSr(ls!EHr~O=sW*t? z9Kw{iJU@{7L7w`aUzDd)o~<1i<-pbM(xetaySAQfdM<&c1qL*ovD%+P7lAz45yM1q zwk~5!jo@7HH;?!s(QiZVQ|_I=6(|ZXKUUBkE=P}=cf`|kfIA=!aE5(pD!Az2Zf^g1 zQ_kGEj2g-s`@|NVtdN47ZwqW)L68~{B)ZPr>42jVKu`&<=-=6EG#8oPa?uZwTo=EE z$Ozs<P0cX2yq1^~kR^)xa(^dEO?)K79(oc#F4KqVL=O2u7YnhoJzk|KDiopppK(>a z`EFooVN_31l8P?~{-*)m`c_`IOV;-#l6mh+;b<2%5G0=*1eFyJjrX&VD|U@VdMMVq zCf))plMu90nIhOYDdbGRo1^igVfY>uQCopD{H!wf2zb10R6-$>s+3Nx#Mvr(JTgA1 zRNZW|!ouNH#Ol<+w=%lrtqoaCNpLrcep5?P!l;YnZ(NSc=p~p6HPzX6Xu-0isjujR ziuLWNwp(Ij5Hx1<4Wo`p%DG<9WUct2nsCR+T&VdAq-lk_YT+t+=TMWjjq4fKunDpr z-RBkxH?_s)IboKp`<YeI5GN!N9o)Cp#^12=K^60!y0~(%bX0AJWZrj?MaGunV0pb& z(^LD*p!r9s_C0R0j}Pl!n!wqC_nC8@4@!3L8(unj?Q+A(Cl3m9-BB`NRG;+>hAR$~ zFizn9;~x_$>+4sHWbl&A_v$sC*&}%^Ln&1E+8qfe%opix%Tn)<0SBM$i}s9Kqe;uV z(IYmmRhFGMg;JU#@?LEG!%0@$w;|{C^jl|`qrPoQgKW55bf>wC-2Z7n+isfL^o?3> z@N?msnu6*ARGe8i50&*PNBWO-IrXKqUIUX7em$bK6ieMGpElll8=$kkz<M?yamZwB z@!I3-a@L_`nx?a}bmIR=ul%c%Uy<+9y5$4z>oaTfiPkeq1py1Fp0&O42`C4ke=Hp6 zz5(Bn3uxC>vrz>VkS~cj1yPpfT5k<hpZZ~3wW2$6A?sDr2kE059%asBSk>m-rmEpf zKW#}&TAM)G#%8hD7HUMCj>hD-hGX3V1r|-HsFF*=SUr?EF%Mdh42il5iu$8((9&|! z5|A9PUmI?3-_^=7(R}ZKr%=}^i{c?nMw&>e(E4vP;&3cBItj^b?_Mw>LV-CZ!EIU7 zVTI|v^0ScCvU7X=YiWJ~Hzu#NG$bh01o*Ymyv;SDN*<EZ9$e=>eLWWGK6cMB`gW4W zkcAl|q)dl|C>`0e6wHY7pk|zSb5;Ig_?V-Y+g|SY?2!pIM@ZfeOKjAu{6-x2KP@)a z&dg2GAZEw$GnWR!4&(S;xZz+Lt#JMolhtCk!Zf|Y5avBJ2PL_b#Jg`yGr<zu>M4@R z-_iO{3lp?2qOBfGx3i~uJvPEPE+$Lb^vE`sq3xa58PdBtcgdaZ>Spl@G#_i4#R{#L zd%KwvA=`?re+Z?E6Ux{EZzj~jAz>eaF=)iuPn3|+e<x}Xa}~d_6YMmVou_%Xraa#7 z5xRLmD5ni&)DgHnQSfx|V#+n}ZJ!HA$`*<n&9ikjvdzG|zM&N_9xdu=uobmhYPzej z2yc8B41r$<iR9-88vE$JTK~hE(~4?utsMfL^V!_oNC3~IueP-?uj6M*gYGru4FT?1 z0DgOPDxEti`D`<Jubx@XY2!)U)fs|8`zEc~W85~TdHL)Hta}GiIAlcM%#D(CCTrC0 z?{St)FZ^#7d1Y*8^IX^|LRmm_@^9VeKJqu+qHB7+<MdxCoZfCSRP77pB`JmrM|s<c z#~C*!(Sxd*uPaqH1iN`dTwDNd-?RGDD{9(p6u)HtTE7!+-wZDPp{en!mVE#+uMh_` zqAk~c&lnp%uo`rj_sJfaxtTHv+WCE^)a}~bodHh5&oht1fpvZ)O)0#p-gf7ePFZdr zBG@rjfAM#ax`Jd=k5xG<7^6_5lu;{9#S2oA61;&-{7}S7fKP?#!w6Qgy6u92U|wPo zid<;$IqO3|t{JflG2jb*GqW|R^Mj7;Rz4e>UJuQ8#0#F|ZJ^r$Nc0S^4}TTE`CIhn zK_4}VM!J`+fe}`)h<9*ZQ*L1#2b9b4Fha-$tXgRqiYo<rhutDE3)wA#%n|Nh&Yo?n z-iVpA$>^3NjnCmTIvfOcU1fb6%aL3!!|{!y2JLMd+!V~z|CF!-4A>W<m^i)|F9F4a zaDJIVty~Equ9Nu0y-^ePn(v6*I`Xo5zLIu!V04%JLDmcYAh9i0Mjtt?tITs$%xRlD zBozSR%|Wvvw9tTeWWigKnow67UKB~`ShvLULAPKrY}^i}U}xhEW%1Nv1`Dy!=uni< z5V1*2MmHasXy~KHIWEDCUz}uHLo{#O#GjK&J$q@42~-Jsr1pK`uWjebz+69L47yLj zUK#HeIg<@Ev{m9Xb$i>0DVqc9+_nu1u~eX;t*lIK!U8FnsO7FV;-dE;W~3mg5c+4F zgO9cyAF_oO9mH>;Q29uP1n^}Ox>Nod@&xj>3UCD1eTFyX{b)nKQ{1+2L#aw0WP><- z0wZpQ6^nPg*#2-5vz);nNalNt&Sdo~(o-pA^{gqY@+QJ+#6pDIKzOtCBi<YBu5@du z^Z+9q(PZ12;HRB8@Rigtz;fu@_uWA)>Pwb{9m%s`NMQ^8T@wN+$%F*KOfo#gU-ucl z{%xY$2J2N;&AUFBtkk-_{JzHoRBZ5N_5FHm3-76auQE_yrLDJrQVP>UQFZ)r^cKJ( z7(!y)@$IjS4#oq{{6k(M3nublAJRR6l^iIvnl#z3s$|{}?>Rc^Hb73E5b$_U(yTP9 ztu(*Pj3b3JYa!>!>GVB~pyO%*lQ5}zw`*@ZuQXO9OQb1=UTk2mP}t*qS956VWOL?; z6r!zM5P&96?dO6&*?VB^dokZe6>)$UXP`tCagLNK9~@0tO~BcICrWuf#=B^?iAs8E z!sZ`5?pDz9W2bk_Wj@y2?^aLI67QEz%Wml@(rB|a8e$P#tnNPZyXpV%@_}xp*%RjX z%Xn+6j|@dMG#BBmcR2GK?SQrcPkDFelCWRiw~H@Y(g8aeMZGd02N<)fV0h6G)a;rZ zmr@H%L#3dG6&V0!vk6v;EPrDa>d=><;Ls~_W83D|9_-c|E6TIg6P{J~bw7?4WqR+6 ztJ^#wu1W(_%o|%}B+C6G%9ly(Bprl0g5ZrDdt<PQ-`Rso<}Y&j#cgg(&czdA&ueTH z;-OHXKN2xZ-akk&D-u7HTh@<1XZ|KZcc#{P&{dE1WE8(tJ4%uxll44b!USo<B_XFP z7IN?leGB2JugYbFu@q?7{w;52v?i|=Bmi7Vv(@FjOWk6y@@4ysShy-y`t&dfIY1lE z<nf_bZJ|K{J!i^;C+@FskvrHSTa|9D)Dy>Yq)ao2r1?|HX&r0O5FTnCDkxkpA#$dR z==>@W-;mSJ=0nprGqt>VDZoZu_2-&>u>S=}%b%Il^$g7&JI-?)_vgV12!&}xL?!Z> z*ho>{A7V?6jGN0XQhk-t3sQ^Djg{21(|_JeTqvtK<dmj!B!fEtSs$<Iq_7c{vqTzb z2^<6G#F~a}bj0l{HC3iF@BK0#?zRTRU=)JK;=541gB$yun28y2`opGHJJhrIyB`;J zmR@J%gchTGH)vQ`51U?<6rcj|8O<3Ciu{{Su65cJGe_tw5mYff01GsjVXAqnkluwD ziL*)tNe;tU{t)gRnM=SGPox<&as<^L8=|dj<%Iyjnjm37!l9k)+njIrSo@w4<8f)f zjeYO7>JWqp0u4vw=K^#tnIeT+e^0d$TCB@~5^Zkpm<r5Ab7`&b`5b_AoY^S{^V8tg zzf?J8A8l_(pDIIqN*(n)frDi@PptRkQs0hzes?Hr>8`p@wVPV0l7EZwx1x;I@Topn zNQklKZ&^vp0&w%?8&8CH{YxlGQ}a$Q0DXKq1WD9#UIe{eztt5Bh9v4i@}+^-Ur4g3 zsPE=J0F&u+aybM`J-CR-;wgAy2mdwRsXqPs`62q|S#q1Wn&?Dx)3~5%oIakRxr`ff z8T&kqx%Y{7{s&*YmiatJiLKDoD;FJY!^MnXm8@^GV_!|+e)aFu%dx>OG<3_=1kdkY zJ<HsPUDxsy+*r|^<SQP4Il>|aV8?em7U_@R;Ypf|k>XrDV+Xvpb$lEpj3G`3j`^Uz zkwkF~(m;3d`yS7?PZ|jiO3cr}^k`MD5ehZX@dv0dpA(@C)dQ~M+RK-b25(_QX1J=j zJpTH+BUAL*mv3+zu3i;sMKp_@rxo7r(}?B4Fl0v&SE#v5H80jtcfBw#A}cE|oM$lQ z_s}3OiZXYGn*M*i03Yu&QIV+nRv@XF`^}dl6j|lb82q@`1H1o?X7~iZ`p{<HY!B7i zp%>Nc`y}3FDAft01yApmH~15o#0rnuCjH2anfDHNFfP&JvqWPwd9|pG+DAue^zYVp z5Yiu$)_-N{m$JE9D2m#Gz1zl;mBVcLb_0IZkTU?{@8WdAxXFfgS$zim0}p`Ygz6nW zgIBtcEGUJU!nPLi0iX6{wk)nySaP^fK5+qsVki5sx*mMIgxZccpEqHCS`e(^kh+@> z$*p*3iDh%hMyOdJg|N_R3r%%xfU=p$mu++q54#S6tmpJL3ZtQr1H#ybbR!}dzWC=? z3i8*oz`kbBB%b?5bVvt9YN!aKDp_<zo<HJ*tw43lOW4t&KoA}mIR`4i?L3D8*H<$q z>~ZnlHZFEYme+&l=(c)OO-^mi*`9@~)3%N!>Vu8HMJP^>T+w<7pR~lJ_eU}_bxeA{ zncoM0M=Qn?Ox`6HEji0r;uKN%Wls4(kh2!#KV2Ife|pwFGg$D(r0(af?a-93b_%zt z?D6pqPE<&!MP`D@GLM$~#!4|e=-;n2evs+#L7xN0r6&(8Ri*u9ULH~>Sn9a)Ym~9? z1GqIh!<oo=Z*Qz}%=+&=94Y9|p7rNYUg{&nDS6wU>pa>Pf-Zeb);EY(BTYF=-#c;@ z<F2eMh+aUkf_oZ1?kuJ%FBmX6D_z_F;=^GAZ?afozfB(ba2_aqtpmMEdXJ)89h1Ge z%Ixl4ZA7gTZWg=fMJ{UZz4Egzu|H$6G&n;u<4{zK+hC`=MY7H$fOX!jaP8uWvL+%` z^D<z9g>IzL677MqFzpMN{@cA5pDLTmt8!F;R>{KkWH97~g_luRcLyOc|1#t~K-r|W zblSMc{<@mcoyPk9z&dp?vHs~?+H(I+BYX_5Sfl~YwS1do#DHbgJ>PzG=H$=>lvj8E zt$uNXy0q?r0b!-fur%&sb7kJGeF}Hj&>d~md)^sZr5D4f3#qwG`os+XjN@*YbFVNc zMq>_bG9~sRkWo%~NrhAm(nmHR=tpTae&f5|WW(u(yv&gSX9n4NGu#QvphI*k+yy4w zH$~fZ%Xm5Av-9|{)AIXK)kMQ3!$5GCT;z*Zi0MJAGEh;~4MDE;MS@yJz1W0oPOsq- zYuLA!x2N$jy{>J|+*$T95b?P$eO)f-X-_&lZ8`A$0ucy3^(FiV$yJ)@%Eu|1tg?6L zo&2Phs*?w<^KHH$b=*!{WozFC;a`m~lku^sJ}+;*T5TY5CUt$<oh-#`W5gVKd0eh! z8}iz+@e<0M_kR7YY(OXDh|1;xq@epRk9pFY`!e|JwevH`$p8SAF}BQacF0zO9~inF zBI=B}NO21nzzrli`=0L)9$p$$SNfWosNOnf4QtqAT!l@t!Ypxq#}z=?UN8&TPBcH2 zk&|0<Q82E#Bh4EHabiOnv!rZ;bQTsfpNDN8Xm#=2u7I)ZqDVSBgqyjAJ9H!yw<FfN z2HFYGhN+*<RvWVRQWUX0H!;XigVNT_md6=i{zwSg$;IrQC45y%FD1E`ZmB|x-r9ph z81Rx|?0OsapL+bN!va|_7VtW39FMwVepew;6uTOadk+;*VOmkqoJAPVD~cq_M?|g6 zw$#tRG0o5Bel!yy1eITbtWI9hMvg+e*+X5>NMz4RapxC5Gl(9hRS)FfDF%;5-@6F+ zXZKY^{V+8FiUdqASg@YCKzn;m8~?eb5IH%3)y!NE46>k~3I9hl?oNVV`2gsVr%G+v zBa4?9E2@7}Ia@rpgF;IY?^RP&+1@(SxNxcu#$VT3C$()8<IMY(_UVW7Q`)EjJmM<* zo3M+(8Ny6hv_&lDV1|{$q6m>NJ{2YqEa3TV%o3E~J$a^#i*xB02L4{&sqE_y%S|zu zE-Q=IuhU`^qaWphX<X{tU-!&UoCKYd{P#sdP#;$RN--PRO@0(k;nW9cH%repJ>KF3 z+y#tiq0xY%XRKG1S{$dO1rhC5ZR|z3spC-jZdGp<<6<(*F5Cb7&KiAGHstPdE)%Gc zTHo(FYVK&Z@|DJQLZZU1;^!7i>55h3Th0oagrFk>r_ig_xtcxJCa82a$_Erpf_y3) z8AUo8;NF(WcJdtuNIC5$g1e%zLP8;bS<kP35l@~ZuiS&|E>m;I*C}e=T!{l?5{HQp z`DJBDw(nuCy;tk;AC^Y_?jB(fvWV_0#25I_rJy@nPm9Kh6?F2_Hc}u-<<w50ei!{> z^p1ulff764m1IQQL>xaOT8kYcxNUEW@~oh5BknK-h^fZUIOphC2Ky(Y@B+8&`XOgI zp$Dg6`lY!+>$@MA%x@?NvHM##%FhI4Z}?QPKFfahnk3JLMSOM|T1(bk{2leXc<uWz zQd`opv+Avf47c^7JrE4Hm$w*tb}l*a)$4Q*lq5CjzjSXNBeh{{I3B<?7h+FET29{l zl`Bz;t4nKUqwCZtgUM%t{I5c$0=OnWMHC22++Y+yYi17E>e~AJ6374U`(F9u{*%w_ z_7y-BeOVfny0e+11V;$igHYZ}>`faVFxaTqHZN}w#_=Fu4~W=cw$zVp@kRNkT6x^I zoO~$MA!nyLms*|srv=zlCJXY`Gu!yii~Plj&n|3S%rDZyGMTHhxWgI(^6a|HfLZQC zfq?&=d=<4Y44J!Ig;u!A&jg;{^$sZ8{wBbld|BL!qS6JI5o5kE@*;$v91eWXhHlGQ zYCLbd^U6=jOFzI#1W~^jZN4pmm}C}*$8?eg{VtvRd8hmt<PUK7Lv0wK@*q)sbLy9Q z7j~~jLhyjX@)`J#Lleo`sc0{fdczw{*IpxZ1Q@KTsK)u^q-`li3hlF6VksPr?eV)b z%a7-{gXL3i<g3Q^Jj7^Ux|LB>uK`Zf5c&Uzdh4jB|M&m@WuPJ;5|T=HO<KCUB&1=| zAR+>S#Mo3i$LO9&NjHd;(j%oyK)P!%U>n=Md;iY)oZo*t&wqB#;&DB$`*pkDuk)I` z-lC^*gEkcu6C|Rp*2#^IM94i^02xknD&zL)J2Ju7fc6TXXzXCm&YmBk8{$!QSGqtc z>1!rAVYPGbV7G$skG|y5a9G#XUo<DibQNc@N3VG5nLZM6aEqwWz0#?l_DXYt_0Qot z7iU&Okel%<*y;eSYU!JW7Bh}f?{%=0wkbWES{eE#F|}cexSVkLi40wk5E0Cu-Hf!G zo(t|U@t|h~&|TaF_eIAt5i4Q;aSBK*Z_+a#EES}n;2cWNX`m;j2`k+S3gk-vUo^>& zM_5xvcy|`VWgX$ndS`Ptdh8LjQDH*XoAGvA(*Jf|(})e)cUBJaMgEE~IOweRmi~Op zAbG{q86Hp5Ku=LOj&?4~RHz%qh`9nOTyKjy-&pdH?G6C0#C@(WQMTvw^Kp4N+a>4% zo^q0OQ{>X31-Kb4HiHv6<n0@@_3avit>56}=T;oXr#5AHf<3VLJfrMG3&m6#+qZEY z%}5>-qWOS&3I5Qv`OmKg!%O#o{FlGGZkZ652kKB015qzccs5Q0*>!9KJK1)Mrb}n_ zBL6G76pT-y+rQEwhW&qbpVf-Q$)%F^CdZI}uF2>K-dL2wP+Wdw5BvWkO9~Ozb4y%; z$<63co&9}*`=mgYtkeG`6<FF%ZoP4V!?~R5MleKFb7ybZwu?(8V(dx>xQ3Aw`ZWXO zB}Sy$@OQObY@Z~zlgMbU=vpcLF9&C({;1~yN`&t*U+{i=As+dh7Zg@9a3h}0Vg9R= zNui&Yzc=n{uPero9g%G4!7*DWPh<@7Oy5?C#_T}s&O3{*#KEMWz1}#OQ!P!(>`qGg z%@(mbIDY}7&sOC+Z#=zo2T?{~JdlarUq!Y7voIN#ADrE}!A#%^?bZW=k0_F!S*_qd z5;GY$TA^7w-k5X98jg1_1b+cZ$=wFbjf(2*jYDd5AR92d8*SwqIzau(WdtM~Kfe>| zQw=vNkK%1xz5Ixm#jV#6un)8JG^zbz!1pJLp#(YnH*28)G<Kdi<exdgu(~%b&o`#N zVBO;r-n%!ZyG{1UuWG3#O)j1D+ru3}UOp--)b==D?Si*+b6Bf%LT4Gb?Z;ZIL{NaF zfH%<43kCw$f=~y+og^O8Y2W@z2ly^9ee*fz5<s2f=jD&Ty#B2cv6#rqSJg0Y{a(lT z=nZ=%ZNaPn!XrCgX63dKu0E}dj7GDdlMy%<%@Zp*pyck(3;?8)%{d3T@)A)$h`b1u z&zS(?G2X_h69@RV%<;W(Tn!`vypHR73;C&;o$OqeUw`Bl&*kX!_2Bg@U(>f>VI9LQ z5V`hTc^5C#aJOUitc5wJ+@NZ=tLy3lJ%e}|dDlgvR&XoXjO2BkUeA5s)PQ^SJ<qht z%?C}3+jmPL*!k+&4^37R8#Bpc8N&p4$N8uF?A`Ti2zGK<_epBG#NO9WU-)iMs>db> z*!{c^>9|_aP=*QIM#e;I(`Zo97U@u_7d8B<C$k|YHs~iy0}xy%9Z&RDWOAR&Wg#|Q zU6Wh=PEK@(0<0L1_V|Y}@JK8nWSgd;=>0S&o0_*vH;OG3d7uF4B*gE3JlH_cy<1FC z-x%sii#iUm)+mdf%Q*&dhJN+k+$Pv(ck`E!QDnsb<XSG9z{Eq<yQgVl>oU~WlcRa- z&%&E?w-LN!NW>s_(#DcD#6^2$EsD}8Uld`%NmW}z5);V9+!dHqd5x+V1p!gR0jN3s z)zORbk~!1G6Hmp6kW?^u|6>QI5??=^E($+e!yoC7^_vVMAGs-KgoyfN?rOcgqy$4I zwG|^rTNb*|dnQxx;AGHkNjxK?)~k^E=kABM%g-{t(S68-=cdO0OM1=!S9%nvxnUu- z4Li8vR{DBQCSKxn9=HFO<}0d06=?zoCQq`49zt%eO%r~ncHC_^)6r~cVeMs?m7<He z$0gi=@7w3)WWsnj{1<uvKMXn_hnM(=;^brEyx~@z(m{ImfChNifs^Kn<AJyC{R><r z(^TD=gNYKScUCBC=4MDri}S`;WyC;E`;&PLE)@JODF12t?YShqEA$$EuJ!K2=C=<d zw~2d7YV`EtD7g(8;z+!u^8|8D5#jcU6xH72pESL{8KQ^ANT|M2Z$uCJUx(<8<Gx=o zKJW4aZVo0(DqHy5k0!{qO!%yD*(M~?CHG{yk%m4s^jaoyAye49`ErX-G<1sT?R=Nb z{0cH6|5vKiGTwKC?Ps5!bWI_yk~Er~I)S!Cj1eE$++klVD?1Z3!@EaeRrg;=BJ0@! z282aC7>(xAjI-p;H~oOO8Se;x)Wm%K!TU4c2mHRvhg@+gQXL(|5LIy_#g(Z;hm^L; zK}U&v6qi`&;$TDkmBdu(QPTa;bNwlK4U-D_^JvGb4GDud2l3=A)A8CaBnU2F`oUqk za)=p*aIZ`jwa^E(>*_id@oVa0T8c-tUv?%Jut2z&o5^#WWsay|75hoYftk+yKfBOJ zA#1JF#kWN@ux45y6OLe^%vd{K$OO!#>HRIru%e6F)%%3z1FUYo7>9<7P7dAbJezMC z8^;_ZS_1Wvi+f@_Tdy8Nrftr)<?`GtXvttI_~~yGhF4`bT|x<5V*9$PwyN^)c)8g{ zMbB8Z_JhSdX;pXm`JG9uTgnbdT%KJ4^`?HN@0G=Go_!qNS=uO3fWrkTEm$yThnG== zcaUgusB)k-A4hl3Z*80SX_r)2b!uRuITuH>kwa7?H!}(1dx+I)dFYj*5R#4)d;JaS zgwYhleN)2t(&>DOZ&nRco7SdHrm}dspG*-t!8^~MCmMt`>8irXDy<(b?Cls1+O&ha z6G1l|qkH`{Mk^21voSJLyq@7w!ryLj`s)+{IkZHbgjKTR8&%c5z`iqhG8Tujd&{r~ z!4_@AFvc7{^EyjeT{n}`NuoyDwYuvZ8@!66m_mS-+Isq3q8rpP04paWsWq_DQ>8BR z*YQnK3xh}OrJHIoj>Q|9E(@nY*l7hfsMXi2tvH^y0*byx>8v<nRq!xGW9^)LP+T#N zJ*9QCYMR|iw0;3-z~V>I3R>LvArmE~eKWHQ<c`0U5HpB+Owl@9{fhvWf9=sGRi~jP zzwz8GAJ5*$`||G=gR_3dBbdXQqEeTdo8j8>m75+NI-qmUGgT<Apr*?U8%$pV>`8<} zeibv%`QYA3bbnEUajOM88^B4?e%sv*eY!Gl2)OXTcF~|0@0L3Rn=%&Y%0)+>*z`P6 zi27IeR_1M!xF|nq2oxXANk8^)|Hvk~l{HG=L!3=OO>+-e%)y<s$}Z_Ox>ECe2Lj)f zPakodB?j+S4zO*G!-i)&PI-@Hf*I7zh0omYW4}+bTFJQbA5Zl?r4xWjE0uiQUCWf{ z7f~bYTDo$4%)}IX0rPljZzmVpgSX3Ua_RUfGx&VigfQulaTHIPcicA{h>^>yneP=_ zvV?Lfb*g*hjn+7X8X`??j?J$|#{rPioiuA-2VG8_vC{U1vv_Hkh@vQ!DCO~nisQGb zZ-k-qyrh3`Bh1?k3Z8_NpQkfsjqabYopN$gpx?g*7Cu@D-SUUS>G|yugSn|Ej8i4& zt@+F!Prgq4`28c`BoTPEQ6v8siAR-Ar?PS?x{w=%h0<(WUP_t>WgIThsnAAnklvCj zc`WoP=(ttu2l84Pb>B%Wdv<jc+4Me6zx9M5>c7d9ll#CLx@w@`i|bYAy04<O@2Fng zHD32JT_~FT5enV0PxpcQpYE@;PlC5BZWAO(lSD0?)$eks_Hf~H)&C|BR>imXJ>dN; zvp=^`#x4k)z0$-y(+mCNSV^TFnqp6&{}b%rFH?SI`X5OR%<S+e<HZbpNxE(OpvS`n z-cR3P<;e+kAC#5zqqp3$Vd1$flA%qmBj1=1IxxY;uKV>kflLE-py+LruZhW$X^tA) zDR=IOd!H5Yv|+;%v2sn)k{7Hx{Mw|XsxM9UF9wuR86jt9(cs5X^Wk?X#h7N`Oye{< z|Ec~b%X9xu{P!o{3&CLh1poKi0tk(xlWFhU^Q`_oDHKzm_U~V8!0p&1i9U@1f?{wy zWGVD#r0r)s6B;_Br7p6~zrM*A3-d~6eSAO{S0mgOX<Gy`(AIT+Zo603;Qexz1f*lM zaLV2(k4Z_q`&-+!Udtdw_tiud*i@_IaPi3Idi~F>L)l<U4#nkG2#_0A42@T=7J`1Y zJ~R1lwe2yGTB8An#HNLGrV0%!IMs)gx;34|n2<aqTLNQO6yoj9Z*?m9-FD{Vj{5B^ zy3z#Qj`x`Ss)<0l<4o+93Yd1@T0v)4L0-Cxd?{UQB`qiXZ#na7j|RL&y$>}1#<sc5 zD{cpwt=EA9Hx`(_W6V5kP{}a64WBSBfPi9u8;zJ|ojlaZey6j!+T(+Xsv`#zlr?<G z$0yyH8X{kixzo(ps>iLgr)|&3G3Dqmhab$79J=g)4Gd9s<rB|>zfc-_z`w=iB{px` zpWrclt0X0@ceDuX3#M1)+k^jo%GZJy`<?b=(Uk9)Yrl`yHEBRztSfX~c<@k~uLybZ zC_!}I84igjTeB(5jcB`=7d>B<A2)$EZp7^rWbtMZ-#mwv*1E%RfqmkD#KSm9aWzAt zgWf$iiI*?I4Kh_ndiF!><hh4I8I?Q>k523Z4#*7ZDEJ*Q|Mv6u!{!*<&gt>~ij*rF zC40TC(J0Dbij;Qv5&k<XDCj!mEgB3Mv+WG`{CL8qgE`ez`C0p5b1;=LEjC@bCw9Ex zdV}Q9TrjWYWPaRT2~saxYvKf6L%g)lFV@kWm(@TV3hKlvumXqAx%fLfA>tlG03)L( z=O@WuSss$c@v5AS_lWSv!rDy^K>6~0z!RWmi5Q0$TDA61w|eb+4Z>eeSm?&!cR_w* zlQHaiOm24mR}wK7P3y&8bBSk%ZL0>u*(??;D(?{*1Up~Y5@8un05TBP3LK&zP^9HX z+~DxFYCOL6HLAgeR$UxgOb#A}g#c%NUJUc368alpGG#vqsWekMXB5rBn7Kz*b&+Gp zp;n7QYtxvc<R)rPF%ZGYRBsIFIF4J8Is;&CZk?%)?#Q&pEtkWwYG0h3g_;S@sjg#7 zCXhK9?<JiI6u&dKdH#j+1<nZlfJdy(5b{{vfnrO7(<cU*Fle_QY-_=4mr>Odk7Nvr zvm1}?b%|>1OKD{Yin~}gTZ!%6N>Tg_Yo5o*rVZK%$#WdVaY)?N)>nP6{UCV;r=QTv zed5hjI)k=FNbm1_q+$8D-NAqui`~}a<>J#^oE)?-BUUez4eSTV>O_oKh}o@RKMs?+ z1M3+ODGIEbi|bQ{o1=5^ugq5v$)LDpsFHKd^tAN#BrCq+$cLi!sn^jD-g9a;jtpac zPiysBR(K7gQ<>XciS0He)RN?8cDut9sn9N?)?0KXFk!J&s8f25e!uo+Y)u@0bqdsB z#3$@Vb-~ZceonDoD=7hZ7<Qjn8J;z>`~{RTYRvKaJ13ZIoxKa2OHxcw(4}Iu_Rmsc z93cGo9(QycMEC%Kx(&xX>4<!2W1y+uK|kJGV}YL@d(s;Z$d;olA^znXsi?X!kd6zv z#j$KQz`dqN<wB1>U)g&{(CcN;&o=C}DP-1rR2^!3^Mvc~!jvMX_Yn_-xfs-#T9gyS zo`m~Pk(yZc&}eP>kz9GFueSa6bU(fDYp!++n5-Q2tb0cgd8JtY2)MU%54my9O&+LQ zPaUZy!lpa*Et76)@$g?3%Z)YJG@px6qS?SzX`<6)|EnJXa@KUb7G0eR>N{_YJ9z9v zOPIP<j~Hp6;*Q9F3TGEI&+Xy|f5Zh<>->0^O_|E7*8nO+nj;@04o--{6JYZz-Utul zZ7n=L^oXFjvE)HOx!o|@t-b}n9umx=-Bp0>p3el?GPCu|rg!lHy#OborMB?#xm8w_ zXY-4h5*jNVhcuq{i;nwOKJa!Jt&_-6fXjx6VpVWrc5cnMG)U=rck05;mGl@ONtm~p zJkK31@&hc#^ePJV9KLFLhTmQ8s2=Cr9EMHJVq^1XVryC)wr5daPoC}tkuF-u8iC_I zCVo?~`>kUr>)y^u*`VU8;nrwp^(VBBU;?N!+jS#FkobTpM)w`y{6*mbqTghs$HcG! zzKuTK9%g}5gYc7hSa<i`><cADpiTwu3NUQZ58FdMff{RA)ifCyuQZ(PZ0il3M)AY1 zH=Seta1->DpYnrDGqoz7(tW~d#|R5LnF0uP<cu&;`Q#2!ycCA1RpqcJh49aRsv7hc zzm`b(5uEho?lFjA5dEBs>#j$4_hUx7?Sj?P_i_Bcv+*hhg3H8NzwzaLiTaEig_1ob z=R%=`%nh5)q6))^tK$1I`bK8!Z8<UE!PMR!>k20CIvfoa<Ax4c=!~~jY(iCNqK5lz zK6`Y*z)3YgF?*Ai!c3ogsSob!E=mAJ?O(Q$iC-eU2}7O)er4RmTY|Ba04kKAe$=VY zS|P8L_Wa3r{HVt9>wYu)1Io0_Eg8I|lZoaua)g&tMC{(w1Nr(oqp$nY-1;PzicAF~ zmP&_yisG{l;Wb<`mEQzdxvTa|L4%Zs*BJw)vq~vcQ0Kp`^ic<AKIJ}jHRE&c-~xR2 zpiO1h8ER>CZX6n}N_v5j<dR|3`Tg6Z<ANrE(pXWveoEV~{s!SbSO{iC@y4t7W9Y>- z9g!#t#kV)&xc`a?Z*VGa4tVhgC}Q#6|FDZ6peKC{i?cUbbQSJ!9#v2|42*qVp8|8! z`6`S-V=&UeWd4HDYJ!F<wbVJCgxUP4TZ}$@agwt4XzH{wcsK#WAjAU>#uV$1zr{6T zmxA?60d~D1tit^#($z5=CqCizwpk61y*5W&s<6D(wT7;5*l&9)a}#~fDuBm~7hZq$ zEtiu4QcmbOp!SvLQ;UQk9`}5%X~NJJAiC@*IFRALOuNHTos%_aj<iHLh1%R*5{FO% zY%rZa&P8rxeZ$z>8JHycx!GEb7yFztxAxCt{kP~xLr+9FQhS<NyL#qPg8uXNu8hY9 zJX20!Mt)BD7qkcW6I3E4JR;`mW!E<Q$abH5C*N1h<fS;vbTC$Ixa(H8iY|PGr)fQZ zt&#z5K8~SNCsSOFmc(}6W7Nxn^~|rL@=YRqH~TLhDR@QM9X=0{H^if(*jwYFWn(E7 zjh6o|d@?JOJFdIp76FWU{G0X8c~LLUpNpSMgjk|G|H8EuHMs!ET|Wc=1WE0|<EB6g zqy`Yy8<bTCrf}ihZQ~dG%t2k`gRG*)#??tG<OF}`Zye+k7eZHEGwCcp=H?m;*p_4W zRUk(<R^Y{gB|$y2?O?e}7L0ISoI)21iMZ?}YZyXXThws<oHMM4%jw7>zs~KSenGM) zc?f-rlN0v_Cnu5?i(OS%jTh>RdbXkPY#GE2ilx@vV&!L@$sEif=TQJE!eOQJt4G_+ zNrfgw27G-C`$|a!Ag>;ATQ#c=LOJ?S#`^;Sq^NhU^-8CDS_>_qxUoU=I47Blv3h`; zTSwP<TW6Rx$jBUW&T5dsV#P6~oio))I{JWJXq0ssWCh$9(mDpbBb=s&$tnIlTN|S! z<fCCLSP!*sE>#P@JvOdF(sArme3NtG!xDnqd0{Fbly`WQ@-492W6>QFeuYfQ^%P#u z+&fR`=0S1+6n~K#eQ6nze&{!FkO7)l&D`6$z^K`u?5QigDFs6=a^lrB)p^8mKdb_k zLNGF997*-7&h3P6p#&L(8xHt|jzPV54Pgh`eCFm1U{YEH$LHY-Poi9rPNM;nT{E@u zvK?Gl#hsqiY*_6z>aNjHa(um+ldv%LqnxN|^k8_qOKGVtS^odA0N@Ug>X#T=R~FYv zolYu;*uAcq2TGHm?|Z`6=%|cBt<GC}u?f7I<{X7pY_64QMG0j16Cp3N#AqA!m2bh< zpdg5?Xs6g-2B?#<K#%aT6KI-!$#c@Xs&x^DjXZeCiKJ74hTk*YB=@VAG-_VQQf?g} zY;NQk=xBwuunpjul$JsFI7aV@2}A6Kv(R2>g*>Z);`VtV0Cmu#iQE)6XN7#=V8va# zZA7sWTsMUws5|e1e7{Xyh<={!nupbR4!U?A3@RY>Z<E+`>>qi&emtD*ploHyy<vHP z)cW?u<M2ttU;ECWk$_98@=#j$ob>uF{3o7K<CgYkYSqxwz0aY4rOQfpqQF&Lz=3Pb zA})9ZZof@Zztf9VxW6Q3_S5%(M|LbPJV*3n>p*`<$(hls;qg={;qA_;`$4RTcNOO! zi89RqAb&^Rzv-LTn`xB;`hy1t`|{pmiS{qNRnH_d0HMx+1F8Q=d=&)RHEa4BPJ0$i z?Tuyk?z|uPzDJ$Cxc~9rw9kc=)EwJTsXz8RL;?7XR#VCo@OA^{=k~{C?Sn^E?|{2B zFwAofQs>M_9#WXF<sa>yBJw53DhIw8yl9!*hA$n<9PaHm#Ql&Szq-)>H*Tt}UcM8T zTXW^ibmnR!PcUOFxY-SlfO~gGg)}c^!{xONhET)Xg7GolADcC{F*n5a<K41uqHTYT z)hIUV2AP3y!9W$qp>js`Sy#I#t_)ntdBO^1c3oPQS9##g8E)LP^dB(D7<&!EE4ZW@ z>5{lk4W-JKNLAn403==Q7-%-Eb|v&@T*>!`JhC3AtOPll)H{znVTP=x<n}%=kS~iN zU?FT>%9l?sV{9RHpzbi$)4o&0V7^SndwZynu6n5z&FN9ADbr^?j~eNqhYvU&3oKmg zXl31fl1d%E=k@bn@#N+AL{sVN{`EW?e@!P)hczzWnP2ntj0^3)$uAA$(Qidgq%`B3 zaXoSReJCJ}Z<?-IL*DoUufN7_`r8ZMsR7S9nVOW&jy48OZ-U+hS)mVxC@BjeW&QR% zNH?@j4B`hoH~Ky)>5r7$@ZMf7t|@#SeO4URPk9|XrdGXNxPk$bvr&!;?EX^j_NtB0 z(e|*WUguC0uj$X#`^Q(Gv7wt_)}N~bgy@rvP1>TEXk}-22GyAD@uRT7l-Avl)M)m6 zu4lrd_;-L+cgSx)6)zycyYaC!w>RVA6~p{K!|t#GN-Migdw=&T6FmABGPnxb7J6IK zdm1b8E6+W>W-km8WM_2wFdlC(#fvE=NF?OG)?E=>g@~mWxDimt(9d37{2l@?adywH zF8f=gWd{Agult|A#s7I=tDCC|5TnPob=+(c{h{^oo%Xn!zRj)kn_}@t=Pvl#T7$Gp znkKyCW$5wFRm&T4P29^a?>^YIJ{IavNb8nZd`kF8&GK)y!?L%S>)|TEL|=0fD$s8e zU)jfMMexh6fp^Ixbk<R&?bVX@U6EX+Z2T`Cd`QKziz{xd=5!_iI%sMya8$2xkK?qJ z2c|8%rd~89!&_KB@rGcpKz}g=S#)cpZFd#t)m=eSTK9>U4>{e`Z=cn_&G^jNJiaq* zQ_L9CBUJK(s;q~vB#@vv`t)(@Wr!tS4r*N8S5FV?zbEMtxws`jDz_2Vd-p@O0+m~} zEizhX%-on`{66lDpto6o(Eco|hZh6(5QEktw`($^cbyXF!F=i;eOcQ61J|^A5J8kC zFy$`?-w6p7zrel2l>{~+&s7-{>>8fJSuutvA=i9vbq<?lNNVlPVyIkkQrbvEa#~Bu zSSAm3PNY69(<aVmgDKnK8GpnxCpvt2)E8>gB_V^OtiPCNW}t7GTOF0x`+jD^#!OJR zmPc+)!Q+oc7BDgNd;LL>tBX`oL2oJeW<u~?!C(p+ro{;ZZ^GGs{guF56Ck#s8oQqy z_awa74{2yuDptOC`s#<!h$TG>qAKrr`<sI=Uz)YvdGOPS#}ua@hTKFcIx*&V)qL9z z|0|J4aJh)WopE*%b`|8jW4`N1N}Q3n3H`9Np16^Cx_8<mGE$8+jy_`vZ?N-lCZmj) z3vAH`cl^w@i<#n~4EhM+6rJ(l_DYdxzCKDjQa_NWrfnt;-D8Tg5_j$<cB<Fn7#@7P z4@E|y_gZh?>f>k3f>g6a%{A$Jco}W6WYD04@KK4Hn%c`^ZBklD<$v`qgIrB9VCiG^ zjo^`INfU=F8%i6KRm`vR<6ZMZJGT#X-a-|UDV{u}S39mW9!wUwBUYpbV02nZi0eBF z5sgmlh$EY;UjJ1Fe2=>Hs@-u@7bwK@4b6o#FYI+;&RNIPpS_Ar>n=22NK$Zejd`Sf z)J{VmM?BKsZ?;TbpIz|x_9{K+@;IBL38hSeQBtL@>xdUKeAX&90HDggv?4!YEX*R~ zP2}FKbc9uW{N^Kxp&PU72+z}c#4aVO!Yxy_N+WcbYr@K@Kq96j;H24ZTmJOn4w#(y z!S!)wiE&>34*i=L2kXZG=*JvS&N#2n4IA%!#PS+h6`#9}CXTNV^>^rmWyrgiA5D>| zDF=+Oijg7dplz%8H!CVH1|~^QLVw(?=voqv$k;#-V~0FcRnL4*90J9lnX<t$7@jws zbIcMSb?1rSe@e;$b_om_Qc7m$ET;z~d}(DR!6^x-xyHx`32rCSg0F{;Y+igsQwQLE z8AK^rZkn!!wO=CmzrU<~uB&MO811{M+IiTTl$802b7$Off0knLd@c`wAk^qGCl&MM zRs`eBhKS9ZTzMK_m{uW+idm%oWUgk8CM_K*TLQkE>fA_}7Ulm`sdR(}5LvirT|#<S z4y+)Mdb-CjhpGZU3UNDNLE*mbzEa=&k?Jh3P5dcMe59dHda&?4?uy($dyFpYp3G#i zMYJvxsg0Dm@6?FQcv{pF>)*3~WA~3iY;uBa=MK*~)Kp<S@=w=jz0}yPkj_tmoi!TR zyCz&@eX*Z-y%%(Nt&+SM_WI-XdsAYaUnXtmRv0ZU0I2su_<%ERJi{=73ob!Gedx>D z@{{^PC>M@v3a~gqpA5>|HQED-hgRA{^j0GRu3APe7R-^CTEHr3uH#R_+Ao0tR%H4! zToDbL0p*6^F%X>;Jv{mOJjMjl!sc^ET(aP?2z-rIBwkoc7vy{J$6N-6b@g@Wpl5{= zC@pJNU5t|pXvx47lJS}a!O!NKVVu3sT`07F`Bu?4n@1s!v2_@RPy7H@KXg2JmM+Ea z&8V>}%HdXb{uK6uRxE4zOm}BFKH<0jH$VO&0S>P^e;%Wibsf`y$zY<q;#G%xnBTtj z0jIM=yk)&*O{Mx_hRjmUZkV#)_cj}gZtq*6-v?LRwfHmW9I$Wna(1~AoL&+<qHXJ1 zB*aN9<sR}4C<VQ#z%3oy&OsX^Ou+E)_$uN&$a06+hBY@s|E7#^z5Jvqh)iU0r5mWE z=5(a*Xi9_Al^EmQ#bOr(A%E}jZ2!O@NtEwtjm6mF``*q0fz+QbVCtIo$bm`DJ@MD0 zpC%qqkWvNoRw*40T%!bK#L^e;tg}Xcw3bRN=V=#V%$CRzQ+;IR{)auf$gIQJ%0b~o zBs+$6Ecf5w+Y98(v0cwaJ)WI8<dv{Fbzx4NhXonFg^Klfq2NHtH?tqK;QJcgrWWpX zvv*jt+w2~BEboT2TlD(x;ntW_P#%`_?7K{5h9hlJIBfb}^p|qcL@PL_lV;_yw66Q< zwBtTs`^);LE7cALx@|r?QcOlqc^GNx@Qj0*tD3mg@A!OF&Nt)Y^6s4;%zCknbecxS z$wta{mSm_VTZrqy`<&_T=2Kc5EuI!1)})R`jU>)z1ngLvhRjtFAQG<xzn?4)AIbpl zWNVqRMl2Rv-5~)nlT(WUYM*mk4Yq=J4{I1Y-;`y;ML2E?0|OZ)ht1TtKkNy^?=${5 zlErXt6HZJKpQ6B^5Tv@sT2;B^nd%;rs4O;ALdjoAAFn1r1H7cGpf&LLN!fNYR+NBw zT_v`Ov_}~=g>F<?DKNhyZ_!RW8LnlSUKoVQINzx~`t$Mn@L$U$4knr*l@pvi`5nxQ zZWVL;eK0=rYf2-Qvy|cuRoiidr^V^$8K-5#$0+BU63OVR8&Ou)qc^i^3M${%=5*fa zG=}mK-lSE3(o8EaI4ul{aFXQbC&fZp`@R6Ah%ND4Xg;v$<kr3of<M|wTNxLd_A;m6 z6t6lNS+c7YX(|W7Q^8s0!#a2&XIvqoPn$8yPlAZ@^-Nq^cP8C4VZfC4!qY<qe|>Jb zSAp%17w3XW(qic{;>k3+fMf8!3j@#Et4&eF{6qN|-Llv2h1-Ey;@LdKP`(inl+!~S z_Y3U%9jOtFV@hf<b-;^cYQY@|$oVHxKA}KXljUi+C-fLf%l()3r0nDZ15kR!GPU@T zCdO`vwcU|@7Sc7ofzSAGn6Qq1XqmnWS?3GxP_ht<^quSkQve4l(ki>!c&f3FnIC}* z6)7t)9`>OfL+635f5j6Adi%XUI*r#XV*8HILkryb<Gnn*zRq3YWadNG=_%3eW|drv zGr=UqNP1+lFr$6-GWJRKs~Q*nk75j=LCz4aWSJCIUz4q#l!6avKpJ0y@omR_`l!yH zTFK#8NZtO^_aITnY?l!2TQ)B5E%w5cS^Hm}?3Ff+r#wv)_6lwcUUO-;ESE>_47yZw zCFd$CT?<Qr+Q@hT1a?^Z$iADVoC|V$pnWVf0!3-9NC|wV^bO`l>ylxNdzCK~i}0!( zm|vUXo$!dcR5;o~56&o6_*<9-PA=+v#tcr69yli_X<+|?c93fb<8q%T2mc9;d_{r- zEz#P#w{{iE8nwj4j3Tb+b13shPVzT37hb%0ytT)|Pwr&vOMT44v#uDCYLN=71bh2t zR8~&!xIKg_uaIXwp|<$9c;%hZ6$1H8P`r^#09>Jej?W!m)pQ-uw6yca2t7U-=nB5k z43FRt6Cz)e?MRoFQOB=bVZhtkc0xe1Hog>1i49>CdDjKu?W#&!emf=AcL}mmO%zN- zzp-n>v(t5IyA3}V##Qq`+348u>YqBCcapHjDb8TGnhGjbV59Vf!ftL?bV<*{|LiG^ zN<TP4S&aVBQv^z}kp0EOYjDGYCb7P9uGoyXxPn9gm^C$Rjxj7~{#Vv!115Eu@s1d* z0o|8#n0Dw6rXKZ{Z;hLbT<%j>EZGz$L*IQ9%H5&VK4|kf57>Ab6MwixT!R-A^S>cj z4(0LiMik>5&n*NUhDviqYzkfrD#URcA=9rglRAoIIfJfby2F}(@{5GqPK-Js<^3P_ zuV3xEVZ4-3TJhSNGvd60yjKA0u7)$+xdM0|DwM4T@CKf90wlC>DiOH|oV-6_BknF2 zM~3R6?|K<~{oA>nrL&RO>6eBI3V}vZx1?fhQ)VI221=lfdDCtW?Cy<pepO;MDrYfR z-m3)qdruIet0_IgvAWNPJPnHH)9zTMp)UIF6W8q3jm(2r6bWn>s0<vVm<n~$_PawY zTfBK)-&xgQE$5<sH}Ygsu}7<_?$>yJfcTt|{<vZrJ7_0P#z@P!KiqNVJMAxW_yNvP zwUFI8oQw><ThKz1FVKzQKmN*8ZEB@o%vI=uT6DK)=q#=@!ui}f+Sc!OGB&nc2>Ef^ zN^U7dxtc5M8kg%dAl}cv7sd1=XfV)OKgV!>Hgo{o|LY0a)07csJ<vjf9%n)ESJR_= zffd#UYyJZ@Hi=dDDfzY}$M095573U>X8{Sp)c(E1xR6yyPcoq8->)*7au>z(`89>9 z>&C&_(|>z3yG<XO8v{j9mSFPWjwa49j-P-<OO_^AMlk*;{{BK$z#ejU`BXSO%8L2@ zSv@;)av-Gh?!<a>a&km|fZcv)Y=2tS4&1sYWCMJ2r`@bx{-?D2n~IvVqi;LPCy@<v zB6|JS@o&>B8N6k5QbetW_nTgpf?SsRLp4LA$?;Ohs}VCHU8*16k_S>}8)pY`1eB@y zHk3S_Wt_NQcSgx2U~^(&KOnB5`{H;gMn}i8K9tP-2t8?z&D<$mX-JMQ;QQc(&0u14 zo8=qudQH-a*<*`@+$dHLtfa+PA0~ab7qF+BlDnvFcg;YXp3Y3bm8UzZ{q56KDdM`X znO<q%W4dE5lq%(sFsM&s-KZ5-3O`5V6CR479m#mStPZ3}<Gj7ka-oj6uXW9fvOYMi zKp>_w36Yp6e?UG)`H13oqC<)o>WNtNTXFCD0bEPynaf2G%3!#8YChzhGCluAsa6Qd z=J%tXQtfH(23D#E6_1WT=ZLmAXnf(&Gz$|;`_n{RC|t+Lv$UHn_lWR`%2V-IQ`<!P z949CDY`!(O;Ok)QaXNBO-kZ8pF~E#N%OzevD$A=)=U#=YQZV#`&GTm!Sm@)+tQNP# zo|Y~a(^SQ5x4bmon<Cd|F9~~Y!UxB#?y}7|(90@mCueJrw8v)`Mod26Y(tYFLg1ZI zcI|`4GJEDKV7VaG6bNmsR8S{}g}}9oR0Zp4M>X2C##6O{=3TGaTAVf)x0*K>+um_D z*37(op(%hm;2U?7rPMCmp=EqZ<T`iA5-OI)7~(=VA3K`BYn;m=;#3beW2zVw(0&(b zLfjlit!Uay6B~<pn3k&JH}&2QcxH5Fk@~_N`!fltbBR$FmY73EF$@ljy22f%TjYQI z)cMgi=qK_bYIFaRwT18lHy};@A<&&~GE$2z{zLpjmEL{6$zg1cw;SYBRYOpHLY@TY z(I5ZJPS}x}`zB2Y%r^I!a9s##R@+CWRT^QG<xtp3upAZ`prhD7H+M;YTV-Ya%HZZ` z{2Ou>mv@1?yg<2PKgOr_AyFO*S#iyAxkWnT+#LR8nCC9`bt&n&$S_G{x^ecXQNVu6 zh0o6eVx!6F%~-r}Nsq2g63$3zeCGQVxGG4uDV%m!qlnnrW#kbR2`;w(n>1c{n6G3I z(`!n#wWQY_A7^M&ndByyxG(c*fkipJ>p&BjNj{}No5FZJLrh$CPfCkrHVP=WDclJb zB;JXA&}sp`2pa;qm^qvFZf88}T+%T8(GMHVv`_b8!>tB!gXw(|aQ?W2MEi8)qeaQD zF#vUu0)xc0(9Gn4)XVxCpHbO=3)IEo9mj*MQ@i!=f9fI~0sak{r}d%<^K>4%2O{73 zPCu3Q<KFMTSP6wR7kHVTzX23%49_yl9^SJ!T1+gKYhDL~+N&-RtOLmH>Iq}M7t5r; z_}tjR+V>8y)f&6LUX<YJ6xy%bk1$E|<;$r<O~Ihxd}Cf4iU!oaBdF7<_w#~g(k}o9 z(teodQQCF=dWmSceqa69ax(O*u<@m}JhM`+0zY$}&YBMGr!0hV4j_Jfm_CiBXXUMM z`{kwDs?$v8v-CM9WZVPFo=+C5-EqakWC#Af-Mp*E{gtB!F!jjWU$8D$9YuN&J=MRz zfkt2F>Sey0ZhKsKU8EcJ^M0UI2fk7I$T4;kq!YYicOao^%G{r4e${oA0e^l`$o-)u z^868&k3-D_rb5l=J0tXprGuoO@!O7ySxp%n6c2a=0m#lsblLvq6+KLtRb))bdZoM8 z5(#c(;1#hy&E%cId;cSyZL;T#sdhny1O>7>k0#ynlfBg3zL*V{f+?>Mkm5qCt)sq* z(%CzRKMuPGRpD#S8gp*w3DJ+Dpc(A-&7ewxd?EGs%+lI`%2(yN6oqMJ*V~(bz%Cm| zD*tu(atT9z%g(ORZgU{dF)wd$lXthx(dm%*Eve1LPLdQQyNbuM?I%EvCCkA9A;QtV z<V1~+c!5xKrg`XlqrZvJ^F3MDxf9C<mSCyJ%!q+LCFMTF6SiB<^1Q2%m3ZT8$7$LE zSO_#iy!L1p+Ps7_t8TZHd*4{BAMH5jI;QT@usr3L*90&P<SJ?2`y$Y%`*6#1=dKh_ zGwvenCt^I+MH5+N_bvC&kGk`A#5{U<d=MrhPDfOkjpQ+zE~bM?6^ltM*PwZI2kqT7 zxfX{DUe?9*kOyDtybp!=Q|lI><k9eFfBKyMx;!)rJK>3=XpQ~o?G<uEJC;S}CySy3 z4=e<|`!H4mxk>CC-d^ubQxe(|#Z*akUv0JuLe{rLab5_2m+{|x7P~qQ;xVql|1S6o zKmtm}clCZ!)>i^B_VMaUdWJ>Ml{!cD0)|A_X_&nOrkMC+sS0yhj~d4_(DPN&D9msV zm}UBerHG4NM3L$$nTC6#dXo+LFCus(pNFEpbTp}aW7}c)cL(@i=jvbd`l=l8$42in z-s9^>hu4NQREZJ=YY#{%CSX;PrCeSL+{_f&C1KG;L(yEHWyBnlPMwz5NP|NS*iZwS zn9)zOHA_bC1BaUp-HPa9iX5F-`^)U@0IbHiSfdvtJXHI`O~D3(cu>*P0T1&U{Y=v7 zacytD<hT@2Gq9Ap<msW@V(TL^a%C-!Gm_vNy;-x^SFheo!>xTMF6JJ7H<$}$aPBST z6hEGt**R0x*HzJdFgm3O=B-7lCmN=m)iCnzA9Ouqj$=OaA+|N?(YEoGTNmHqUDy83 zY?JI4c)bX);n)K0#Fxafv(Q3jP5T2+$R;s24nJK8JZVD(?knNTknbs4Z==#qS*v&< zaTc2iLZ6FeysgII-UCQm=d3ZLhG<b068ry+H!Y+7ebX|SP8(GM-C3bt9jsqvHDT;n zQ(~5yn2p4rLg_Y!;b1c-HaV2@1iXefO~K}ZKi(UcSQ|wX`t3M+MVrkNg5%)hd$5J1 z@4k3+^6=m_@88(gI4>n|)HvnwKvqRYD3^*AO?&*HUBlv)a@p+&ua=Z}TfW?_P8uan zDMb~I7~_tS^359EhJ#d)5UVROpsF4xG0Oyf7S4R-n3S6vzCAvtI<Qz{na;kE%Ciy4 zhFP(b87cOKo7uzD>jwIZo|_u6Fz<Akw=(^l_2dAFblIV4giE1kjfRcJT~rGrKRZU; zla_0iKRm2=8;TblmHUT~pUs)=&XJT^`;%qLa5>@lHzqD6o;iy*eF5}3inwN_8c;05 z)~gw4Q4s*Y#z}v$e*Q$bVn#hDV;>zH$FgM(>Y#}0niuMbn!g!Np=+D-;^Oi}*~s2^ zvhhd8f%}*=H5;AGA)f%yr)COPhe@^35;Kj+^T1L=&d0{Wf0VwF8seRwG(S`Pnp_j@ ztg)H?=ilS!)bx5EtEXP_wOD9U{+e!He))W^@RrBB97ZRf%YAt50XkF8kG8+@&|U5@ zb6Imz{IJ7W3eU^vXBDzOE5gp>>z^n6WIRL2DNf&`G{I?3XdreO7z`8dZ*qr5mML#$ z*9TP*)6hsC&Tg)`1qZYp2NsygtQ}P^G~DT#6O!)gOuWn8H0~<vx!8E^dqHl~zf@I{ z*!|hBbQ5c_4_t71JoJ$Kl_D;H@*e2NA1OpRb~xeGFwa8R1-TLxSBq&=DCsR25ZBU) zRQ~pOO!c=PueOupo)E~e-}d%6(wZCbqpoy|o5(|-9(ufGc+LdXbfJ-oB5y5!bnw~U zpQ$kHU(VLmfrYW3y0?SeLa3R5*<HO5^5(ZaZmTD1-rqv^<(Y8ozKpPfd_n8mrb_|z zk*ZG~#>uVqFE6>v_|uO4{ZSsl?CfxwiVa#rP-iX`!)y1M!rC_0m)-Tgm^wS(?S$9< z=Rh4gi;;F4mX-NX@#(=#i@j;%lRvJ~p)L1u>3~mN;rtmw+%z<YN$}j{Z}{@_l(f@W z*SU>zR`cxmN(OXFw@UqG{pBh8vo`PjVm6}A&9OEi8scp2teY~+?L*SG`E25<I_HEr zYv7TN`J?*>GORy5h<Nc;*b*y#0mp9V{$eshOZ!oDkrIW;0~vkzo758jSUPiKp7Q9) zZ1I-LjBSJl22|qhU`~?iy2(80X0tWb?y9+ubR+aU;zzJfrcy2B!CW#s$5`t-^DyWG ztKygu)nFCPOGl5zsC7=^>t;eqrF#88PE&U(d&|v-3mz-_tK$bfTlmr=`a$#!{&VW1 zU-+0O1;aWJ(J5XVjai?`RRlx7J7L;gX_{V)sP@4+RnuE!Vumv?j2>|_-ch}Mvoq|! zRUYSg#~qd`KRryk-Jxxd(1p02XQ;?V4BF@uhPCaars5m>2JJLGn2fA{m>CI5NFKsh zVvXF=N+KMbH_ShpZ8}b`(j+IpzfyTx-P>P|5nWU=(uN^yF62=joJ8nslZ^=EZ*u&P zKXVo$zC4oV@FDrqUX0M<+(xUeI2H->P!ca*IjcDKkO|O6I%RUV5oQuXs74YIWpyT3 z=~a{4>YM9MiaGt3Zbkf;XWypZwzOZ0oF^{4qZQBa3R|jz#}D6=@<{yoM1TyADWVWO z+xzUjc|Ia^VkHdTRDvBCuWeJ?MUunqpNT(?xo{Y*E^X^1at#Q0pZ>P?>+;7YpCoZw z92RswKLj4KYOGBaLGPn5jg}PsKf#4b3Vw72Z_zX&tL>k?4O#jqOAY`1X*FdNxDD)@ z%G^Ubssw?`&z`*OQgw-u-Mr9Z7kUK8J-KiA>`uft&JA&49$E3@b-C~>RPk|<Cv@uK zQ@^)P!F(my8FVQUF;obA`PkQWBzy*^MT+2<B90~_?}WHyJnQ+o-GAja&;Bf(b*`PW zoR&UC!_~_^u4xq{{0@GM_7u^MuPhZZoLO>+dzF3?GJ=$#qOzQCg(mT=HxkZv2)=ls zpMZQ)%<DNi(*7gh;!O6S|K7I0vu@6#JrMaxZ%YE7wR#MUuJ+b74CZjo&-uSOh{pXb zG{}8oxe!dl?y>pK_N}t?c#QI__k#S*`|a??7miAWnbTDX75~QqAnTDlB&Z<^qzB%I zLo+)gveGuZgEw(-NXF%?BxrsxP6p$jM*go-O%NQi{@rMec66~F73KYWF9q6!wj$Ll z8x`R<nb*Z=xC};<<Y74k3jJR^=S5Dy_0DCD!!B=vZFhpWz27yk3L`z!1OQyVM~c1- zuiyelo~G?XxPUFO{rG2}Qn@(B-SZvFj5gPgl_D5F1|=7mp-<7e*>on@fl=5t-9!zM zsD6PT&{zo5<p-1#FA$=-|Avg-t+1d3tfQt1f4X|xM=dN#duTrY&szS9<DRsa%fe00 z$CH1p?90kINMEcAcl)d&iC=Z#rPrYxwFYuqyeg$TNm2T{;Jd!%lriIk*i@v<q+9P# zd?8HO)D>nKI+W4hdxMx)D@doP9$z%Ymeos<xAGL~PL%#RL|Zp6a!|EK257--gH91& zeY(XG`YF24^ty(J1h!>7I0(NfR#oHZ-`LD9`2RLLd=Wgjfu=$qwjs!bhhev0ar;`y z6Wroxdv3-;Rr;IC&I&)ubO-{LJE~rd$G0Z4N8GH4ziU2K7$hex)-~G@)J)e+kN-aS z{5bTMLY(CKFNBl3j9>0L`<_BqJ=#l+0OPx~1nW(F06u@Rl*oe2grm+mIiKzBcuNCM ztlo-17Q#?nY2zug*H~%Jy0T|4C3#X-p#rdkyvJWbfJx$3udM@xq$WJ2vksiaqlY6Y zDL49BUFI&Qap=~WFw`?&{>ow%9)g=bQmO{op-Z-JHZN;_T>xGs@|;jg17YW@wu-;` zRkWE|5(jIa_c5B!j>D)d9{Q~pc2LiFgu?>$XQ2XR1L8pO%j98CO_BIO=URt<%1WM% zt4@}=tM?towQ7|dX<K`NxUSCja;WK|LkZmJYEJ^5%i*CgaCv8Bi0Ep}u7P!c=8T3l zwO25vbPL^lz#<^sj_25)dh(kiXg*fBzAlSA=YcwQ2LE0Dx#?u;D1P*Wl_`O@5NCkG zF0bAE=Q>gx@M7Ud998G-w3=fGKQ@j@B|ZoKbh~0xe7_WPynb-gt?})3|K+VI$|SJ4 z*geyW!Xm)hr50`vo-Inx`F^2>05-Y(&B@6}T+yD}?+l}Z!++8jN>2DZ4=t9QOli1z zZ0&jPz8dFynUJoS6=*r=?LJTgW95y0zQL#291uWgzlraMzXd(X#N5H%+=Sxa1re}N zBG6Js9U!hjJvi6?naR@%&+sRxJS*_<Jbks@4f1B^+!+x1qVsb?&H{(8fh~cZ$iI#Y z=EAA6;s;#C!rqAImMC_46z@!Iq|K>AZz<&~#vI4FeRr1FV;;CWhXBH*k?RUFd=S+* z!|%3-{0?$-H{P6ze>;{rw_j9r&5$)sbei9BcxKM~CvqO4B=T=SoY!afkpJexCHbzC zI<!ghO;;X>qiLcWv(d>Z)N?T3dP}U5Q!JSnCgX!&e8SI_$Cuuw2q&7TwG<;2hN0xp zU;Qc@Ng`sC^)WQFRlVt~oyIx_&eKvgrT|(<`zM#yjV?muBR?Ld;DCh=fM11{=cBW2 z_6-<+-ix<3&<InX-M>~o?Jvm;C5_hCgQoDCP;i5na)L}H3j^$R2?$eX(XQQz(`%z3 zf6>}E#z49$0|zybO)1&%j^5GS=(5Svyv4~b<8j3*UA=LX<y8E<PJ$9yq}su2I6;Ky zHKX#00~9}BQur9R)4ZV{@8|E5uIFToe*RV1@}$8n(>p>BsU#0kI%-s*06Jo?lYt+U zSBqhj>hO|I9kh7<$Kdok)cKXSnUZa1$Uu&IF$2kri18wokJw9!V=2hPW>&0~<U0<| zQqobmuPVP{Y;#0ChGo?zpKzLG5&108Wry1wLlk+2?iGkRhT7FeH2C4ax@9u|w-Khx z9}nFcbEFYrr>P2d_dp7+>CgYZ9WLYa`PVYleYt~3B>^U8J1i&+K5oX{AR>#(p5NUF zW4UA8{Pjg{o>J&bCYnO*265I~(km#ZUY(UQt6gM(k*Ys;QWp_pSriLwKkev?KT$8@ z9U?eh)5@m{M|p@J_pbCb+-YOWr|psTrDfy*OY1zfuCpAUP46v}w_^Rhh%Zd)<7g~= z#uzgugIThY$V28kmpIUNx-2f)o%*76(`P{7Q=1D*sexK~><aHg*B#je^-&n|gtxcQ zu`4keYV<Ou8)TV9G}+a<-Pj^h#t!M33IB~>o{-CCM-;E=*xUpW`az=%T4XI>ySx>F zMqeDm8N^LeiDV-!5;*L3;Mq`10cpAU9?u9%mr9XwydN|?z{|sSi(i{<vC%QSKg9v> zIX>4xU_<cbL5^Ly_*)=@;Z=|@kh^#?2sE-v`L0utn9|<EC)8vQhRlHwKx_JD8}GxB z?x}@Q-l5R!KQD;@-jJs4?a8`4kYK2g(d@eP!+0dhVJ{Gw04As_8a0#Dw-J<g7AD3U zPJDqESoKPd<TR?*Sln`acpv^<+IW0Z{NQDL;0X|y&n2R;H++o$M3tol_$ZFXn06WG zY65Vrls;RBhte;Wl_rL@jJ}93vHDGRp_V8l6d7WM`TiEp;ESG=#U-c-jB}8PuIEp{ zE<IlrQjwX^Ls<6SP^TnQJ*AF!KGsGV%Uu)+cia#=HbW#gu9HjY9NovaI(Ac>T>2zA ztqlK*56<Yx?V&D&2-Lg!*noH6IZ59XUbHCMDb;Ux#fF)q)pvgS5ELD$*Qw}eE0bF# zIIEpalW92R8DaSnoWib^#Cx683KG0}#wCIeEghFmCgZd~Y$_A>=c1s_b1s|0`Mb`V zKgE)v`R#pBKz_RmH*oa9P;TQ^dIqVjVLtIO$|wm=Jk|6@5A&UQK7)jr_Z=l045S(u z#vp_n6$9&e4qx2q0cmc>jh3<_^N9>b{1NW5q98%9bg|}ZkiTfvCn<By8Y`BhOYMI5 z-@cX<0f)GK=0H?ddH3g9d`=C~f@wV!5brs0Yn%?iT{&<}+K33b>6W<x;mIH6D@MS_ z;Qe=&U6ZI{Mg-Dj@(5=6H<`0_TFMjx)ytg`Jv-pO@tv`MSkr+stqY2<oza2Z9VPRs zbD)SFRhWHCN!a6#?`ylaqJ!SAZeVI&1+gseOFxOt>(<L_3($~-UOhd#ELyABQ1Ck3 zii!w-J>Y&Y>SaE~OcS*>S(U?cwYG#R9x8%5=j|jp{PEBKyM?}CQo`j57wZ3fO4TIw zY(8p(ethH2g;#j^U3RU0eLkyyq!Qm>l92dr(J2bbu60mmyxy7U848r(iHnK0)uiV@ zKBd~NUTKXO@t7=p{r_k>%b>Q}u5H&_tQ2>G6?ZM(;#!Inm*P^SxCPSU4#A}m+@*MN z3dP;6kWyR&gaAnhe7T=*-XEFCzf5MXz4zK{9p|x5mCtW=ZLuUopMJ+pN-eZ49x|0X z2*$G~BBu>u@~0n4!G4Og6PGJtqcu4W67H0H{v{(lftW!DCajs6qL4qAre`e{GMP8H zASqUY<TqHXW;gi3ZjOadObU9-C(|TlhYI;*g&2w)PyXv3UgXIq33=*oVv>oThUa2X zd-6B%D}q1WzJyrz=K<BDPQB8?OIoJ>zHr3%J2+uej?lYyK0+;#b*8q!u0c5_3Q$3; zSncLzN$kzZA%r2DDO`gq39g+wZt+1Sz|xxsb0Ji{+%{3<WH&x=cQZLgaK75e_W}kV zhk*Y6%_4c@eJ=I>_FS?Mwk|)(ZIr|XXD+|LY%IS~(6*!_m1(_h@TcGATIlDbD*qVM zhxM8-7Ri27(d_vy8z}@b|DDAJV&V)6Af1F$s_pSPcen-lUQjgUiM(^ou+qCyS-n)D zpejJ~h6*R7zu12>pC?v^f6cB;-?^>oiw>s6KJ2ANl)ek*u*o0n6tQX7_ZS5J<KW(3 zHDDJKi~zbT@bO)wmIrqr5$Yd*7q^&&pS(c~Jr&O6S5US~Nkam>P7}*wNn5#loQL!^ zmVc_T_oRRPZ1ri5Jl*@hQ1DSVbZ_Bh@;$aeD_2Ef-r~&%{r)D#g7^Et41Dhk+#Da* zZi*wEEokSUvi!zIz>-dwHGl`Qr`T@gQD;_2i%mpY8WB>tL`1HLnWjaV$_J=;!1Uo{ zUKLBr4Z+kF@dsTD;ath8+U7P<#iXP`dKx#V%eD3W`x&c5O`}RNYeSZo8bl;*G2WjY zB|uLipILiP75H(27z_UNi2FQ=oXYJ3!|mO-`^2O34EdGcla3<Tjk^pf{OLz{tF3R8 z)z8nnbLn%m$ID{}`?r18xsMo>!$%*tf9-2@+=>g|Oc@%usC|5PnX<Sg2Ldn7DOujH z=x$()v+NHuDx$FS=C$UnGs67_hiASPdBtz*{NLpcNv*+xHb9clxN)1NmBV*F_53J) zp=U&x^>LL^j3kwPfUBTMiKoqI-0(Di^!(<@O7(#|`x8Amox-MfsY#h(&pDzKYPV!4 z?576OGPwBIww6!$TtV*WSj_bX)V(u|nQ}X>sw)v0L~4&_3)p&!lw2dkl)dw3W+rtj z;>GPL6Te1h*NI&T!hh|In3)$d*9|jIULI}Oa7<lDt;7;VFH=V@S)Ai>Yj=x@Lk>>f z%%)a=V-a`XTKKH&Shk>dVUc%#zIY#4++Q+GP|4u~Kg+ru52Dh*MBk6AxyGh4fB@&! zu<mn|ic+2pAJ$tslC4&sO<V&2j<l|p;e~y_oWVsDAACJ{?y!C|Ll|@fG6p5b=Z~W^ z$jKM{pmP$CD;>8X=umUub<&fS<qxc1{FC#Wgt1U35St<fVYHY#If_-u$y1oM;4Hy& zdt={2H5aF{wJAW*t5ax>)DHH*ybDNf{XSx#*ON1qQg<hP;Z4vM#_9GSbh#gGYE$7t z9-5Un<1EHw$xB8^CMocJ!b)zfYvZfZ#D_Yow4TcX-8VlIuY+IvXA7wZ*!e^2W=zW6 zn2)C}=uGMz(By>bpp6D7#4FZGWafM)LaxnO7WjbK0K|ZJyn9fX_>i86Ji<R0mH!_$ z;*Iop<bMUiz!MFT2+`<}l56}6Ca`;+JnGiCg!9vWjvIRRiHYs7ip@zk-7>2GAxr7- zCTyE>w*k9I%-EPV+i+vb8A@V{D`V-8Syz5($?u|cNWP>8{SQ3q$G(|;@vZU+`sNRD z(;2ZEp9|$F1Zp<c>FVc|RBRkm30Y$YmU3;$&gPVVG*{gkw(9!>^U>c~oqarrL$K`P z_wOv0vq&$6FF#1T1wTi`^`Q;B;hx-gR*l<?Q-?*0KUTZ{zQT97WHslt*PO`5%k2rE z!uB@7+m?1_2VujC&m`tVYX-pZvV|*tD<f>~lD|&fLc#V2U^gLer3nkMoUcjiKvM*k zJ;wdie9Mide3onMbd~;IA1&bzJ)e1(tyjUDDlNHr#2m@*gb)-LF8Spbi;pv~oKC0R z{e{Rfmo(;hp+58#oMAFlul$-DSfe9?z4jFhDX6Lu#u6kHZl+?nd@(yg_#`I2@04g5 zkCbWx02cI^8L#ex!>=|<*4G$5+5X6mo+muGS@t-Ag#Ur3)+Rm;WcsNns+s#?&+yR{ zVlEbT%5f3_gI#XJ8MHLV)M2aTJ@5EBD!K`$f=>%E<Hu0+(|}W7sb_E^e9*0?EPl|} zUQ3Qy1ALx(8>G{rK&7ludm>BUo1aL*%*s1C_E=2Q@Cj?neiXGW=L_`X+%t{)gr9UY zpASY%_&FtI0^J&HgO=Qs)fpe0_}xAWiCf4AzSeM9F!D=OXm%D2@~UjEa_*M9`EecC z=c6KA{%hUFnt`02kAuoh&!4^@>SS+}w{hJ(bh#84?X`nI@C23t@;Hq9ns~F-^JxA& zoe{V$_Sql#fX(`StLbOO?Y{_W`YbtEYZ9$68@4~JQ{DY{`c>z-m&oO3PI{6!VLLso zlUY*Nrm_#UN^D89+uN|cchAmRPuCS4R9*;{O?(}W`qC+49j6e&)GwqBN$<vqxa@_@ zh;^xG1zhMXWfO!&9K*(Q!*Y9Wi<9#VkyrrY-`Cvf7-?hGQL_cOu6ugE*VaXvK+A$; zdIM8YE4V8CQ;p5<Jx%?>t704id1!>&zX>NkqeaCCL%ziQ(Ea5=^OJ&Cqv)Y2GV0|n z8Os;J?Pocgn6T$hw|ch~RY-V6+3g5&TfHBbx~=4gxu?Jq!Ls|oLt<`;5owi18%w>m z@cPYsRzQ${w@g(Nkx>lW`R&@Al=vuiAb;abasy#cWMTTwX=&$aHyIL@^a`?3by=ef zwZn<Vi7K0>RBbv12bt+1|7)MRg1!ue%JF*aJ@*avf)f6_w)S%<-&W9Q_Xy6d30F-; zy!^K4nSJ0EA0;D|HTFKcn`(QQlp`NrGfUj2Vh^-so48cu7Q|H-(&>@m0f*`&zgDI! zb!*DmMQEeEUWKqEOEKq&s~)MEbauy-OkCbeMGvvpuxXy#2&Mbz_mp+(&q19~PKf^L z=SMV)JqYwenWF>of7R6%_84u~I<jA*8s>H^LJ}71Q@TuwlqCqXHC7!#x}vOg@edxa zVkWgRJbA~_19fVFs4KBK_biRvaWi{Uf!pL*{2c=b@~Umwa*Od&RQ4K$bKEW+KhkeM zQD53oF^O<wl2V=gI*R0WdHYW%`U5WZze!|W(a6bv{mt?uGOU+<;_!T@{K|J=e}r8# zkiM9rJ@4$Tz;1H1lGL|RcFiZ;N~=~UTXWStXP7y5O}NN{JSP0YDEq%z_VK*(mO2RY zq{LibR(;N2%71JUbENvdx=Z1Y)x})OPeU{n7~23w9<@1oUM%()b=NXxXszM9GO|8o z@(_=&;Er)b^TVHuxw^&<lMU0qjWDgcKGCbvQ&r}8KvbQ_rEToj7EPmXwe`)d7_K89 z+&rq+`$KH?#oD{3iad3@(P!_*g}w!ua+Hkl+iNe~MU6T@|H}JWo<2$5%qxnl|99l_ zCipzWxxX*ij-Jaj7)_0su2iBc%kc5KYhIf%?AlWY27H2$nk%6y292+*+hwy6MAe6q zat=`<Ham}wB~U4r<2O_%0r}OvuZ~f<4#L!8h5=1V0(&KjRaRcbF>_O11+?PzO?$5j zOm|ucaF!7wT7tIPqkWyKgG$Et>1hwL-$l=0dh|=$zZ7M<ei^yqx%pdl&q0_6`(d12 zyHxc~x6>*#S?r={;O1i3GV~$Cy`y96!@gG^y*9AqxPy=<ZS8ursEft<(1m3{AX>O% z#bnWPqPvdAdhoguN=m>L?f6yRfOoLgT9zsSa*D`VX7xC^MJmS`!oP*ZUom`iq%(GM zvr&1YB<A)x)?COMZtQ&H(<;>|KJ}I<speEt?hU}a-JcG|n-x8#@O=vfNnLEN`&6qe zuyaz|$8WY*dmFtdG#D_Rh`L&N?J;9`(Bb^DTQ+ER>n_t>Q0ONU^EWcsOQIGoiCtcE zD#>BJJDb0ztw7r`am!UUfb|w3y6LW0T2>T9^sC-zfg*g%^ZvZZFK|P_O;Aq__c#n} zondi<EX!>7?xGlp+EG_a`1^_baGK_0Oa|#>Ac6ArP;?cja?c-JucPyU!Q?$q)H&JK z%w`yIJbfB*tsH9+gf1T7Un{m&QXR!nS`y>D_gTo^hZeV;-L>4E5nu~Yz}Zpb)!ulL zDsCb>3QV-1+qLR9!p5m-d`vB=EGXK55}{lNl<kZAg9~hQ^mc_EfA}7ojs*<&HqG5~ z&>E@n%I?OC$^~o;CuaOBlD6Pb`o#Sw(KOHhm5|_^B;TU^R79Q0Mv5@2U1CO@|NLD6 zB^MF+vy!rXgel8bR?ZUk=yv_|*-L1^;iQp0N6f*|#rN!_LEI2q8f8!?DVG;?$@tB? z`1z(<m`dufJ-x96${fEE|Cp0%9lj$JP6GZ6wxv<A)NhK^P~RDgEPVhW$c+Mudt@yV zq5sNk<jFjX<h$Gbn72@tF_k=t3G*Bp*ZeGCk7jL_2||YF1{59Y+H%7jQG*Mat=6%Y zNZhB8-Wc<K1^H2C$l}Wh`*@MA9y8`rW-M(rCo$reDQB?}6RjQhYkRLMqS@*-nOrJG z7Edn{^~G2r6T6yILM~1DhE5ce?HA@WHIyl}xjRP85C7@CQ#2A8RZR4&fSv^#3$JX* z@z)p|b*lmjzGBufz#4iSUTR%1AUL+BPoS>%UPEP)vTZOid8=}Cum=>1f@MVg<yVM^ zWDKE|_kQ_V=SGoGF!oq#G<aJ<4fRfmTVQSomCRR1<nNITa{M^O`8jO@NB)o?`=&U1 zyUGSo5@2z86o8@D+9(u0=xQD-yGheOGT==8{!$#1r*dzfHgyEBW$G!rn}(o7F31Dl zW5rdA@5t=UK=6g<obwqpZV%4sln#O`=Y%OL-b&}PafzouI2=cp?j}y^90v`rdZ0Dk zu=p!q=@IjPh;JV;P9VKgi`ZAc;^7ZQhnzq<J@=g81^n$J?K~<)4tW)Vvf*ye)U%jF zbZ)qbSEg0~y?^j!>;1V6-xhMm94J)_?TPF-KPTph!E}ziZ#c(C3t&+o-}<v?{UhZW zln!L7kE0UC_ZnDefRQ;Y>l!i1yJl+#X?K%PrV>p(GU?ezxyoqmqV~q1BHKD;fNR-q zmB00N1ijo9M&sMlucjzR?}`!W(8`_4r^qoV{JAs>(^93h<R>o>T=G(G<k7z`TtOM* zgWVR1syT7ph8wZN_9XzmuPd-iA|J3W1z-Nj@wuEJW%$D*{W=^@3KBOxJU-4hn>p69 z>XvM<KZ$AN(LN)l+m16g2bKR>Lu}q>Y(VV{)7hA_4s!IjV*6#wS%gMBM}DV-UROI} z<mj6GD{6N{P6r1Hf0aK}QBxIUc`O3l75|T`+YGt_fkdxz-;@&b9tTwN6Ta+F-aXK% zKTFA6os>`@5kW17d+xvSO<ujv^(W85w&eUIsKB$AdGepp@d^pti<a==PnLh$)3Ce9 zdPAeGdvmZWJUPjNMlZ5*Z!l64<GK43;Mh~QvkN2^Y%cfz5-_mkq|tcQ5~ub5-3Zh$ z#jAg+HrNEuW3Iqhv2ZpQ!|(|xOr*LlN0Vu3B$ncA@|HtILrpK0U?b1=xGlNN$WMho z-HV33SR=R7kN#xueY&ZK(Y-xA7h=pn2|75z4Po^65Xq5vl;LW+H(J)~d`pz|Ie0I) z?_BCE6uGQCweVHSF2hEtKorfLv!{qEQe=a6yCSFy9LbK7qUNDa_(vQrFE4f+NiK>u z`gsV<vEb%^dIZ;H`l54<jTF3&EBOLbe~lf*K}tUS(}c0>Q$PRF)z=={l;el;fegHx z-;%=4t)c}p*XuLRkj*(FFVXMm@YuoXBBFwf%2_)!;4D86QuQ8_9vq29a$T7WS7=By zjqDZEhpdI8OBiDT<Bj8?P5~pibd*Qe>ZZ9>C&h@9cBFZqxErceB(ujQg@fua4O<3o zx_p*f>9zH&KmQxd*DzN^)%X_<p5umX4$ZNhFE(kX+i*%BaImoG38n`0h2&KxL`%+? z+pyw_Nfh;W^xciUXOQnZ#VgyK4sR^o=FC%AI0%>U!_xe6P>{>6hA@k=c925piny`6 z48P+E%FV}Wy0RpKrCI}9l}gfJJH^{pCrc@X)Tvcr(Jt+VqmIAsMb!o&KC0UOLdu(S z1tdJthNK=XljV2(OzI*PH{43i`wlCtxJRoVgKzpTa-HT|>6Eg~!lJBq0$MZTb~1s> z81lH$Z#?}q(IL>ho2NB)0j+xwmG`K!6v*8v_O~j^LCc!zdFwB9rtZs1RNL|-J@pTA z)HaS0EP+w8J~#~A_|`xy32C1uRbVEVX!Cn3IoebZtj<cD68#4$C#vSN7dxNJcN?u| zsn};3@C<aMMMBOx<KEByq=5_xjp$ASf#9&fs%uGRl+bKyN|Okca*O7tUe*qjKL)8^ z%wcia>N9MpaFHBW`|1g<G@Zi*c@?(*V4F5IY+Wq2J#s@m!m6@v@dL|8vS`)wyKJB| zL<AEB-475Ys9|DfE1^-b7=;41!1H3>4b&7jbmO|}*lTO-?%`Tp{b}MPT9VltqdRPJ z8(f%&Rjsr>0^8Zh&MMd6O`r<sbn+K&S<>t+(U;%|(uREDo=k9?pGO8E3!is?vSyrU z!uayYqBbKq3vu0{_H%$T`-n8;WB!PV6vtRh=RjT^Nkaxz^cXhhqhjijDIdrpC`3%L z!u)f)hGED?EQ5PDj(eBdV`anci<WS5?-q}_K>Smlp!u*T>NX@8ZGcJEfZ<hK^Y{?9 z#GDPy7FF)T1qC?_d_?<H(hH-OdjOY|HnHjQIc-CHceQ@Y&&<t{4SPSxg7^O+s{Ddx zzts6;1_h?_8B*pR2@hiXj_L~!ea;6(@J&St_iD|^2T7MybT9r11}U&)%Ua;oNuxvf z|HSo(F-9(|F%@LROWDU+S?C6id>D?=e|xg(@d>~RyZ{gREzBhdm8eE)MaEIMI>4lW zujFOT|EVMl3UnAzs!nBIblz5x@r2LtNWM_)xW6H~WcG-qazA0j<T|_oTvBs7gF3Rd zz8p@;&cpq*UKQbDi8j(LXv@Zv(g5l>`mbyC*Z6B#kjVSC&u#zBQ~-0@$Blo;YzK>~ zZ)d?2E^A?A9W6&v8eaP8^d!%Iv_rpak6OLo%8%ti0ZH_aOHpr<&2Xo?f~`#ycvmQ$ zA$BK@)-wv0L>-G1k&4a|t}kl;be(wj6m9s?EU2Y7r!I*NC4B0Q3AdXO(7f-?_XLnm zpnuw~(_Fy@FDE_|48@zZA?`oPTtRLI^wGGsQ}HFz&vDVpTki7i(yXghW;Uj4UGH?q zF4ieD`?dBaSDgrt_z>895p>YaXi?G~gWK8T*^!~_U87^`5)KXo4Uucy+Qb(qi)s<$ zyyN#t%woj<s21S|p}ifPpMxCoBuPgGF=a##by6Mtc3NKW`#%;S^{bU!x8)w8e=}9K zLEY=)=P6>qumKBDE!f*jfre@QY@0^yNL9>dwafR9vy@fnE90OqzPD6CV^w!bS_Xs5 z>5B#D!7_o=nq~3)LGOi(eczpUOl6LS;+t_29>!%Zqs^Dxj7}8s18SN}xJ@+a!ri8F z8;;pJ|Cm>qk}>Brw^sZ1wWk@jf6g)JdLLzKqc`um_{6k5a7-JG4L@0;qa4#&beMkY zQQssK{MipS(W^*ce6;Euxw2J{zTu0&aO(O|(`GhI>nIg};$EytvqT!Xv=`WA#gy)h z+`vn&HwNf%`ztBs_f>VJjABaI#9&b<E!od2wS!yFHuqr^EFo#Zw9?6pkFVl#n5hVI zFy*o`>vben0I9R~x)L*VK}>W?1i8#whaIj($NdtCIik7tj`*2qTC|;Ak3f}d@AJSG z$wS%qdpOrX&wpvT{#OugS#m_qdYO@N{L9+4F#DYIJ9-S*f>JI?Qr&La_bDFia7r5y zr~e{O{~&CeC3>DL(T3$WTlu7@bIO9W({GvhCpF?bZ5K!wHebF5$815;Vb~?FBN$g> z<JRotccw_n(a0tA`31Uc2YwQd|60!Aja*bWS#eU(fy!pyW54++zP^FBP?ETf&oT;Y zLJP3No{mRGbq>Lr@z)~JX<*B7g=1mJq!wA*ez)gilb&xf%kMxWxrZ}TIP9c<F%NYw z^uN{?HHzTv-`K-(*2;F~ZtrSjkq>iQy)3C#f^`|tMUkD}0hwQG0#)6ph{G6W-LN+` zYb!ND*TI2*7Z^kSS#l75f%m5eQ2E<Ho`L6GwF?1R5A3;3*(6z?|GK;zKV3V9q1=gw z19DsXr2#jsW3mp~m;Qrgmwqq;o{Oe^>HXaf;s-=+%j(Lc{cm2SFWCvCBQwYB9Etp$ zK5gxm8=NyzdYr5jB<o+=)Eb=x7RE9Bq4Vy)gG~)|rzn?DLiO_2L4{TdL$ko{b+2$N z-#9}SbvI`>`2>No6KFx4;NalAi%+(l+0Sxf2iN8EOXb(~C-iMK<%+*FaD^tPvb>ir z@vxl?v0M1Og(S8OEBFO;VNNq?4wSS5wfyoyk5T~pu->P(FVw+r;8i7ibK8q%XI|ic z=@VrHomf`z?Re;$9_fnW#H~-Cr}7)H#?bMrf3GwZq@5%`hv-3QPx)0|C$4D1^WKa% zMx;^f!1r`f2>Ss`G7x6Vw<%Zp9d!?JwB|3#*xC6!g2&3tCZ*izQ*q%2!WSw5Jsr!2 zULzDa=f5UhoI0wdayVs;<W$lN23s;Eh<nVsoYffcUcP(?AE!PaTr210_c89?0vR?1 zH4^XYnDaFH=tT9heylVZW#^TluS=l%y6lJR?gVPiWz;kV3Vx}c9`@WH4PQo#Y0)bP zHIS?c`$-AnM1ceePACq7tEE<&fNl3;<sYcJp8n2;8`R}L1qa|uc^)T?&+|tSBUbX* z)(ncUep@BUiQFjb9!N$XzEhs-2qm<Tgp)$3Y<fMqD-u<N=GuZ-7Owz%%d!L<aT{#M z!<sS5Cfy+H81I{%&`>1{o>G40$4+6p<$U||O@zXeDqGlPzmTH3;nf-kjqG6Ii3xY~ z$EOW;{fnEr+(%$Ju9t^SIlzHkmlmpH;q^vWYp+Up<=MwJ>;NVXdIok$PMy1Y5*hJ# zzv-GMUf+;;tb6U*H8Dx&um-8Q8|<bn-SYv54g@eyW?*&dmqtj4J19o7`)!xF5t`61 zn?F`~5Mfh+qzfoS>F#KZ&9-WlJcRjyYcFlsi}o_4&6I%Bt}UN5zAFfYUzXI>`BZph zx~2>-1pU%;mJLvOEpYx{MOHFpvA!pr%KKrt0e~=)!h>MEdSfpYPRv#ZB=9#UI(&<N z#57s=r4+K~a<~}N{&=^|xlxp6;IH%O6!Hd;HCxgMJk6zeZ$KyXQ78O1s|f7+^O9?4 zptufcBCFlsd9huYCjGpik7R&*XVr310T^^)pG8|>D$6cR`J9bcp?z4Tt^u^s{>>s- zG8Wr{rCgMRH4<cA^$^e_W-z?_(_<GHEm$r^q}LFjRhW4U^eB3a7bj*!ta);8MCTT9 z=eW%QS{;)L(hYUynUyWp4^~il5w*$=W(G3&E;Ca(9Ffl;&!cf>TmOZIJz*&=9zLQs zt~-eO=eqh|s9V^&8#L$l0U^M;wLW36SXB$u>k8|>mplR7BJbygyM*SH6d0I<HH_;7 z3)9z`1NpErx$j9W`+;(x?j+|TAy%v(b@sC20@WujuC@rv1SeCr#q5}XtAWhcuT>*_ z6;2B;qDKY~SWtl<_$hJXXxpMMZIzx`Bdf8pkP#gP!lEWV)ECK%t8mkjgE^OdA<Pda zqM*o8l#WYJZ|z+&REz)6!UrX$RcH;B<o3|W?*T<|zlQM*qb;~Kq0o73A26+2Y0^|p zyb&XnK6OP?Gb>Dga=Mg#a-G~cag}m%syru3lv9W0l$x4?S&;i1J=`^i6l6hdw%Ooz z=cJ#vjBfQ`V$+}SKJ*_`xvxVgBLl;(lw4(^<S#LA6!{==#eYA2xKX$Y_K_P!iKVn+ z`2avehI*-oQYor#bWCKM*p<1B%~17k{Vu^H;<-Ob!o{YUMlGKO+|wouUR#*_z5$S+ zEMK+Rxf(xK+D_ICv$f_%#rs#~PJjJ2nbUr5T@CFqsgLp@Z_GB+YOG$W<r85Nr@~Tz zgZWFwxX&Mliybt3rLP9-n~U<MKoYgbUD6@1g94-snpi5y`QjVGA*tlm-)?hJTfSb| zVmQ|%BnwWtSAYP)*Ko3=)f?w}onewRo+QoGL+W}boR)j952&6B`#g_@g1Tn8nuf)Q zR)Zq9g7X_j;sbTFz()NeXZ^$Uz-NzLr1nN2)qR7ot6`DMl}^feSUoGrwz~W9!{yh; z>sW04ne{V=-^|Uy_f|1zniQa1Y(n3w!p7F>{=+UwTP^v4Mg^B{QgdB%;7F{yzrbKH zozo&kvP%oFhmb_9S_hRv%bSEr_c}`KYl9nKZO#Dr`dj*;ToN>jd8`*aSz>@)uTw5s z626xw4{^J!Sg>s{hkEI9N4!qc+GN{Yo8ji0u_-S)oug0dM<PVj9zpK=Ur9q2fM3t( z^wkOdYtmkS44=Hk=8m~<tQwUuTDy~>itEn|Hz=qqg=xhoM^sf~X5VQCJJ2Zzoc>d> z`C5FrCgms9CnwKS_s+Awd9Af8ug>Oy0n&f0!FX8(cEm;Z-mx{kC-?ysz^<j*clzR~ z2fNn78~hh|1cRlFBuTt|YbswqDlu;V7eO*^rCRwQ+ikO@^+`J;IK5z-UCJd~hR(*C z?Mhuu>11}tg{W;5;TRd{e%&=Xw)sGpRPcR6s@7JJ)0ppvRykXBad5%h&-f}Y7HTG) z5l=SE@P5hLtMALGJQ3|gEC-H%z?wUik&#9=?!dy2tjQzMEiT7c(B8gWPoH>sgUAA2 z*iFXpDNnqbG_ct>YWFqKMUK0yJ?2a2bu*eeOHBW_6=dN*(&{u*_T$HA&{zW|eezdX zWH+Kcm@?%2q!_6J$Qo>t3jg(4#Iw`ta_boRKTZ=c=4LDwAANz52#|)XYNa*Xe!5#r z8!MMCh0Nb0iaA_>BU>SCTJ^WBRg1sBmhy1hDqF@v%_Npmq@FSa`LT58@=tjLn>Oxo z;TvgMl8F>?ROF5(Mwvpj%xwIF0_-VHR%cVn6$>N)d{G~Rup#-}E`K^Z*ENTLAfd$R zaj;`O=%3U|D0I6OKKu@Q)+drk7fX$K3QSAd>@mvpJ7e1uiCFHJ${bw&BXTNF_;r2| z=<rRp7J&Ks@eTz&X$Xv!hhG@qdhb6MBefQAO1=Byb`SYyKDc-?5d;HXt=li&-vINr zQ3g9zqPwHMoPna1dy;F7mYV@tw`olQAlGhE)-23Cg5zlDCDzO-jK3miw+NQ}e(?Nz zZQ=^j{KQ~{abt<inwQB(z#}8lx8fA7WiD%6C;JCzATwK<Df-aA=6~N^??15oovge6 ziDZ1k@`ThwTX4V7!0Hv1GL}kbq-s>*)A#PX<Z`*fjHFa`b`yFlk!W12@15=VVc1Ht z?glkLho8G`97z72GlpC1UDhRUb`z&-r*zYn&bS&|0MaZSv6GbhE1H9;N9a2nyvL;g zd@s=Dyl>T@$wQRPmqLrnGSIB|_hX13fqgJUDfcd`{-+x}(jh4S^t$3V>-{1?3C$eQ z5`61r=W$<Jtdt9URC%wVrWErYM4S3M4(H@(s%8)%w5#K0frD3({M0CW9YTooCI06w zE&8lJI$FZo3W`cp^U&Y0;N~HEqRJ9{_?)sW>3|}$o-l<lTq`xchO$ld{n~^*CMT_| zDdpnM9LfWO!qH;GQzF~5LEY{5-n<W`!DHjZ*`Se&ZQe#;;}_@7*P^*)$)8EpUC4#9 zx-N}m+;D1#AUe{afJflZgS*X!&4H1J;)OjucLY#{ezlL`guDH9J-y$j#MCUg<>f<u zac_0?8;>e61dRDBJ(x@By-dGuQgObvqHC%#vRF>Q=5S)cRkBIs7UP0BvKM)ic1TBN zW^G;&V=9*^zAc{Aw~#h^f)_QhQ3j1I)dnNB$+O>?v&0=iceHIE3O*5~a$T~hQTRPN zn9Fo4$9-D<{cX-*JRAP6lgy4v+N?j9d5(^K%q;y8!ke4vALpc}u$m#pXbnKiw?36% z39pdpucymM&;KlgPVho8(UjjKJfm2v9(cA;&?fbCW)c?8xDL)t#a_^bgBnZzd1vs@ z0{i%XGq$@c15>)cW`V{2AvMQX+h4<8lXEakQON!8vFb{cI-|)Myl@5aIio6yG31AF z<m7j`>j5Er>A4M<z>9Fty?Sh6o%QAms#r~8E|B*;k3|tK6%lS$6Q5F!#q(fh{Xb$l z?O!bXPmgL?k!?$ZP~hDl8G8v<$DR23Ip?{+7;n~5yuHQSz4mzSwd<4fqWxB2o-#%x zk2BuVt+|m~IcFZbl;WQzHQvj2YS>Y}mvT9a*a-}9P4`Xt>0qfexyC>Nd~Z1B!)wu3 z$g03~CAr7g)NEp*?0N>VSQHV!Fk4pVu8=qA{CCmfrWX|b1;>XTqg|76IFciR3%H`< z{f=9FchIj@_g0vTH^ss=AdIcjtS~NV*c)~ilzOy28H<${ip{2gpNRoUcr2=|rCVXE z3E0pwKZ}S!QFVy+iVI1bpJ2*Iv>^snw0?mY{n)oHx@c*6Fj#RfmZhLXZ8KgpQDtXY zaBL1q1GRr40#18I{b)7q_J2G@c)}<xE1eY`UQ%UY4wUUkq?H>A*X<fjbXdi8)2p#u zeU{Bvg};w~DF2HwZ;3Bc-nm$rtZX;4T&A3ccRfBmuHF#sl)-C1mh^f2@VXwj^isEh zG*Nj^Rb5=resIa!PL=+foowNy^jwb+Hoq=4tdCHWjjuRqH<Ce%3JrdOj%<~ljAgPC zbVHa#w>f9KN+=vFjY<yv>WoY*q3SjEzMHFL^OQ4d{maoKVp@yr$CNHEe^nBQ5Q7Al z?9k1U_EOT}0xt4REZbG;Ni<_VcI}w>rf`FUzBmn6CVHnU!f4cCu&fF@aIvdMj7(zd zP@orlIfSqnx%S0i8AIuzAhVu3y6p@`?nj9>!~2<kEHlo)#(OhTni8}gm-#>Fvq?fl zYbT_Z;};26?W#>S(h_gYzn}@_9Rldr?>4UpeSx<^yUz=MC%t?lC_MiG>KduCjaQIz zQf5e}+0!FFO8}x@Ct2$esDyyuk6%UlVX9PQKc~Z{(C@TnnTmK8e#XT8e8rNY&0+QR z*UbCwkC^UpC@P2_d<(3AT*k;@@}oL!3oPc3-XXxWQkO-+Ne(UuUy_TQ+`BR;c766# z<ci2D;P15o<w2}ii14b#xqVO(l_SU5^T!?;d<bj<uSd3u%{|MTLJ~a|Fq=MeD~~Ki zDJJ~hDFKuKmHz3(wG11^#<lLVD`!s69>d;WlpsDhyhz#)vO%Cdg^ys#;551SrF+zL zG@)be?z1vsRMD|_wN#%+Sl&ouS8cFqUHwBRVwJ3mh1P~2UJ-i{Wh^6a!Qh4)W=XAk z-ym6g7$6w>Cl2e444%kTi6z}B4s!MP^jHGDyTi_!KZKv=eR};+ohbveua{u`C@1Lm z*z)_W%yX%gF|KEB9=H*mi;obTST!pz6e)g1EA8BF^r<CE0EI5e5&I&&n@}+EwrrJP z+V}@peJZl=6#wo^ebb18&;3R^yz_hJ?5as{Xim$k<agzCRoBP8aT7-xR<CoG_=fab zCa01`=|(96h(E@p|Hj%57<7%{Uxf98L|J)X5)2V2{0a4|&An?*T-D;cwrYbH{!1A+ za|S1~Cu7yb@l)iWdMfoE6eOc8?GD+kQ%{T%X(`oC;&u?a*e;3nFnO}&0fZ;`wJ30G z{$6sv`0~9c_@g1@5T{oPp;-&lq)+j#DRx+v_DSav*ZJA)X~0`GNNfiWbC{qUzU7f; zV`^mZG9Pm+`f_yvk(mhH!IO%1Jn1lzscX#OE7)n8q0jq#+{S$(`oUp%0h<cB^*R;a zYa3pZ8X2wY6Zf!oocfi1(&mFEr;exTTj$eyKX(W-ZY44Yohpt=M89mf9IG*>2hP_8 z%u|rG4c3``tC0=1cPChM@6xI`*E7NotctfqCs@3ROn^)EuZdLZkxA2Z+8Lex#||AA zy?$2AKV_xi$cFhC?@1OWeiHbv;`S*|-KL{(iT^Wiwl<t7Q{t18l*HG}{6<FB`A^bn zYe(Fia%$Nven#bM#{Ph_hZoxPkfsK7KCtsX<oTYX0}o4RWcz!RqAVRp;gm)^7ddIs z6_;Iv$|klFwq}oiHCJ-QwXfe3y>n8%+DzBK#ABeUsq`fK(Te9A1`jF{r?}NUN1Ogs zz}2X%!B0wZUjRE$ZwdBCDeadT4@}E7vhherT!hzx%G#uh*?9=-=8*4?me+(>tS0dv z=e!|w>}S?EVv<j@M|Fh;MiY8HX(2tP7a|dFuo2<89w>lKyUcKF6{gC4slx85sy>G2 z{lHZC%SEn`{5V=BB4i>aYO`B?A!h99pmpnW)IRW&|43^UdJ^`~S<;#t8(bRSlF)^+ z{>w#P%V-}~zC4WholiP<g;d)vyjw!pQbRR$;WLJdnlW_^(rZkj92;kMqL+Z^e~A?Q zHK7|dAD`>|oL+N6D$)fM8IK4?*qT!>l2FuI3{B3=fhCWaBleoIWS#|T0Su0g%vy0I zy8ldH$Q&jd$LbpJszRfjO^>c#rY<Er|7IM$<}71YRXq}O(dtXF84OIgVBr_D(7(!l zHQOoWW`;yA^aw_lJtV62*HL!be|}sIRXhr;x@BSE`dw?o@*2D5)NJF(5RM3aJ~HNo zIZDr1BCzY`t_7MRe`5OS0H?Q~ssTVhxV53f3nn>vA|m<%ljrck7b7YK!<3v<L)~}K zNwk>|wUB3_&=O<>a6O0&uugq@Xe%N|&?ummyH}>9!@#CWctKUxvo&mb8xqOpdk{~d zvxOcEr2GASUkb?OeZ&Zb?_9xcc!TrYv!|}*p(sdYkluIG=F9sPNkaCjXx<0V8fVJ` zGj8_${HXj8S@uuwicKC6aTGGlcFe}=C|2U?lo&ZM(LJpHrc=z}qxbgRfwxi1{oZ?z z6o0tj$aYujk68b`FMY>0tSLDMo-p61a_NA!i2#tPXs{s%Pk2Lj&dD$eD4dCGODxN+ zKD2nlJo#Z%(MM*dC%)zcka->3@?i43+lJ5Gg6junjGtwNxqc(@c&GL*di!0s%qoJ9 z!|~wDt_Rb1jdqqK#*?9p@k@;tu`eEXHel9X!4esI6H-xveGhI&)D`|-VAl)U@S^>O z-|jGui~YE~n<5&~`IR;`cHhG+s|7x)bSbc)A?&_eiHHzP8874K;Is9XavUZ0SH@qH zh5%Wv-DZiY_1mE5TXAOXuk??XLxS20;uxGlBANc2<vFR<o?ZcNA4_P^Jnv-f7>^X@ zXk8wN-EQFE^9l_dOZQA2`%M=6>3j)7BlE+*Ax-5UE^8dL!J}e!ym_-ItxAG(H0r6c zK`OunJsYXPnml^LKN6~9N6PAv#cj&q`^fXx&8P6uxaFN)-@{vRKdZ|JZ(B(O0XuUN zmm#<%YHN0}yj=RH%S;F)Ps>!pfV#wPG@*ilyY3Rmxe1g<I>^_pS|pPR!?^blePDsy z=I1<_{=As;W2;vyeOsU&=-P+ix+hd4=N#v*n6`=u2EM@t)$CkNtuLQbGqB)yQzA+e zxfH4rKe`zLettm`=cvyyDK>S2!`(P_NXf5SWQS#gHl?IwDtiby;<!P2QKn{4Dnj&2 zjAhc~kNoT$<@E_33SQk?3BRRxV7vp-i9v#TjXKNeAUMqQ8pp(nVASib?6c)y#6koy zpbOBlRf~XxlwQj^ti4B#`_r^wE*_)x3l(u)bg0sGpCQ$lX*c})HP7^iWLl8--v8b- zQOb@pm=}attwkQmttlU_m73fkDEKXRm>^z@>FM3+zik|ml_7x}(POe-cO+Zn7+4yg z<}CG($L|XgL$oM816^j$T_hzF*yN$|inU!bRWsSG249zqeZI`aN8D~O!Y2M3xopZW z>M(koNSxtGNuG;v7^$(STHcf>Q_EcsUd05L4~Hx8=8-CHb22Gc5Vuuc!wNg<=T=2Z zDBxSz6Ie{Fs{MXbCp@+nwMjzTLzwW|*T)UdG3!8vg{$oL<5tIf&>wB1mw0WCQ}6es zJR1r$UMCmuOVzvBmj@<x;Vsh(vHfb7hElhulezuGA-|@v<ciD_D(h|Ul3c!dJL-7} z{CJU8lpp%jvbWRmjOa*q{6acnH2!6b>G9f?Gad(rqf9Zk-qnxfx&?HRl(Bx`ur~M# zGbPr0HUK9;Dk>`UE(*BGo724h>}(>RF)pNHtPoImVM%F5S^27M)Yru&sgNC$&ssyf z&h-4;C^cC|s$7y*#&b5&CVaax<51W`Pxw^Ujgx!5KCNU3n&3Xim>3Qo0PC_9EGC^g zZ}7J$O8UtaGDx|ccx3*ttI*CX35t+c%n?6@+|w_R+KlL=w`B>8NET#*0+8WKdGC)( zj*0n9usds<ve`ye77c`CK(&S~tffdwmt>2IFZ$rOH~w#oy~|2V1dm*c`D2S;@Nw5Z z@8s8_zBr6D0Cb{0QJeXnFz&TJ$FAcVNyGCfko0azECH|dCq3xj9a_DMI|P2cwh1|~ zMO$R@oyHO$JZq*4!4Ybx1+=L*5_vVsI-P1c9jR{UJ~|<sl@m%rO{LT`_4WPY)Y#?$ zH`$VvUY0kNjA(iGM=9_b-MRjAuO<D4kef>EJD{R^yJt(8XbHwIA!q&fp)}8&esSA{ z8dMopA(MmdH^z`l6Y-bu$6{36K|16uIX%yGEvgS8`;PsZ81l8pFdRjn?oB&sZj(f# zn#4y&pgI4Nw6fw)lYG&C1_JH+ZvAE<IdIFWyC{TKyNMk02Gh8T$@m<u@}UP!3xhw= zh?>$%J)|VK;kdREA<ZE|mSEBTf+DH3mZaYAB3)HyKFWs4Nd2`&G0!Ljy9ipvR8S{f zWrInFG9jn@av-w4JC=pF>T<gUJR4{!&M}r^K?yhADGeSyy(Vo-ZE5eyu_1oTlws+f ze<XI3LL{tdjWUb&bJ2Mh`L4aR$@~H6B9SWbITu0Y8*D+uYw}>M)n$Shvd}pgJQ5QA zsiL0|(5>%b%qb;P2>9NXx^JyLLK3ZV$CNcbx+ko4HJZys0hIcL|9j~78__2$cyu>= zQTbVP-?f~Ly{Hk&48A+D@u8ClNEqr`Pq$FiQfB{U_0*q=xM9UpHq8@S0uuG~v1j^o z(;GP4ci%jG-zF+)$)DdorQ1;vYYOzlzr9&{r%zwBap=n6#%)L`voC2XUiSg&cY93b zXLZa_YBTsp_fVD%a`5dpp+5>M-f64c;sV|*u<nZLnp9`XbY#sEJqSDEEd}y$9iyL{ zM%B?vEnf9f;6=E`7{>ul=kAEDtS#61EpStAh<_SZ3gpKk?XzCS&3p~w;kg*tiCB;~ zZ%re(BJ}%I#lxzCR2#E@pAr0FxBbXvPKasg7qmI>mOJq>L4T^iYv$isZD^IC-nJ78 z_38>}bZ>1uZY!7ZOiK>_e7kn&Y(`}}yUQ^iinhFyrWWz`B3izi5QsCjch#TSEID;e zA{$0w)H$05gedsl7J)Iq?J_ysoJRN8ogGwWGKaFyk+IM+gDtzW-$7Td93rjBG?z=v zw%iZMGEy7GYQy|<nw#3cUgB~RCc3RDYJ>5jO-o;!g$5?Qy{WdAO-d8XC%$fQvFHmQ z8%ZKc|3!Y_%_-3VUb})5PVb%wkZ-diZ_9OaBc><5Enoejp!u{s`*fG<sF;-rl0Tak zgO)BP{0Nv|U{E|i$Z8<Ra9<Fz(2pSoqDDSce}(%kJFe3FIC!piD1VVIQV<=pCwhlD z4W&K!l6k%V8vb{kPjpqrB3!Q718p#E|I3RRVvfiQ$vBi|tZB$d=96zWkoZ;7L^^g2 zYIoA~tNDnouD(d{Cp6}#BgZb|C<AgfytPF*VI+ihD&O`1f?;wvIA=TitqhOEykE=e zu>^c^Ae2A7&giDwz5Kz}*PM68=`4Fz<$~0UHr+QS0tqMfd-R<DQCEv#P5>}O(R?xg zf=%Y?-hH>V$@=&D)5#}v+tbB8bG*{VOJ8%}$G~||s;y(X8=4r!`~8<FlD=mT#9zxJ zwzsJRM6YR0120sraxVr4ekCkH>pzA;5F=`ojZXEpNPl&$qG0(Wnx+3^0ix3(0n4#V zEPw5(awfLrj|8lNvrF<yPpA70B<Y95M0pQ)HkaIFY#LsTwSI7x(k&)cHDv+7`3+0} z$RtyvdxglZ70C@@ayd`xuk)AqDq|{<mrcSdidi&A>`+AX9BLqzVuWQyD|nTWoapUk zzm?8LNxv|kxtQq8wsjLI8t7pxg>dtF!I2J)T|&EI0s}8*SU$D;xBKj*a7j>GF&8mD zN_$}g$8!bEPhdyV{^~4rPbt!gf5zc*Gxn+etGS{G8j1N8@3t)prq{B}`yD>2|K8FF zbs6Uc@#cvTkUhWq5VoQ*x^q|P-Xs3&^8C-IxVb08xbAl{c@LV%Pk-K*)BTAiQ-T3* zhfOBYJ=HR*8y2aFKkpMP$Noj_J%~X-4}o)<XdelPz@kOKJy9iGz#S8jil6sH<^27Q zXUsL5rfQ{n(uG+3%TTHN#dSey7)*HsxAwjvTlVRkY+i>KPQq)8ka=ORR)>Vv+gs+; zBMT;y(gVUXHaEvn!AnmXEd&iDRJQft;O;F1Rzi4+#!zhUad^1*w_RIY6Z1!zZo@N# z<HZ5}5v8K-n2wlpPMaU!c%w|me4Q;*JU2YThRq{vaU*?MGy_|UYj++iadO;`8}>Zf z1-2(_vJC9OWeO@f1wFFLD>f?aT=r*sH@Zj`Y4!BVB|G`fvM;e)0^4nWbnQ^IOLl(G z8x`GqwD7ym%hQn(H4guv@$JtgT2?uKr<my2A566Q3XqFeSX5-RJf+;}dXNZ(Z6o0= zJ0v`K3hH;u!|bJASE->Lf=<zo_j(>f?tdgM2+brHZdoVFS4Gl$LLKBY3-`uVf55LT zvMyrNYy-+wo*}rPWeTPJ0hhn`@4j$|uV|SIs*|z_F1fr`>pMQZs(qwgyzkTu4LQ(A zv1oL_wa0U1@emjg$blBg2RhmA0t0nHJ9^zYxD?^nDE!6=z?xk@QJvwgY%BT!yKdh* z@Mr904?BY#OXiT9P`9b!LybF&i#{us4vV-(6?Y*`HoR-Ei<!ZAWNmhgVD-lVNW)X_ z&(rhZ;RVk{n`Pu0-$SE9#(~KZ%|9b>`^{+W$H3u-Cx8mV8amTG-u3pZwyKZKaYQ_L zks=^^`tBq8HIx7jPWYO;)SMX4WmPuQl2fUI@)Q0$wH(gEog5P;iV{$HpBaC(V#lki zPp6I4t;a!zZJu~*yzPGCILUK!`B!vlwClqHinSa?@6t%aBYSg6qfPtCCxleA^^s7$ z{1??Uu5}+qN!w7q?uv3A>hFnRfTf1V!rickLy2Ewma>VzOX{S|VaU|}ycl~H=LMA6 zn0ENhbv8D`+;TBOMvr5Wn2U>3?>;LvW#0MV{%DD6+Ke>aZQ-l-hn8)ES@cpcTIBM( z&_d#GMVs1)w5mRulXlK7dHr=^zh7R4O&Bg0nYi@dNjToH&b4~YTdx}i-DhmGWRQ)_ zx+A1`_?}Pj)5?sVxhpaV?E)ZJ>VhJ0<40-D=8Ca*@%4S+mGC^}e0;&&$!LZw>r0<F zh$GsRmTk=E^NDgyK#dWNU#ZebHHupexkxoja`(pDRKjAF-;XwxQ(rEdqFuFCG#^hL zT5CtQzcjzPaQziI_X(Q{aK7cDg*-4B)M)-r!T7Gl1LBjEn*NM{bK`N!>h+JH#N9f= zZ)TCf26?cjR^qfy4PWxNE55&vX;0qqwf3h!gatNV$iL=g!6$BGAc>|uel>%=$JRvF z2W<`psu^>x;l0ZkwE6Y^h>Wk=XfW_%`UQ)5(Ai<=5`E|0U*iM9er6^HRwiOA&mF-u zcw3N7Ho(a2WcRs3av_1Jm?g(b1oM7n0Mid93ZoNf6}VW1V;OW0m|Fu^#le#qhK<U< zCMc<t7n4!Z|010o_(5}_&%jdm_L{<f3jb=4t+edvHH*R=M0&#hVcLq<MS8rfgL;ju zFWlm~SVnBS=ItR{F5mLWP*onlFqf}<8-O33DYZ5{Y|d0Mb`mf;DFj}F8{7pq->Fye zWz#4o*tk%X!r`=UHyW5IVpx8rUV6RB{r+T#&zxUHUwE=Ssg+;$E?Dw{9Q-qck;d}= zJz|B~Ej)pA2RtI&U{XG8BIq9wW2$DdzM(0Ilj^*nqQ;&CCTiG%I-c|YbbO`28|bFv zx|cnO!8Z0HP}lmN)nRPj2EcNhnt$@y_{@HgsW%lY@!sF#3Kgf4yX*SApW=zj+|PAE z`|=6xJkyi2zLI0`0tnnSB=6_E`Moi?B_3nIxGgBGy9B>;p&+B^-*|Yj`iDRjzAb-i zW8bgFWSlGMBy9E~&wav$&F20z`K2RiTkj-!fn`mw+HEKIi^|tO_Nyk^Z9}pEPDeHS zvbeZ=6MO7y)t#1G8@c?)p}v^WG9#UzDY5IAfs4IJTg?2+KWw#z`0Cy7uJgXhLQs!8 zWjycur`vw%CRqKJka}!3j)Uo4W!&O6BRHpOp_Qe*lM2=lI-Z#`Y1ZmCB?TE&%vMjX zVP4XspXcSCWmkmt20{GI(2~S$)6H1z4d|K!Qcai6Yy4>Uiq^)29$SkE`uy++gy}$y zz@IltoB2KGoW_D%0*gwgo7%fR4}fELv2ST>Mge&?!zO1Au7KvQhZ_x*C>P(}%sq+K zZaCncK3p_K8I@Y6iZGt;veaGk%DFxXDF963_}ymC)=KKNmsFn!MRdvH$zWU)q1PW6 zBPKR}Qt!H$!<J=kXy(b<l7?;XIH9Ji=br#%wjUN5G42Fz=LV3zrJg$nLtfUh;s?R^ zI4?(q%ZC?GH8Zul>U024AD0N;tq7i6w;b4nVvI!cLv3)?YA<i?sPd@7H*-jPokX0I z3)FRAQZ)F4?B-w@oRscnn)7nHyt0vrYO<#CXq&wZSry~4>Pe#9E7pU-U!vfCl4G7@ zWAd>>6Y}7w2g(x!J8b>)3?^~ex^H~l$_(PTZsmk4ci%%g{CS*LdlFA-l7ZOHz%r|` zCY8(a$n1tQ!&2!-r{3X3zSYr-6A{3#ViABq$<L`sO`FqX+n#VpO{C=*xx`{CaHjt3 z<cYmvtw~3dXzF=+*QN6ri&y1!@z!$C@$tb|G^hh97`)f*3H???F{uJ=wCFD@Fw2c- zu~m3I1WBO(R>9{Jx$3+A*&inVxTAm5vn+0}`b3s`R81v+N{jxf1?GY|&iPzQxZ|Gj zpfRgqz4sJb(jMI8eqVKYAItVHMdiI0E=@5zlhRXnf+pzo?8r#+x5fTGcbu<J{(f4N zE--JkExVn@FwuY5BqLOF2Qf>gO`%=C)h%_wC|5D$T6uX=U3dGd`-#(;)Hr74^E;(x za2xKeGnud)PJQH@r(BSCN8ZOa=oxOg|2ZBK6~`fI`z!H<XdFLDp9lQnh1}4nQUWVJ z1Kw||S91-O<`;SNzcJQTFoxug-`<_6$7zatNpbvSeV%kIt^$Wod<kstbT0Ixwygtz z4Og#T?MqCmWaQyw5m~;9IP#42QM+zylcT2QGlbY1E@)Mu?9%cw0(FczzrWWA)2+ym zZ;|ac$cf`;v3VHwZ*-~u!!|{whd(lG7i~V~aY@?NV5M{h7;W4ZLOf(*X3&^tSrh>a z&CWIZ4e%Q)g#Rx4u^(!vBeUfn&?yN1Jo3n}-m~gYa-xbEu1spy>-=ynKPLNy8q=o{ z((n+S8tS`W&W5e_WwybUHo|$P`tYlcPhL40sd*Sw!*%8uhfL7MPrsqZHsipF$r^r- zkw^cJrn8P}^8eeoB8r3}ARUvI4hiY*4(X5*kaRSRp(5SgAf1xZF}h(0(lLqAIdU+@ zv+r}x@Bf{1pPlV|?)T@qUf1;&N`0ovT`01S6BsI6UNAsAW>y$vuly%v&B6~w>06N5 zdB-<?dPel*-$KYcnS?%f#JO^a>Zys^otzSA?fb-m)jlf+O8MmjhX=K~!~E(QZNqKo zSUKCc`O1J=8pSu&-@o0dQxiI;fHr@|YI-k2BHwpSTe8N<oqv%tmiRpu7w)N<%B;6^ ztqtrHv|T4yxL9>%!7=&0e%aU6w;tN7;4-!vI4HkxIpn737h%hiNL|ILN7s2kN3lO8 zb$GuiyvuJ>z`UrDG3>QVSYmu^yQkN7<Hf5r(zx-FQL03IV9v8GOO1YI;Az6xsBTR= z7Utp=dM<U>AGXDu8pgHeX=kYK&pcKfdadu_iEKWBKAGCfIm^s?doKa#YN+3AUM>w1 zTSLT5k8wh7Zm#bLK2!t+pvAjiHs4$ym_Q;JM+it;*H(Ye)vQGweI=}92j&AQOBnG* z^_4T1J!)M{Z`Y>)r_;ZMLBsY;gx9HG#Z`1Qo62;KUsC*80%tQZkkeWxxu%=9Y!=4+ z4A}hCbaIEr-0p4)kWEEprg&r@Sb(i;c@cz!(a9gg-M|atz{tW4LA;O1`MkcdlL^~v zV#g?Dm2W?ywkPoOx`c2G7z$~IUKd$k`ukMKd?L;pN-Cn`wj^5HL)E+FmR*SL7heBs zH35Dn`t%iVXZF_T`&fDTvprQNy%Y`$VuP1dPIuym4_R>lI$}f$`<`ORaO2U={S@LC zANV{=S~(YKvuSmZ-s}QlCGMu`l6=no8bX&!NaMoMK;}jeoD+oJR`wqyA;D>X9gex$ z>Cixy#kHxQNv;ky(Y%u~#;vI_v%RpdKp4_%iA?bDb|Ey1t<J`3mQsmUCnk{_Bnv|O zF2i~8LnmtxO`71au<NS~7=eEU^KZYhYP+tJD)W~lbKJpNVH&kL=YgjKiWD8TbRL$a zqIn*fCw9#@+F-Zl)QPowG?T3`ELd5p9<3ftC}1Wa`FO*|TBJGLq*X&W!onySr;SKe zMJ@RExcYW1(atSXP&N;-aYk$L7`@ezy8)x6Q3@>TdTX-;9DX@~e>VrvqRSP(xk}DC zkW<%xEw7*`t1n+9vkO#W0cu@sUCY?r$*||@?t-vK*p|TY+qeVV<5wh?_nbCCf9%pR za?teagc{pBHR}$}=wk}T-rjGljzoK$1if!a_+^;Y_x8XX{DuYz&EcGI?jQ!2KV9|N z9n6U>`n~cc3PAETXwv7tKF04X^O>W@$x^dguv%|Gu9CxDWyM|dZ;1LOl-s#E==e9p zbqBY9!e7aZry?7IodluvixR)X_Q-XBj|^)B!P6|f>6~Q-nPoY}2%G7>&dvt?+QCvG z^jx&@Q^P|xV$98v8!0Q_B7;hAHP009=VADL<9E^EE}0!x^2DTnp3}_l^Ab1YmPS8g z#-pZiTU(_y24X{A+nOpC9zUd$E1AS}8qeOC-WE{2_sq36=@BDvPZFe|VXZ+K1qPov z;6@}--tUO6_1f2#po*OoafqbK9620}irY4o0PW6?IbmHXtM&xmWp%NbRanT|yG*L3 zV-U;G52fCrCyFwUqn;4g{giqLe7>Yk2j_sj$(8Dqb1U=opj7fRQ&#;xq;wVB|9V1# zrZuteAoY*iI}l{`1Zwlp{mzZxdRDv?oBxHs3JOyw@N+xo%9G2}=6dR*IT1U_PxGVO zsbigh{YR3nr@fT5Utq2-{M8T2PjWaH2qwH##9j9b>&HMiA=v7YUK2{Sr%^9%x579X z_}3fBj%ZekMZmvbt@3^vku_>PaO$gPV3c^$+j^yCl^8c(+Ez|fW20FP621C8a8JnA zded*q0}Z6^x^<Kq>lv|cGe<pvAAg<CJ2-q>UX=XW;dFltGr9M^Bwe)niO%}lgs<P) z*x^Fw#`*9FBX+RA$vfo{HzTwtTkRHl(DHT*GbEpA7`F@=o<-)I)n03PTH2110K(lI zO?Vycp9_<79UC=MCLDN~(<|i%;$Vs?Z*fQ&<}-6F`*!W{HKKUQ@3n^7Vq8`|tqiEW zUBc#5Cxulk9%-+K>hd<)0G8dtii%i=URv*gIPHF*2jX5od(_HM`0+A+o}Pt$>55V- zjv7lzGxvf%!Rq_*i%e+}oW#Yd7nL8^><{i$>=F^{3~s&W=Id+qaOW|Bt<H?oMReyg zBp!@#6}yW1HuT8%`|-<zmpitfX<QQ$YrBxnAj_p_Zva$ik^kM#?W2^B@|9OjCyd0c zyPq=PWP?8b0`3gtc|mXFxl<5z=#*{q-VcKJ7vupw!9E7whc<sCrh|jqdPeZc7sSU< zpe2wTXBcPhZDlS-$cnwpbq8^;P5Jj$*4}s59JZoR&o<wxL*u@>-+VgM-_|v`5(8~e zi1T*{a~_IzdpjF7+HhQC3V)z}Q0Wr&&PHg4k3NOP=JlBI4TH;G8MIzUEur+4-J*jM zQBPuO4D;(TcWT8ge~;v&yH-E+MXbbnKAz7qcqZ(bcW`ON?2pMyc=AMHsg~?SzC@#& zTDngJ2%$LCU5(q|oEJfD_ADVP>7fsP{A2H>YEWKaGxZWQ{mngE6OJ!Lm$gJ*qtS!` zZf4Per?-e}tJ#lEA-#5%K`-ygCa0HvNlN)+lhTP@HYP7uKY>U;gv?m=)#5e*1Fc3K zZZ>vK7C~cgba2mkY$O%8*d*2*h8)CgXS%+p<fT~{hT?sBu*Ni)AH6Fb%ex}4x(%Ya z){fxdHY8BmnBF>K1@slHMKvc9Ug4B0@2hHs=`;CQLAnKI8<F{SU_tE>fu73^38e33 zpA%pSO>;@Uf;Dg;)q#Fz8VykHj);l=k-lrT^odpsq8wK1KCwUtwHu~wXa&zD>qg(Z zn6t5@`??guhGk&BxSZo8$)I6DYwr!oLhBBd^e+&pBHRUV5N=A#lnVn<i#9I)b;|h0 zQ}RKSAiQEK+0whqin!I&jyaQ#axmWkd(4kNe$dG^Hs*Thl1fb(KHs<f;@i->eM&nT zqkEE>Bp}n>MY>P;H6Z3zxnC&c-b1Y*i7!wvrgRa_&$hmM){~uA%Xx7r6oe)jy^PpL zX64zxfZW<s@tyAkl+-7ZxxM8O8HOGLe!)2gvlQ!&C&S8NskuBe$PSq+yj66w5IEix z$Pi|{6L;cs3uK_tQvad9P5j|5;=qI9nQljUhrBI|Mn)L8>~A64b=iPvj#Qh978L&i zX>t3nE00ww2<aDTrs(tUp7j-G8!)~gIH802Ga3<O7{NMWW8sl55WDyJCu<cd`mAH@ z(T1Qx^&PDOpEqU}ygD+_i<qF`bkv?1v0j1MWzKHgAsws_qAI-`>4M1*B#(`_JFK=t zQ+S;=srr=OAwQ=gol^&-OdEteou=gXGR}o+f*lVGjS{=(2*9*>@R5Ubs7I1guT~J? zQ>su0i`dN9c~<=QJY<1p=Sf=8L8UfsEn_lB0z%!a80ydJCV6E*sgCKQVjIe4)F~~- ztFH(`zSkvk^d94k=cQX+@4Uy<`0V75HE3NO@juskPdNbq5CRCP`jQ3e`%dnp2&M1J z-6&Mw*y7TAXpuXBju$A5)`DI$^$&`4U7a=9{~Kr?>OJ$Ye}Vrf1CDcV9vv4I5po^y z;u`}JAtvdzc}&Y|`={Mmmpzf*MCyj3V{6JgVeapjTWqy@Y$ApQD`rDzS%)$T$dD3a zB2I2_vSyWGfjKh&)5EW)0I7S61>;6lj;fKG^4#KY-L7t50f3YvFH$5&5aDDxIR}!D zp?|Af?r68cZDgNZjqGlUw$BdB;{W~~R3P~jJ^C^R^WM>46}1fYVa=O=mcc1bLv|TR zs`~n^gJ~BV2YFw?uRK0xCVwfj*eYrvx($zkg_0va4`R^WT}|e)(!@W7NYm|2Kzk(~ z!Dn=~%UVH}nq(*5e<LO4fs;&Zz*PH<jSSAQ!RDiaqTxnlyF}NhT}B3Pr=I28AUU>W zpU?cC-q48oq%O;^kC>E!25@!LSt(qxna*)4Z!+QRZ%JC^iOFkdFlC4)e|@TdDQ;1< z`Q|d0M+(`wavNdK5jGn}N{943yx2Wd0uwLGVE;hI=X{T;@%Jz`S_mk!0YnLdFae#@ zjo)YS*$JOsMPm7(SBq8q+E;O8J(JHVA_Xc-Hp5g#)D1R=hV661N@n5Q>!;=>8os34 zR}>DFUuXUH-`{Kv1!nWttH^KVwO7q+m+kWI_&I3%+#HOnNYy7fqevc(y-}WOTfi*H z2V`!`og~G4Q<RH&Z{6wH-RGq%`V$P`&nSiN*7x5W6i&Fv5EinC82->?>I6BH@UeXj z5(AUTD-Nfe#`E6(i>J#3wmkKV%mdhdKvim($V6e3H=sgaxUeBt!eqXs-!+%f?UAtL zIS$kFBP!uO#H!wm?qhRX2<mUcw0$ll`T2+2F6{F7^##fC35SEL&4IBIz5HDOfgMv6 zl7o?X??5aQMog*l`?+`I(48Y#;lSa{|5v|Fo(_{Fp`I)Gh$$$riP0lM{-tW#Y*B1> zVvs1t&^)G?S;z#e@=v2In+V|pVSH^Ftbo9LmMX@M+x1z(nn2(CzS%=S9bqKKSS@hZ z;uG)HUK<_#k|7k1$z&{d*GKN8G;%_5-V1+oy&96=RN_FS-sG$t5+)>)1(A-J%C96Q zG#_q!KqxWuweOe?kVFvdtP5C{aOAiRUtRkllARyo*!tcWPi%ZX%u5PVTxU;g@jT+4 zCbm%xGm0C4=q-f%APntE++dpDVU}AGj5i~T1LztZ2y-s?;fiwG;sal@O}#_V_m7W! zW1@K_Ag4jBB2R%`{Yg*kc6|7W(_rYrStN7wG3i~6G}PW$G~^uqadOPApBsJRdZ#3S z+4tp3gx1isKETc-oDpQ_B+z{U=S=EmV&wY+L;B`+FdxT7Y;jdyh$Ba%=ARq6Zk>!k zA#0zCQQ`{R#hZ*LEE(9UO%DGG_i8jIL4sKmwbhP15<kee$ou>DtKtBEs~Ry{^K{7R zpQf50jp4?UPL=~(Lb}^}#xwm*3}#yqQ6Z#H2Bpoa%~Vs)W(jw?GtI>Wu!3bq<9BLS z?FXfR_I4D1>N^w13b%giV`vcR_g?61OXL?F!45yu|2#{Z)(6z}+uwP&qGsxChr1*u zLPL`z<U`4U8#afejNT{&qi2@jfbZmG2wqR3q2l{gA~$KQ*&(s!^iZ<FTx?om<cZbi zC~DgFtOQ);(}dQPb^LFm$}n2gj1ry3aV2hGE@-f>s+1?&UX`r}g<xiS%N8vd5Xeg- z`9-$ctf0NHZ=^|?J1J!EWLuC#RJ?>m7_<Y6MGYhua+`M@$|WM8^GrF8QRG}J*Js<O zTMyZ*E*lNE9d~4)`x)@J>=L+Mb^j%A>D{9t=;?S1z5DK8mC1UG3l*&}mu(owsu|VV z{?r)X39I7ePVy4y`~xeHwiYCXzWa$%CFgp49`F*VPv;LDe-oM|bd6FNBW<Ad`t`sh zP;(aUlIwdT88AZ?<&8U4sH5kwFP+*uuEdo~=;ZA(a}d>lI=eIIgbSrFbY*P{J3MSt z-0TfoK@gp5x6EY*XwBt|tgE9RRws~yHp^^;wNDvn>{pXt%~~DlAn1ZlI5umu8gC?; z4d`NFpJ8!W>R2an_Vg*ke6R88A|b}v#kH(jePp6y2K*CM5Vejms?>(;56&1#fC@@| z8X=LYTiLiO<!q_<W)sUNKZt&bE{qy80Y{V#P%tsc63s2*5p9qpyL|OKa;V%aI42tU z9cDq{qBwjt%()S`4PX!nVf5wNm%wI+>CV-?Sbw3`41RVmmHi|>_MFreY?CCVRlu%S zM)9-#52}?UId}dtC!*H%fjfvlNtt0Y_o4e2oc0d&<blRYwWc1xUa>L{At@>;xr_f@ zwXbm!szH+y5&+G`;<!4DC;p2X7QDS1P>`3~vmOvBRt~ij5FIMovb{Olf`Ab^EI<v) zqZ=^lI;kmZTz#09_6f$wcvklZh_(Ko0-6<-QhR^(K5x<ERIB(lg-4VOlL?s-lFGhI zIhvkMqbVjSAiJa>@JUO({<Bc+M6iqXkS$io=0Rkv+7W46PViM0*YD?#{BUj)x+mE! z?k~|I0dqQNqdeFV-_#YYR<_uakaH7`PN^x#I}QjTlKsh}<<7%ZsM&kBy^;jHy3a#o zyL@h$fb#Kba5$8(=;0KRR%J<g2a|^HD3uW3TJlN0lOXA3=<RMvtWVF?Bs;nG84Y`x z(*mMQB#Vg>6!>)vFe99SHN24&6-{LO0*{PDFn%eocB`5*MBOSy3#Sb9`_++=ZQc_` z$k&IJ>zC7pI-DW;nEg8DSZ}V~x@Zkf&(h^Sn>@3%Es^^ys@pz&ugt-ZjI!l9ljK=T zbKV{qYR>Vy?5hNbBe^-2!>qW}3>ustG+_`W{`c2D40{1*B3hDv{^-0SA$m%*`{&2D z+xE2P0?s)s=<oCUxw}&NbpD}#{{}5Nh`nF6y$9cY5ciAn3<I4L9-|^y-Ha(Co>AxJ zCQL^6qTtnmk4G(=!u4Y2leJs-Qk8FkeqBRJ9iS1be9?!(lTeZ`x!A0#47In8lZFZi zV|VxtR7cJjssZOd%T@)0i`kT((Lt3{urkKnP(aGK%~<n?P5;2cJk#?Xo&4nX6cm<3 z-lfLQ0WSOa8@H#159(OCsc}+%94#mkJ>7rux(sG5+2dDv>c!j)P7#I)9dK^CgFGI; zF?0VQL|U38BLPa;frWA+37V1^S2|qmnY_8m^xt*;i{ux-=@35S6o<7j0mKJ1_w8v) z2$$BSi?X?ExEbJRVM7VUJEF6+^@ly$mY)Mb(bYUY#J3hV`W*VVwsd;Rr}qS7HfXK? z5(LQLnN)2uDe%PQK<&1$I&O??q$6LoDtT7ik2MG4+N5#|aB}veD%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 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 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 265/395] 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 266/395] 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 267/395] 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 268/395] 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 269/395] 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 270/395] 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 271/395] 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 272/395] 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 273/395] 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 274/395] 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 275/395] 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 276/395] [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;;| z7D7*1pN^t?ol{jvURX)@T(c9u3JBuMj)~|#T}F2b1yJt!wyA6@pO=w8_DDp)aC?B( zDLOZx2JTD#e9ODXPTIvcC7lRte@S;k)Y{*Eq09iftDPi9yB66?PHuQY!N36lDip&> z?0-{UN!flbZNIe@)wk3dGjc|SQ9B#$=Pz;Ib$IsSbthJIRXXyLl9LRrUP(xHHl;Hr zmvYdZIAE`WS09CbeU^*a0MFVJZ}+kak(BBbn5xpgeK2e^2{Po=7uD@zpiCP52#iI9 zKup-oc+fHh`8X%gNLO!t;c{VUKa5z2+^k>CJRICqQ^u_r2oZ>faGQ#HRtV7XPrFM- z=avwUVxl8ZtIN8g1>{@dlPt%lJzMd2mvo~|Bj#7&-Ez&y+qa5IXIB?#m-9PfW)sR9 znhNuTp@#bn7uO1>juqJc7NS|XPHxj5^3GFv?V-^k8Te^EQ&dv;a-uWBxQf}DNvcV| zWWZtXF-jxw+7>py4R#&)6<O2%icN1_=-yX<|LmG?3O+6mVzJ$6#)LCg2JeP?mNA|! zJVxHiOB3~S>}0F~%a?lnQbYvx+3TrwM|HFr)jobCn&y+)p?3^!Q?a}Bd?ZbocjfFV zj_dMUa$Ndq`OTlJeHNtGa>>2BRYKQCPGSkrn*ME&I8m`N2NA4~6<$~<pd8ghwO9h8 zNo8^-df-j^Q_`MNpQ<mV?)q}=ETj8(QC0N}`sK1#Xtn>q<x|ubP;r^?^+mJmu%u>l zD?^fKV((Bd##y&<M?Ncds)<&gisp?ZiilQ!nbYv*`eU~omJ#(?teic{j1{>^bj8(p z5c4huR*&=^n0lfwb?ei^jJ?RHL-EbcJ2Hr0Ki%;n?w<7H@dBz=na|~52e3#66YAY+ zX6k$LiEVMG&bQTtxArkBsAUC7&33u+<$hU1zVjYxk|=}K-;@!blU$Ro0AJC<Wi45) z7E=rIacff)I(%reaVCyBwBWEUfU>nWRGxn!B6#?khzX%^_TfF7`tSgUz(w8^iQivS zAm|K*4(p@V7ZQVdAszYNN2oT5w1}ArY>_dkQIBofTJtJvC9umTG+Ns_leUNn!=DOh zOW*R8HWPJ5rtB;tc0`RI(w+&=3QDR*<pxV0^2$1t*xcy+w0U>nDU}9Q`EIM!!ZkO4 z)&ZN69H6cF0p_pBGW%==wadYMiv5yQt*p@DaEe@Ar(%?(qwsOW@W3IM^ig1&nsj*O zgfNWNN=9hgq*~~YT-`JPHz9v{g6%?8GkRZ|g^DJoG5k$et7+?~$XyUqg#YV9B%2RH zV$X73*`nvuc80Dt-@MlpdE7HMQOxJYiCoI&r?-_NLkc_>FQbkF3(2#BS6w0j6m5If z11%`m8R&S%*!bcy14crr!Y3&}8${TOj1h0fZ8PpnuDK*mUlw1j0AI_-ZZN)KP7e%H zI^O$L{DV+{nGodKW|@rwa+@P$$G*PTAn6PNt<W*9l<B6n(}vze9~VLGQL82A(Bbof z$<Vo2(VdRfO`!|Rv^GXbgNVxTNjI}XK$YM;Ep(&S57*JOwpP+_m3(f9Bt=;ITKqEk zvyIU@o4vMxl>Y3v{l=ol;KiV&PoB~`1;HG{7~uFb#-t&zocJdzwM!q5=FN{>KLFF4 zc|obf*smBk2wu%>KpP&syH!Hr!yV(m_{%tCTtV6rz}!f7iOwhKdLxh0sf1|ligrSE zBZ3jsb=|vNMYzk7n{37PH7d%}&@}qZMJZ$}CflridD(o5AuD1vyFPKudsIkuoo0=V zt6O_F?LAq{*IJydFkM}=bj;`ThS=;jet7<|`_FokGkO&I!Yd3i)K)wk=f1wbu46Sj z{G{Bj{PKIWVJ+Wik5w^%5RjF_uY!7{wGWtHAZ}>3QRd~5wR_U+>Yl)ex!sO^d+rie zO{vxr7B2H)tBl-Iy)|F|#iLUL1yuO>D(&2`!|p)hhhrb1O;vo6hHfG^sP4qc(Q?`5 zOKbeu7<AgbH(prTzL&g66M{$WwI-VKMiT;*Rn8u(+fqqS;fW|4*w=JgU_UZDQicui zb`H+U*Bq*&M~f+26V16j+Z;*7U%R_5(85lKnh^LktOuGN=8hNKMy{f#GPkN#(LdI^ z9?@8z=|FD0<E1=PjUEW)etxdrk<@pf*db(mvMH|u`GKXl`gqdlAv4nFGt3eIi0V$O z$E&!XA23G0`sj92d244Mu9;Gokk_{^o#fUAhOxGCZtSt~iDANIMQq|~sz=|M5|f7I z3#?C^dq_f8vsC;nW${x2S8S8(0m2l$EudD@6TO;oj_2^}sBGlJP_2mx(Oe_lh|)4% z$xUh^Nw1^5?zDmSc)FtIFO0xh$Aa$K>e1`daqah0bHYEDYoZvjQx>knzb-C?cXn*& z*x0((f1WC{;-e||?j((PE*Qw;R;>m&`Z4P0k2Q+$BIA%Tj}+-ySDol`M4Yr|eU4fc z9ui;4Pj0~KyC@oKdrZ`nEt(hRJ6AZ>o+AM>LU?Lyn#zk_3OO(YoBr(ITK7scXU%f; zT?3r$t?20+a6<1&ZVrS`vx~#=*Cx;TZkJ$SUDw=*Lso%Uq@cUX%_f*2&~gts5JE*d z%E!P>2-_s~KNVK5DPi~xjl8C4CyYx`#hS8f{WJW^a#Nssln?>W>|mHr)U81Pt5bn9 zpU^zud~sLb=3V%3m5eV(Z2HX+!}BF8mHweK1<=LkOM8I8b1Q5*6fdQ+J?qMwZP^Zu z+UZ17`?Bnif#+l~>BlKlzxvwc^MXbqhU^b!IkGAkM%8pA2J72dMLqarTro^xqrgeC zN5o)jr;o{4s&jcUda-comMrQwQXH~IT{V4U_!)t30Op0jN&S|d<?0={T6dL_c83Me z!KPkJam~CHcamz~i70K88jhu{$*|5FK~v1JlHRwrBdQPe1DFNP|126q7Lo(bmVr{< z890~siyRi%1Qe2>iE{RuCWO3*6A`R&<3~VFh*D0$OStcwUJl)@axu79ku0$>$Nup_ zl)U|3!a+_6rOk$z=i}SDtI(6e?MmHy3?o^><;>DP_t@w&$`pfS_!Fc0fu4nt%@S@N zuk0lcHc6=5q)fAy*412!fsapAX}{QL?M%EA;t7H6!P>Pv$qsDSW$Yz0TUHM<aXfax zl(6fvDQn)}#(lPy!z?RoI_Sk}olt;hxyRd8OLNwiqt_s0K9AcCY!7rUYJVmUl+bOK zag-!Ly(nz#DCvZS)0+KiLt1IKyrU?CEps{XS)uF~qj09ulx^CCs`l@aeP{M$X)5E5 z%3}1qGDr+@Sw>>!{(@P4gu`l!{;fQQjteB3@vxxFB6RodWZs7eMvCt8pallG?q-r) z$b5JYy;70UwR}w5s@iwh;n8!JX{%4F3Zar2yn4f}IbG-y&`wX=rm(2YYlINR&RXpD z?B+1D9M;G++s7XRi!L+ss6G-JaC((jkIY(yT;5znCe$rh#sI5WTi>co-=Z5a8OP^N zP!9TF5lMAA4gfG>CA}IB=A5!E;Du5}&cdV7P7%{?Aqf#*9_UWFdsaXciL|ALZhz;Q z_Hr^&)wW)G%pvE6x0<1p*w|N%^C`FweG2fP{{C~7oh#b1Kihcj(XNWtdI6tQKVjjz z`1@+ljhlP(YAfXL+31!ae`(1fF|Rol49*2r@rFsY=v=Mh)t==~8FidXtjD>X=w*s^ zSN^ofspxQ2O>aSa<gY_UL}bq$FMYqN2)*@@?NmNFqrxt+S#xV8GyD=vk6thD7sJyA zmL$*JHD`!=@UqRqyxXWcKXWcAoK-r3ACPfuqIAR+_Zm5ee%$Z<MYbaeXC?=o!`J6Y zyX3gm4Et<?p9;+;d!*bGWO(BZ>Ouv8waYBUwH|f0>N7|EDO!b)ik`da@11rVJA8BT zJ+@f#aXxv|h+$^&?Yh7g^I92SPuJgavNhDBN0RoToA(^nW4sKX+z1@fy@_vtDi30Q zc0cQflitK{yYXNuFvIA~`_E-5sQbeeJx@-)lV4vi7=Vu<fTUlKU+;)IYN)rE&aSHv zu`H1LNP1~gsYSZ5n`~827w&tN&dp0J&b-Ux0#^m;mAzlbZyJ&upQMD`!PPuM;#lnh zIknd~PsbfbZftETXwBgU7f*zJ(c@>;@kr`RUn{c>55PYA_$rBo@@at2K<R}fNo_1_ zlKKg#Qi70-XZrkDu0FCIvj<zWfbC%H<j|VjS{y;ZElL0CXl#;X34Lr<tIz42fsVjg z8h4l@rE579bte!oEYwNB3ME}k9}6wpxM|ByX@Ys;u1+Yh>q>qjej@!900k({@3=E* zT}He!Syx5st#y#qnfOlm@Uh!Fm0yk8(7ZZB6ZiVcnpBq50F9x$WDr3Hx;v=ab)#}r zX%j;K*~yfcwFbqM^KKN5sh|+sQURvC)|rC-U9gN!3op8I7DY^I-D<S_*lqe_|2u6p zF9fipDU|sBq{>j}>vi<YzTBSm06Kp=rL6dAm#QQVGP?iPGIa-pbTAPjoT~*5Y;F@u zx?p-<_u5b5^6{Cw73~N6U)JchNJ_7bzKID$M7hRy<m(KvM{TaV0i9!i7k?iQ**&^| z8eJeM^t}u(l3mPH{$Q1=VlJWLK?&^?f@`7TedIlgPRY?sMkANREq33gn_n9)GbbM) z870orS#_N~T&uwwJ4X{F%WZ*8(m`{tx2kt}tf{#ut6f9YuP-rZquhCPAMlx|ub2@; zlxRv%g`RM^*`vi*n?zNccH^ep%jYTOb&2|_Zf3LOGm!SZjZ5h)!zYzDy>FB}N$&i{ z=GMY+Nz>jynGFgPC{MhJtfWNMv-8v?jgloB^{Qii{TJAg0)i20A9i0|Sw-h|CFq<w zh-x&NJ(t^U<2SW7U<sr&9N*hqZ<TLoH+UD#kk+vr?LE&Pu$_4d^pm&wEktZ}Ez%;t zA#{4zSk)}+)6@s7ytPtXQC0}L)n_V>b4ndHIlw>)cO1)!ZVjAz>1tz%Ljy{|SDMX9 zVX3F=LJ7V4*gE~&9su(RteRkYPf?8?IGvisY0G5QMYfnzV0W|2?b(;sI;3uqLv~j< z=<(+?<m4kh<Ii>7^qc8t6SK{q7Dr#Xc!f~f=UX%=RgWNa%<hTSjb6P&V(8JdeNI;` z10>41{}Jn<M9zaW5xv<?MX}!9{rX>K;;_zH4;!4Z`c)imI}JPSb$tu_WCh=1vhXd0 zsdcY_CL92<?a|DT2l(0I{i0@D`yD0(_yptxKVqW6yNeB{a#M6zc=PQx>u{&NLq`4~ z4|OLOmuTDNYJi1<U$<|&+@L@8HEb)*Id!@{?sC4mOQ+OCyp*G?d`Uw*yZ6kd?zO&i zRgBnQ<VdhY;-LTFgxP#00MhE}IECI*MY!_yGk#?!`cr<XvwEoM?(z^?h|DXQ=-oYr z!R-lLYz%4zjwTnzvi!7sPRkfvpagY{s!LDJnqw7UMe>?s+nZ;H4RoEu`^uJR#YR!- zY@*z)g6(}y`>b(VM$R!EZ1!Y<^p>^|s@n;@(UJB|D)`<vqxX`H0b!)0BMY|#9rg2O z77Alt4Sy5QYA5lCr;=Q}*r#hjoEs0!Hh8bLE}Zjqj9Aamww6u&GW5>ZIr?$`q<)O8 ztxa^EkRsZhzr9Oe=RDp}b5~)*`k1JC{y9`s)$-hO9;cXEcg+b{5jRpq*CuJ03l4*w zbK|uZ`N-xX2lg+8ccVG^p4i&Dt)fmEZ8_YCILXQ<m^RnnLWZJ}*gc~74D&kT%aO8- zi9A={VjdfxnRB4-f>um_5?*37Io)f|Fv@;)jcXo4-sCo)*w^LXcS;pT$8P8!Qbv8s zH5|)m7oV`p*c>~2qw-!*yh;}R(gnc`x(L+^fiH*oSF8iZ2}a_2=pYMA>Uj*a-<xfS zjv4?|q{v1pK(dnn6ux;>jRsUq*W2$?VSY(U%M@o~G>&71t^Jk#e7A|ce$h`Sb`CER zLM4?`-SbMCNQwS$!kZFF_<NbQ=%#H<@^xLc!)DkKv#gq=zWB6!xO1=_27-9#2nZ_Z z;iCt3^YztkL^A_%C;4n!{_nm-DaXT&2OR(z{1j`4xF#0a^Mpd$-Wlp^EdjAfjtkEE zkQ`2d?GlF}oU$UhRGLc>Jy%@ev~}!qg^V=SJ^e<%1MA~CTWftL*`0e~v{p$izu9L4 zOI})K-You{k}=S3+T+{>ZvbghvX@WEOHYiNW9%*SJLRM1Ub|%u10{RK>z+gb*o~h6 zRhEk>=^-}rB3Hjy7!6#c;>o`#!LB8A<Psfb(%~+jK9`Rk@h&4@bmI(#szW22IoG^c zzv#e{6Y3)YMhknKD2al(gpbopL!-=7(yQq8qvi>YsLDLULDiOWU-@bC^@(j|GGkR^ zcTNuY2^|FpHfFYj$nX}tOOL!%^l@k3c{<m7(D>sJi8j=RYR}T8Y=^V5gBN??>TmLh zcYa@)$ZJA0a?eK5k~ld^DF#pMO{&FhF#eQCYv0GaAS6lOEZZ-wTxS&%0{JcdS#I*d z)ufJTabL&4wwwBn2J7r@%B*|OivV)DJ`Px1U3A(d8+|-G>0GoRfo@<<ZVr!MhKlbc zkUy!`9n-|M#!ohK5}Gh^z=0wMh9lj}XT6Ae?t^1eRQ0CqKH}_Jpau89v1-5JGk9fz zMM*Cwj+YZIetLg}e06w6-%nLl%pHB9idPr<-Ueb3M$L>;^gwW{7G~POA3q+O5C}-h z298C`l8!pVbK}<CRmb$1jXQKm^&DAI$-X$5(UozQW03tWdJdomE2%}-taGaUbbpQJ zN*LDXkX5%<PPFkYFmgF4K7y({Mnr5s5jR^E5;1-2`aoz!0>V}ls-;XJsD>JRBwcN} zg%CM0iT26W^a*Q5pw8f$e0*8tY@PFl(ep!yJiLV{vt-0v_05%rTJ@)`%&fCcDVS;J zjNQ8Xx4U?J)>;%wa^@A1((B!tGi}#fA9`~tM5nG8v}NfV4Y5Yv2Q}F$OZPR>BNjby za+%sLo);p*<_F98%W>FA9ao&=VEqRbv@Rq&{3JDa?%a}W`qD6Ak{YQ-Nb#8B04n_1 z^2Fc-U>%0|cbU0du@tPNn<;fhz8Bpu`8tU?FmMcJQ@}Jjh|~$`aj_);ib%~DN`<xM zByE_qem)fP=CZULl++M#8vvDSuZOwpZE~iFw)N(?7cr5v7Iu;>_1=p_m`FhF^88xR zn&|#~SEIv)RAMv2`AUDkNTgUZ#?iHs{#=B5BxF%hw%G8H^ZX}btw=Ydy?2(o{~P>e z%d6C^H;XElZxtFn#=ZY}Q<sE#%~`>kClvpnd9-X$<-Q9lrC+`ZQ<OT|tZ_ASMEWMT zG9hb%&eNDx3#+N;Q^k_pA`2>t{la_gaW0h;JIh$0m%qE%6jq<mgL3CKdAU*%!0F4m z>IM4B@11^a=?R-9k4Se&?n%zw?i!q@dFg}I6fvJuPF|p2vrU22?b32^w<9d`i9ZcI zyIA=2@ut;0>500W{ZN|Jl_U=UVGxs6FAZ548eCr45s#Fzja-ZK9#~`YNrcL-t3mAh zo9^|8U_2;729%+7f8}U6z7#3#_}m;&8-x%P7*OFtJ~T4;3DNWpKA97V^5^*EMo&A^ zz6P{DnCR=j7$=8e$UmI@9qHmxRLWBf^Y`&x+~sL=_TV-5Hsv?&HN<@$N^8C84fh;T z59p0iPIEqGM_J#bcamRre@~#heqtEYTy_zqMS=N@Y5;)GS%JwmTK(caz_)JRTr8Ap zeuxc}p{nV{3v2kB>{HA76YtIZf%kwyjEBjI$kO5EpJjA*A6HOp&u%i~30cZT&JfM+ zEAe8AW@G@9={E)5M5DF1cvierO44L=j1hOH)a<H?gWxapBNIR!K2=x)ILb&des}RF zFQVB%gJ^~Ga)Ojfd($M%Vh_?Wp~|&hvirV9Zui*RG%8NoBpIt#b*OgIaMn8}2LOeU zHL@$2N*@67CXg;Zl3<rD3xRcDW$(J#O?t6v7l1w<e%>C>nU|$!j}RSxFI%>eEu0VT zp|2|qU#CZ+aw(plcfkd3%Ro?#m>yqQy!vb?Ua;~BZbG(%Zix8!Y!S<8TZZnLRFs+Z z@WdI`*=rT0_h$I(xEPs+(|Ai$6ijWBh9)nxCM9`K49x$Wqi@QmPhWlf7vO?q#Ue=v zYF7ehsaZa<W?gI45Q;)gAH3T4&dKoBhS(forvUEVpkbtNvE#jp!>aXe@IGg{zwN2$ zebEfAM7Pqp0o0Zxgs8j4&nG%+%I2z07WD_Wzs~J8^6Oo}xE2iWvOF*Sx4i%W%VQ=D zC22cHUReE{p)+;pMkNtXdmCdZei_r-qxKs%4d|}yq*1Z_C3?~MTz6;;&&gpfBGar) zyl~OBP{hgqHiAwZZQaJjyQ;PW?j_<?oGaTt4q;Qsp3UgpQx)K!<ogxS?(hDB>??hO z)DAdZHFqSpTP834m77zuQ|*<l59xkQ7?r2D5p3Irt;Kg;?k_|<obN&~7O{v}={-<w zBneIZ2}R@KJiD~`+$iEp>K}^RV$+i?*h0^l7p2YKz*_skEtJp-tzgk}UOMqzQW2GE z#cv@tK#7aLX*7TR&QAf96N)E-Sd4Ss+v_uPTznmL52B@Geq9>$@mhVu?VFkxwJ$6^ z@06<IGD$M3ze`wWEKG51%bXRwQ7RnQy$sTLYEVl%Ldx;rJxA9Z{S}H1jP~GYbwjK9 zS+0>$oe9e#hF>a`GjnijrHn0xy##m_cj$``9dB4b=awFuRYkBJHc9;w`EkUeJ{-FK zg`=KdkPnIYY;=|v>32j^u4cgj!pI!-u{J=x{Yf<eP)dG-J=a@rPV25sY4f3-J%W~h z%SGxqX+<M(Hw$eRL$(Y>KMrG8R!(7D4RNUOIm(h~ViLOdm#P3_3Rju$(dLGIGto<( zq-6gJA6kjh<0nsI(ko>kFj?+$vQpPZ{iGAFHERiK00~*PhlQ=RrFGNt-$U-nqsoMy z$h}-}n7S$#r+#?Y{^Cp(&BnHGEo4=Z&!jgjsAU%Ahzx`uCz{?je^ek4IMHEglpW<+ z#a-ccZz|0>ky5+VBxkH5YU$^Q42tNB$9Kz5Gw*D{mwmajV#p}0ZnlV55jaK6whELr z2)m*;Q_?U{VKL>60~}3yx#G-~*PEqxhURO--uke`l^sK=3`5FS$8n?xP*QN(K-ttG zN!Y5*9h=rnOge9%LrU~T5d(~~))FN$+oGGceIToFByh{eWvW?C&VWu^PCvd1Sbh$^ zh%+KjC~rUaqZN7GyXiiOdtt|q&ekkoBudAnQc{pdk`3ltGy}$3fXZ=$jRL=X>l%>y zP0|YD4AnEmx)OUThS!;)($Yit#`MRBs(v-T`f7)i{eTH!7pkZU*i5m!vyh_cP?RjG zLWo+(1bR)hA&crH>r>`ngCk-Pn18}mW5GjilGzhdI$DiZM~ObR?)ps=Gz%dml5^s$ zp!gSH-q49eQ(M7OpzOoDTZ$mHrygtPH5wS?ezT+r0Wh7<*FUsELIv<!fW7F%+OOYu ze$-YZPiGhHlY4N1kQ(Knb2O4DaKSyj&fZ@I_SnG*n_l6j^$gg25WH-#yU?5xQW(i7 z?^C48E-kGSdKBP-*=|n6uOTb><wyHU7TRa6fYuFRn9TZ!t_XeR1eBg%V*gf^M`(QU z`AmcT1C`-!rQb=winR0f;86>SNy&E*pPhxFl#oo~4tTB^SskX5^1-P{GhbX`ZsI3{ z|K<33&9dKhB%So5KAK*r9C8j#kWR?H)6V-;I<-_^b2q>4qrc9hP~^*q)%Q$9sD0xT z11gOd4bz){*^J#26ICESRhaF&5Zb?zl5YgnswO`-gw0^&ZbS^+TU3C%*KrIr^s_mo zp54)Dmn+l-KlqCGJrWu4K0XlBERNlWnYOIpt>gtwsps#c?hNU5(@5SFvMXn)|MH2r zbn?5DT7JT(sV@Eepvt2sRAD8vAr0N=+1)w4Xr&^_=5{76>Y4rBr=<`DX`R>(7q)#B zhebln_QiyEYlbk)itW?^4w~_egQ}-%rnqbaI4B0c!xn=d`X+m0E>P~5Zz;=~aPGRE z;%}foTCRzlSSy>y9N6v{omcjH&dy==RcFRz(^n^3n@C98!y`sWsLyF)t&`tCQDt#K zb3TAhM(HWOMQn-3WSGOubveg3!0Cc$2jqo%O}9m!cY}Cge=lCLW_(VAbrA}Sa|m62 z=RLGnE~CqNpgVir=P7?uvU&7sI{Z`v%<(z7L4jmALja_DR-Hs^hs^_x;$<=2GHE`K z-oQ@lcCq%4YpiO3*-RI8*7sj4ua+`tyFYsO!NS=@L*7vFk*6^Z(HCZU>*|cEuxNo= z@py?WKovRe&+-KJp;%`kN$35~`g>Q9({xsoA={LkB=_bYovJ3!9TR+^__I_;re3g* zzs}c)X*}H5aToPe5LaF^GDM^Ai;kKXl1Pzy?pmMxx*Ikj7b?>XJK_&a-wzo7j0X4Y zTAM^2reJdV&vcf?B>AYcin5oWkZPm=k>XZUaGZQ(`1->Nzw=9%-5bB@NvS6l-fU&9 zXhW5nUL+G=THUC8=s4ISrlZ{G*(~I&Rk5rp*O8P?rk4iPm`C*@#}~W{1Cu4MDqa#( zxkW)VW9|ZmoL{o>;K!ZcRG}H5lpE8LUArPr?eQADmHW-@59^43b;gz#Z6T(K3W(?A zg!$PIPJXVdqm?VlyC;<VUZdRf^(HH4*W}OiEk(nmeY(tLrkK0;$3tIbbzV|*?~wiR z;pq+YVWULWy3)01;%YCw9mfu-%dxm>jE?>0iOAy)>uh()b9E@*+9$S<67@;e#EBn1 zRtfK7KUnBO6!UZK54nGgw~LUxe2}2rmIa^r?a0c_J`7%?Pkz8CX*ZB@Ar;CHf~76` zF{7LwQ(S4zrw{z@giDd6mgOlaw3G)q)qXv!2)sz#`R>p*F$I8LZv5sjeD@-D9Hszc zV$(U$<=3M5M>-4wE3+pv4T(aPL%@Clvx;hF6~Y1VO7!GRi&A${z09k}?>S;#5zPPm zurYD5v3H|{K8%o1fZbEETPFYNJHCDE$Fn21E#xf$<mc&7GP3Aa*w_E^jN@Se;^F>e zeWrcUujmgZTl0Xj`|#V+IU4TftBuOg+wu`#9+&mN9P_?;7;l4^c7I-c?4Lo{mUd4X zFzd$i?o9mfYgJVQVph9xUBHRZPQLnK<LU5x%e4J@p>+${Q(p^<U10eo?-Li;-L|&U zE@2lnhJm``BXVIQv6SBX>b2~%5r7)ltvi`@&KEDs0GtSGpe+sK@DZI&`~Dcr*4(QK zee?Eqfj;MrQwu!~iURrKUySj$`&Si@1>`?9xoCDLqqrP6qO)KRf4SKkIAiqW*kWyq zX{>$v^xbndmT)J3vkX<>?1YobIbm+VSJr+I|MP)8*eqCiSlXBq4*Z^9ozDKj7l}Q? zy#gc=T)V--drhDPoF;0J95i;@BLB9MMXxB`I*TP?YjDOlbC=_9HV+Q(GYdljUF^Jp z;_xX~U{g-F45Em&KiM4q=R7fn0~@ZAlN<oT*Hg8&-}Xm$_uq5sS>ja%xQEq61zkbG z%7ACnX+OHmf0%`jR25pr?>{RC-idGZoBy9v^j}Qcci*O4{?09Tjv1$_#8p9mG`s)t zt?$0wN&<K*;8Ou7*uRToFjl}73|x%Cyz-Cv^M3%xKmG+~dl0yQ7z{+lAjtnqL=_A2 z6_9#?gc#)Z|E-h!gZ%OR(g9L0ka~gC3#4BEhpCsTnU>4n_5%E&e}SSas2_u>K4?(< zJ4ga@7tl5W%{<VT1TEITwhcik9F)RADIAo-K`H!uJ?nqih9H~-;UowrK{yG*Nf1u{ zMWO)JNl={x)k#pD1l7sE_JKgR7<7w4w-|Jb|9X`Gx><r{Isac&7%lS|0~+ER4*k4I zgI81?cXg;#Ow;Z#bfW;=xMh5Q{^lD_-P4@#f2#8PetMMTdJX(-F95I)$vEk1YT;$c zEtWz;l{>x;|G0+jzmqXpz*J2~1EMhY(51dZ;)i>g{;vJ_2;OkgDm-+;)VL-6G-v<! zm-8>*{z_6TpfbUG<K8~@YIM%O7u8NHDU7{1f74`#fGOcdmCk=cF9}yuTdhwC3svU# z%`W^k8~b*Nu`(O?!rKo1d`C<yVBg1D%fDbRfBV-J;CZ0j9E@AEYSB35AJzu`eOx~R zPrwIuG4;mPRF%g}>wohY|F|d>g|PsMZs4Y;7P&x0`@g%5N9M*YcBMaE{}p&3+k*Xe z{L8Wbezcu7?#;-&FC`XWT}+$&55`psxR{4_yMXrlV^+^1|C9Q^k)MPr2OG<-rXnKN zq5nyZp}1H;PthBNZNLLD9m@Q7_x$Z?{O^PZFeYF~fFbessQl*_U`T*j;-6>5AAbR} z1ehiMBB_GF2?S0*njRo<0=dNBn8QDF1&~XCT;iW+#h-rx=`~2NzbEbgh)zLz4JuAQ z$}6Da1S(EHRt-TB78GHBlvkdCA}r`j{7`z21$_z7m-vAjbsDtlK&$TW*6=^Q0Ij<J zo9?xV<*jRf+Y9g`c>#Dtp!x)=Pd}O-p!x)=Pd{P_3dW%N1gcM<`t%*j0Yd@|2{0tU zkN|-b2%JFR^xX)6ApwTOcM}545@1MxApwTOcOw9X1Q-(EO$abcfFS{f1Q-(EjQ|)D zU`Tv7A;2sFh6ETAKMo0T{2F${hRyAk$4!0*JqpmH06hvYV}Kds|KW@gOFKr`y7gU* 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 277/395] 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 278/395] 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 279/395] 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 280/395] 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 281/395] 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 282/395] 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 283/395] 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 284/395] 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 285/395] 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 286/395] 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 287/395] 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 288/395] 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 289/395] 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 290/395] 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 291/395] 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 292/395] 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 293/395] 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 294/395] 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 295/395] 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 296/395] 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 297/395] 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 298/395] 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 299/395] 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 300/395] 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 301/395] 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 302/395] 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 303/395] 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 304/395] 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 305/395] 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 306/395] 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 307/395] [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 308/395] 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 309/395] 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 310/395] 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 311/395] 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 312/395] 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 313/395] 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 314/395] 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 315/395] 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 316/395] [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 317/395] 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 318/395] 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 319/395] 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 320/395] 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 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 321/395] 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 322/395] 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 323/395] 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 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 324/395] 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 325/395] 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 326/395] 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 327/395] 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 328/395] 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 329/395] 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 330/395] 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 331/395] 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 332/395] 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 333/395] 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 334/395] 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 335/395] 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 336/395] 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 337/395] 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 338/395] 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 339/395] 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 340/395] 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 341/395] 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 342/395] 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 343/395] 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 344/395] 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 345/395] 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 346/395] 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 347/395] 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 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 348/395] 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 349/395] 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 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 350/395] 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 351/395] 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 352/395] 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 353/395] 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 354/395] 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 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 355/395] 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 356/395] 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 357/395] 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 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 358/395] 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 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 359/395] 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 360/395] 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 361/395] 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 362/395] 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 363/395] 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 364/395] 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 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 365/395] 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 366/395] 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 367/395] 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 368/395] 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 369/395] 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 370/395] 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 371/395] 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 372/395] 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 373/395] 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 374/395] 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 375/395] 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 376/395] 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 377/395] 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 378/395] 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 379/395] 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 380/395] 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 381/395] 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 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 382/395] 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 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 383/395] 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 384/395] 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 385/395] 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 386/395] 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 387/395] 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 388/395] 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 389/395] 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 390/395] 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 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 391/395] 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 392/395] 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 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 393/395] 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 394/395] 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 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 395/395] 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;

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%0Adyv^458nhwg2y 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