Add support for Backstage plugins (#2739)

Closes #1509

Signed-off-by: Sergio Castaño Arteaga <tegioz@icloud.com>
Signed-off-by: Cintia Sanchez Garcia <cynthiasg@icloud.com>
Co-authored-by: Sergio Castaño Arteaga <tegioz@icloud.com>
Co-authored-by: Cintia Sanchez Garcia <cynthiasg@icloud.com>
This commit is contained in:
Sergio Castaño Arteaga 2023-02-06 13:15:43 +01:00 committed by GitHub
parent cc75c86028
commit f7fff2402b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 332 additions and 60 deletions

View File

@ -14,6 +14,7 @@ Discovering artifacts to use with CNCF projects can be difficult. If every CNCF
At the moment, the following artifacts kinds are supported *(with plans to support more projects to follow)*:
- [Backstage plugins](https://backstage.io)
- [Containers images](https://opencontainers.org)
- [CoreDNS plugins](https://coredns.io/)
- [Falco configurations](https://falco.org/)

View File

@ -2,7 +2,7 @@ apiVersion: v2
name: artifact-hub
description: Artifact Hub is a web-based application that enables finding, installing, and publishing Kubernetes packages.
type: application
version: 1.12.1-2
version: 1.12.1-3
appVersion: 1.12.0
kubeVersion: ">= 1.19.0-0"
home: https://artifacthub.io
@ -24,6 +24,7 @@ keywords:
- gatekeeper
- kyverno
- knative
- backstage
maintainers:
- name: Sergio
email: tegioz@icloud.com

View File

@ -93,7 +93,10 @@
"title": "Lifetime after finished execution",
"description": "Limits the lifetime of the job after it has finished execution",
"default": null,
"type": ["null", "integer"]
"type": [
"null",
"integer"
]
}
},
"required": [
@ -1066,7 +1069,7 @@
},
"repositoriesKinds": {
"title": "Repositories kinds to process ([] = all)",
"description": "The following kinds are supported at the moment: falco, helm, olm, opa, tbaction, krew, helm-plugin, tekton-task, keda-scaler, coredns, keptn, tekton-pipeline, container, kubewarden, gatekeeper, kyverno, knative-client-plugin",
"description": "The following kinds are supported at the moment: falco, helm, olm, opa, tbaction, krew, helm-plugin, tekton-task, keda-scaler, coredns, keptn, tekton-pipeline, container, kubewarden, gatekeeper, kyverno, knative-client-plugin, backstage",
"type": "array",
"items": {
"type": "string"

View File

@ -90,7 +90,7 @@ func newLintCmd() *cobra.Command {
return lint(opts, &output{cmd.OutOrStdout()})
},
}
lintCmd.Flags().StringVarP(&opts.kind, "kind", "k", "helm", "repository kind: coredns, falco, helm, helm-plugin, keda-scaler, keptn, krew, kubewarden, olm, opa, tbaction, tekton-task, tekton-pipeline")
lintCmd.Flags().StringVarP(&opts.kind, "kind", "k", "helm", "repository kind: backstage, coredns, falco, gatekeeper, helm, helm-plugin, keda-scaler, keptn, knative-client-plugin, krew, kubewarden, kyverno, olm, opa, tbaction, tekton-task, tekton-pipeline")
lintCmd.Flags().StringVarP(&opts.path, "path", "p", ".", "repository's packages path")
return lintCmd
}
@ -109,11 +109,15 @@ func lint(opts *lintOptions, out *output) error {
var report *lintReport
switch kind {
case
hub.Backstage,
hub.CoreDNS,
hub.Falco,
hub.Gatekeeper,
hub.KedaScaler,
hub.Keptn,
hub.KnativeClientPlugin,
hub.Kubewarden,
hub.Kyverno,
hub.OPA,
hub.TBAction:
report = lintGeneric(opts.path, kind)
@ -605,11 +609,15 @@ func (out *output) printPkgDetails(pkg *hub.Package) {
// Values specific to a repository kind
switch pkg.Repository.Kind {
case
hub.Backstage,
hub.CoreDNS,
hub.Falco,
hub.Gatekeeper,
hub.KedaScaler,
hub.Keptn,
hub.KnativeClientPlugin,
hub.Kubewarden,
hub.Kyverno,
hub.OPA,
hub.TBAction:

View File

@ -0,0 +1,5 @@
insert into repository_kind values (17, 'Backstage plugins');
---- create above / drop below ----
delete from repository_kind where repository_kind_id = 17;

View File

@ -524,7 +524,8 @@ select results_eq(
(13, 'Kubewarden policies'),
(14, 'Gatekeeper policies'),
(15, 'Kyverno policies'),
(16, 'Knative client plugins')
(16, 'Knative client plugins'),
(17, 'Backstage plugins')
$$,
'Repository kinds should exist'
);

View File

@ -1112,6 +1112,29 @@ paths:
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/backstage/{repoName}/{packageName}":
get:
tags:
- Packages
summary: Get package details
description: Get package details
operationId: getBackstagePluginsDetails
parameters:
- $ref: "#/components/parameters/RepoNameParam"
- $ref: "#/components/parameters/PackageNameParam"
responses:
"200":
description: ""
content:
application/json:
schema:
$ref: "#/components/schemas/BackstagePlugin"
"404":
$ref: "#/components/responses/NotFoundResponse"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/container/{repoName}/{packageName}":
get:
tags:
@ -1503,6 +1526,30 @@ paths:
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/backstage/{repoName}/{packageName}/{version}":
get:
tags:
- Packages
summary: Get package version details
description: Get package version details
operationId: getBackstagePluginsVersionDetails
parameters:
- $ref: "#/components/parameters/RepoNameParam"
- $ref: "#/components/parameters/PackageNameParam"
- $ref: "#/components/parameters/VersionParam"
responses:
"200":
description: ""
content:
application/json:
schema:
$ref: "#/components/schemas/BackstagePlugin"
"404":
$ref: "#/components/responses/NotFoundResponse"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/container/{repoName}/{packageName}/{version}":
get:
tags:
@ -3429,6 +3476,8 @@ components:
name: user1
total: 3
filter_key: user
BackstagePlugin:
$ref: "#/components/schemas/Package"
ContainerImage:
allOf:
- $ref: "#/components/schemas/Package"
@ -4311,6 +4360,7 @@ components:
* `14` - Gatekeeper policies
* `15` - Kyverno policies
* `16` - Knative client plugins
* `17` - Backstage plugins
RepositoryKindParam:
type: string
enum:
@ -4331,6 +4381,7 @@ components:
- gatekeeper
- kyverno
- knative-client-plugin
- backstage
description: |
Repository kind name:
* `helm` - Helm charts
@ -4350,6 +4401,7 @@ components:
* `gatekeeper` - Gatekeeper policies
* `kyverno` - Kyverno policies
* `knative-client-plugin` - Knative client plugins
* `backstage` - Backstage plugins
RepositorySummary:
type: object
required:
@ -4848,7 +4900,8 @@ components:
* `13` - Kubewarden policies
* `14` - Gatekeeper policies
* `15` - Kyverno policies
* `15` - Knative client plugins
* `16` - Knative client plugins
* `17` - Backstage plugins
PackageNameParam:
in: path
name: packageName

View File

@ -0,0 +1,49 @@
## Backstage plugins repositories
Backstage plugins repositories are expected to be hosted in GitHub, GitLab or Bitbucket repos. When adding your repository to Artifact Hub, the url used **must** follow the following format:
- `https://github.com/user/repo[/path/to/packages]`
- `https://gitlab.com/user/repo[/path/to/packages]`
- `https://bitbucket.org/user/repo[/path/to/packages]`
By default the `master` branch is used, but it's possible to specify a different one from the UI.
*Please NOTE that the repository URL used when adding the repository to Artifact Hub **must NOT** contain the git hosting platform specific parts, like **tree/branch**, just the path to your packages like it would show in the filesystem.*
The *path/to/packages* provided can contain metadata for one or more packages. Each package version **must** be on a separate folder, and it's up to you to decide if you want to publish one or multiple versions of your package.
The structure of a repository with multiple plugins packages and versions could look something like this:
```sh
$ tree path/to/packages
path/to/packages
├── artifacthub-repo.yml
├── package1
│   ├── 1.0.0
│   │   ├── README.md
│   │   └── artifacthub-pkg.yml
│   └── 2.0.0
│      ├── README.md
│   └── artifacthub-pkg.yml
└── package2
└── 1.0.0
      ├── README.md
└── artifacthub-pkg.yml
```
This structure is flexible, and in some cases it can be greatly simplified. In the case of a single package with a single version available at a time (the publisher doesn't want to make previous ones available, for example), the structure could look like this:
```sh
$ tree path/to/packages
path/to/packages
├── artifacthub-repo.yml
└── package1
   ├── README.md
└── artifacthub-pkg.yml
```
In the previous case, even the `package1` directory could be omitted. The reason is that both packages names and versions are read from the `artifacthub-pkg.yml` metadata file, so directories names are not used at all.
Each package version **needs** an `artifacthub-pkg.yml` metadata file. Please see the file [spec](https://github.com/artifacthub/hub/blob/master/docs/metadata/artifacthub-pkg.yml) for more details. The [artifacthub-repo.yml](https://github.com/artifacthub/hub/blob/master/docs/metadata/artifacthub-repo.yml) repository metadata file shown above can be used to setup features like [Verified publisher](https://github.com/artifacthub/hub/blob/master/docs/repositories.md#verified-publisher) or [Ownership claim](https://github.com/artifacthub/hub/blob/master/docs/repositories.md#ownership-claim). This file must be located at `/path/to/packages`.
Once you have added your repository, you are all set up. As you add new versions of your plugins packages or even new packages to your git repository, they'll be automatically indexed and listed in Artifact Hub.

View File

@ -4,6 +4,7 @@ Artifact Hub allows publishers to list their content in an automated way. Publis
The following repositories kinds are supported at the moment:
- [Backstage plugins repositories](https://github.com/artifacthub/hub/blob/master/docs/backstage_plugins_repositories.md)
- [Containers images repositories](https://github.com/artifacthub/hub/blob/master/docs/container_images_repositories.md)
- [CoreDNS plugins repositories](https://github.com/artifacthub/hub/blob/master/docs/coredns_plugins_repositories.md)
- [Falco rules repositories](https://github.com/artifacthub/hub/blob/master/docs/falco_rules_repositories.md)

View File

@ -0,0 +1,6 @@
---
title: "Backstage plugins"
aliases: [
"/backstage_plugins_repositories",
]
---

View File

@ -1,6 +1,5 @@
---
title: "Containers images"
weight: 1
aliases: [
"/container_images_repositories"
]

View File

@ -1,6 +1,5 @@
---
title: "CoreDNS plugins"
weight: 2
aliases: [
"/coredns_plugins_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Falco rules"
weight: 3
aliases: [
"/falco_rules_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Gatekeeper policies"
weight: 4
aliases: [
"/gatekeeper_policies_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Helm"
weight: 1
aliases: [
"/helm_annotations"
]

View File

@ -1,6 +1,5 @@
---
title: "Helm charts"
weight: 5
aliases: [
"/helm_charts_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Helm plugins"
weight: 6
aliases: [
"/helm_plugins_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "KEDA scalers"
weight: 7
aliases: [
"/keda_scalers_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Keptn"
weight: 2
aliases: [
"/keptn_annotations",
]

View File

@ -1,6 +1,5 @@
---
title: "Keptn integrations"
weight: 8
aliases: [
"/keptn_integrations_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Knative client plugins"
weight: 9
aliases: [
"/knative_client_plugins_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Krew"
weight: 3
aliases: [
"/krew_annotations",
]

View File

@ -1,6 +1,5 @@
---
title: "Krew kubectl plugins"
weight: 10
aliases: [
"/krew_kubectl_plugins_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Kubewarden"
weight: 4
aliases: [
"/kubewarden_annotations",
]

View File

@ -1,6 +1,5 @@
---
title: "Kubewarden policies"
weight: 11
aliases: [
"/kubewarden_policies_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Kyverno"
weight: 5
aliases: [
"/kyverno_annotations"
]

View File

@ -1,6 +1,5 @@
---
title: "Kyverno policies"
weight: 12
aliases: [
"/kyverno_policies_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "OLM"
weight: 6
aliases: [
"/olm_annotations",
]

View File

@ -1,6 +1,5 @@
---
title: "OLM operators"
weight: 13
aliases: [
"/olm_operators_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "OPA policies"
weight: 14
aliases: [
"/opa_policies_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Tekton"
weight: 7
aliases: [
"/tekton_annotations",
]

View File

@ -1,6 +1,5 @@
---
title: "Tekton pipelines"
weight: 15
aliases: [
"/tekton_pipelines_repositories",
]

View File

@ -1,6 +1,5 @@
---
title: "Tekton tasks"
weight: 16
aliases: [
"/tekton_tasks_repositories"
]

View File

@ -1,6 +1,5 @@
---
title: "Tinkerbell actions"
weight: 17
aliases: [
"/tinkerbell_actions_repositories",
]

View File

@ -264,7 +264,7 @@ func (h *Handlers) setupRouter() {
r.Get("/stats", h.Packages.GetStats)
r.With(corsMW).Get("/search", h.Packages.Search)
r.With(h.Users.RequireLogin).Get("/starred", h.Packages.GetStarredByUser)
r.Route("/{^helm$|^falco$|^opa$|^olm|^tbaction|^krew|^helm-plugin|^tekton-task|^keda-scaler|^coredns|^keptn|^tekton-pipeline|^container|^kubewarden|^gatekeeper|^kyverno|^knative-client-plugin$}/{repoName}/{packageName}", func(r chi.Router) {
r.Route("/{^helm$|^falco$|^opa$|^olm|^tbaction|^krew|^helm-plugin|^tekton-task|^keda-scaler|^coredns|^keptn|^tekton-pipeline|^container|^kubewarden|^gatekeeper|^kyverno|^knative-client-plugin|^backstage$}/{repoName}/{packageName}", func(r chi.Router) {
r.Get("/feed/rss", h.Packages.RssFeed)
r.With(corsMW).Get("/summary", h.Packages.GetSummary)
r.Get("/{version}", h.Packages.Get)
@ -421,7 +421,7 @@ func (h *Handlers) setupRouter() {
// Index special entry points
r.Route("/packages", func(r chi.Router) {
r.Route("/{^helm$|^falco$|^opa$|^olm|^tbaction|^krew|^helm-plugin|^tekton-task|^keda-scaler|^coredns|^keptn|^tekton-pipeline|^container|^kubewarden|^gatekeeper|^kyverno|^knative-client-plugin$}/{repoName}/{packageName}", func(r chi.Router) {
r.Route("/{^helm$|^falco$|^opa$|^olm|^tbaction|^krew|^helm-plugin|^tekton-task|^keda-scaler|^coredns|^keptn|^tekton-pipeline|^container|^kubewarden|^gatekeeper|^kyverno|^knative-client-plugin|^backstage$}/{repoName}/{packageName}", func(r chi.Router) {
r.With(h.Packages.InjectIndexMeta).Get("/{version}", h.Static.Index)
r.With(h.Packages.InjectIndexMeta).Get("/", h.Static.Index)
})

View File

@ -2069,6 +2069,17 @@ func TestBuildURL(t *testing.T) {
"2.0.0",
baseURL + "/packages/knative-client-plugin/repo1/pkg1/2.0.0",
},
{
&hub.Package{
NormalizedName: "pkg1",
Repository: &hub.Repository{
Kind: hub.Backstage,
Name: "repo1",
},
},
"2.0.0",
baseURL + "/packages/backstage/repo1/pkg1/2.0.0",
},
}
for _, tc := range testCases {
tc := tc

View File

@ -97,11 +97,16 @@ const (
// KnativeClientPlugin represents a repository with Knative client plugins.
KnativeClientPlugin RepositoryKind = 16
// Backstage represents a repository with Backstage plugins.
Backstage RepositoryKind = 17
)
// GetKindName returns the name of the provided repository kind.
func GetKindName(kind RepositoryKind) string {
switch kind {
case Backstage:
return "backstage"
case Container:
return "container"
case CoreDNS:
@ -145,6 +150,8 @@ func GetKindName(kind RepositoryKind) string {
// provided.
func GetKindFromName(kind string) (RepositoryKind, error) {
switch kind {
case "backstage":
return Backstage, nil
case "container":
return Container, nil
case "coredns":

View File

@ -78,6 +78,7 @@ var (
// validRepositoryKinds contains the repository kinds supported.
validRepositoryKinds = []hub.RepositoryKind{
hub.Backstage,
hub.Container,
hub.CoreDNS,
hub.Falco,
@ -274,6 +275,7 @@ func (m *Manager) ClaimOwnership(ctx context.Context, repoName, orgName string)
var basePath string
switch r.Kind {
case
hub.Backstage,
hub.CoreDNS,
hub.Falco,
hub.Gatekeeper,
@ -448,6 +450,7 @@ func (m *Manager) locateMetadataFile(r *hub.Repository, basePath string) string
mdFile = r.URL
}
case
hub.Backstage,
hub.CoreDNS,
hub.Falco,
hub.Gatekeeper,
@ -806,6 +809,7 @@ func (m *Manager) validateURL(r *hub.Repository) error {
}
}
case
hub.Backstage,
hub.CoreDNS,
hub.Falco,
hub.Gatekeeper,

View File

@ -113,6 +113,7 @@ func SetupSource(i *hub.TrackerSourceInput) hub.TrackerSource {
case hub.OLM:
source = olm.NewTrackerSource(i)
case
hub.Backstage,
hub.CoreDNS,
hub.Gatekeeper,
hub.KedaScaler,

View File

@ -176,6 +176,7 @@ func (t *Tracker) cloneRepository() (string, string, error) {
tmpDir, packagesPath, err = t.svc.Rc.CloneRepository(t.svc.Ctx, t.r)
}
case
hub.Backstage,
hub.CoreDNS,
hub.Falco,
hub.Gatekeeper,

View File

@ -6,6 +6,7 @@ cat docs/www/headers/dev docs/dev.md > docs/www/content/topics/dev.md
cat docs/www/headers/infrastructure docs/infrastructure.md > docs/www/content/topics/infrastructure.md
mkdir -p docs/www/content/topics/repositories
cat docs/www/headers/repositories docs/repositories.md > docs/www/content/topics/repositories/_index.md
cat docs/www/headers/backstage_plugins_repositories docs/backstage_plugins_repositories.md > docs/www/content/topics/repositories/backstage-plugins.md
cat docs/www/headers/container_images_repositories docs/container_images_repositories.md > docs/www/content/topics/repositories/container-images.md
cat docs/www/headers/coredns_plugins_repositories docs/coredns_plugins_repositories.md > docs/www/content/topics/repositories/coredns-plugins.md
cat docs/www/headers/falco_rules_repositories docs/falco_rules_repositories.md > docs/www/content/topics/repositories/falco-rules.md

View File

@ -0,0 +1 @@
<svg id="Assets" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 337.46475 428.49896"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M303.02856,166.04816a80.384,80.384,0,0,0,13.44825-10.37128c.79419-.76227,1.55041-1.53052,2.30078-2.30078a82.04885,82.04885,0,0,0,7.9292-9.37811,63.42474,63.42474,0,0,0,6.26928-10.76539,48.6159,48.6159,0,0,0,4.35877-16.39782c1.48279-19.39118-9.96729-38.67493-35.62195-54.22687L198.55737,0l-120.26,115.22662L0,190.2478l108.60107,65.90778a111.60534,111.60534,0,0,0,57.76172,16.41577c24.92212,0,48.80127-8.803,66.41919-25.68646,19.15833-18.36218,25.51929-42.128,13.697-61.87146a49.0086,49.0086,0,0,0-6.7987-8.86865,89.32561,89.32561,0,0,0,19.28576,2.14355c.05164,0,.10144.004.15113.004a85.01244,85.01244,0,0,0,30.9707-5.7937A80.536,80.536,0,0,0,303.02856,166.04816ZM202.44543,225.85583c-19.3197,18.51-50.39855,21.23664-75.69982,5.89936L51.61328,186.14752l67.44336-64.64239,76.41687,46.38617C223.01074,184.58405,221.49072,207.60742,202.44543,225.85583Zm8.93348-82.21734-70.64722-42.8888,64.40723-61.76837L274.5083,81.09558c25.94006,15.72455,29.31006,37.04126,10.55042,55.017A60.70506,60.70506,0,0,1,211.37891,143.63849Zm29.86572,190.0401c-19.5763,18.75629-46.17029,29.08777-74.88184,29.08777A123.81616,123.81616,0,0,1,102.2561,344.5733L0,282.51672V307.194l108.60107,65.90778a111.60536,111.60536,0,0,0,57.76172,16.41571c24.92212,0,48.80127-8.80292,66.41919-25.6864,12.87708-12.34162,19.99024-27.12934,19.67981-41.49311l-.00207-1.79126A87.09493,87.09493,0,0,1,241.24463,333.67859Zm0-38.98346c-19.5763,18.75635-46.17029,29.08783-74.88184,29.08783A123.81616,123.81616,0,0,1,102.2561,305.5899L0,243.53333v24.67932l108.60107,65.90777a111.60583,111.60583,0,0,0,57.76172,16.41571c24.92212,0,48.80127-8.803,66.41919-25.6864,12.87708-12.34363,19.99024-27.12933,19.67981-41.49512l-.00207-1.78924A86.98006,86.98006,0,0,1,241.24463,294.69513Zm0-38.98138c-19.5763,18.75628-46.17029,29.08776-74.88184,29.08776a123.81568,123.81568,0,0,1-64.10669-18.19305L0,204.55188v24.67737L108.60107,295.137a111.60583,111.60583,0,0,0,57.76172,16.41571c24.92212,0,48.80127-8.803,66.41919-25.6864,12.87708-12.34167,19.99024-27.12939,19.67981-41.49316l-.00207-1.82306A86.47145,86.47145,0,0,1,241.24463,255.71375Zm83.69079,25.73815a94.13732,94.13732,0,0,1-60.19177,25.8556v-.002h-.01184l.01184,26.66766a81.65277,81.65277,0,0,0,51.73316-22.36865c13.96777-13.38458,21.14453-28.11059,20.98535-42.64154v-2.19726A95.16106,95.16106,0,0,1,324.93542,281.4519ZM241.24463,372.66c-19.5763,18.75629-46.17029,29.08777-74.88184,29.08777a123.81625,123.81625,0,0,1-64.10669-18.19305L0,321.49811v24.67737l108.60107,65.90771A111.60534,111.60534,0,0,0,166.36279,428.499c24.92212,0,48.80127-8.803,66.41919-25.6864,12.87708-12.34167,19.99024-27.12939,19.67981-41.49316l-.00207-1.78925A86.98289,86.98289,0,0,1,241.24463,372.66Zm85.74475-210.20623c-.67859.68664-1.34534,1.37329-2.054,2.05194A99.29568,99.29568,0,0,1,302.7041,180.193a94.67991,94.67991,0,0,1-26.2456,8.71143,98.08664,98.08664,0,0,1-14.16089,1.56634c.50561,1.61213.90368,3.25007,1.25,4.902a53.15974,53.15974,0,0,1,1.13843,12.00128l.0039,9.65284h.05371A84.26983,84.26983,0,0,0,290.08789,211.48a80.95382,80.95382,0,0,0,26.38892-16.82178c.802-.7702,1.50464-1.55835,2.26294-2.33654a82.04872,82.04872,0,0,0,7.92724-9.38019,63.32792,63.32792,0,0,0,6.28321-10.77527,48.44218,48.44218,0,0,0,4.319-16.44165c.09155-1.236.205-2.47388.193-3.70789v-2.048q-1.08069,1.55245-2.257,3.08893A97.66566,97.66566,0,0,1,326.98938,162.45374Zm-.03186,77.921c-.68652.69458-1.30566,1.4071-2.0221,2.09375a94.13054,94.13054,0,0,1-60.19177,25.8576v-.002h-.02978l.012,26.6676h.01392l.0039.002v-.002a81.65282,81.65282,0,0,0,51.73316-22.36865,73.5466,73.5466,0,0,0,16.47339-22.492,48.45386,48.45386,0,0,0,4.319-16.44159c.09155-1.238.205-2.47393.193-3.7099v-2.19323c-.74439,1.0747-1.46485,2.15344-2.27283,3.21624A97.104,97.104,0,0,1,326.95752,240.37476Zm0-38.98145c-.68652.69464-1.30359,1.40717-2.0221,2.09381a97.185,97.185,0,0,1-22.25122,15.67536,95.66871,95.66871,0,0,1-37.94055,10.18023H264.696l.01185,26.6676h.0299l.00586.002v-.002a81.65068,81.65068,0,0,0,51.73316-22.37066c.802-.7702,1.50464-1.55835,2.26294-2.33655A82.05256,82.05256,0,0,0,326.667,221.923a63.33031,63.33031,0,0,0,6.28321-10.77533,48.4418,48.4418,0,0,0,4.319-16.44159c.09155-1.236.205-2.47393.193-3.70788v-2.1933c-.74439,1.07477-1.46485,2.1535-2.27283,3.21631A97.33693,97.33693,0,0,1,326.95752,201.39331Z"/></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1 @@
<svg id="Assets" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 337.46475 428.49896"><defs><style>.cls-1{fill:#7df3e1;}</style></defs><path class="cls-1" d="M303.02856,166.04816a80.384,80.384,0,0,0,13.44825-10.37128c.79419-.76227,1.55041-1.53052,2.30078-2.30078a82.04885,82.04885,0,0,0,7.9292-9.37811,63.42407,63.42407,0,0,0,6.26928-10.76539,48.6159,48.6159,0,0,0,4.35877-16.39782c1.48279-19.39118-9.96729-38.67493-35.62195-54.22687L198.55737,0l-120.26,115.22662L0,190.2478l108.60107,65.90778a111.60534,111.60534,0,0,0,57.76172,16.41577c24.92212,0,48.80127-8.803,66.41919-25.68646,19.15833-18.36218,25.51929-42.128,13.697-61.87146a49.0086,49.0086,0,0,0-6.7987-8.86865,89.32561,89.32561,0,0,0,19.28576,2.14355c.05164,0,.10144.004.15113.004a85.01244,85.01244,0,0,0,30.9707-5.7937A80.536,80.536,0,0,0,303.02856,166.04816ZM202.44543,225.85583c-19.3197,18.51-50.39855,21.23664-75.69982,5.89936L51.61328,186.14752l67.44336-64.64239,76.41687,46.38617C223.01074,184.58405,221.49072,207.60742,202.44543,225.85583Zm8.93348-82.21734-70.64722-42.8888,64.40723-61.76837L274.5083,81.09558c25.94006,15.72455,29.31006,37.04126,10.55042,55.017A60.70506,60.70506,0,0,1,211.37891,143.63849Zm29.86572,190.0401c-19.5763,18.75629-46.17029,29.08777-74.88184,29.08777A123.81616,123.81616,0,0,1,102.2561,344.5733L0,282.51672V307.194l108.60107,65.90778a111.60536,111.60536,0,0,0,57.76172,16.41571c24.92212,0,48.80127-8.80292,66.41919-25.6864,12.87708-12.34162,19.99024-27.12934,19.67981-41.49311l-.00207-1.79126A87.09493,87.09493,0,0,1,241.24463,333.67859Zm0-38.98346c-19.5763,18.75635-46.17029,29.08783-74.88184,29.08783A123.81616,123.81616,0,0,1,102.2561,305.5899L0,243.53333v24.67932l108.60107,65.90777a111.60583,111.60583,0,0,0,57.76172,16.41571c24.92212,0,48.80127-8.803,66.41919-25.6864,12.87708-12.34363,19.99024-27.12933,19.67981-41.49512l-.00207-1.78924A86.98006,86.98006,0,0,1,241.24463,294.69513Zm0-38.98138c-19.5763,18.75628-46.17029,29.08776-74.88184,29.08776a123.81568,123.81568,0,0,1-64.10669-18.19305L0,204.55188v24.67737L108.60107,295.137a111.60583,111.60583,0,0,0,57.76172,16.41571c24.92212,0,48.80127-8.803,66.41919-25.6864,12.87708-12.34167,19.99024-27.12939,19.67981-41.49316l-.00207-1.82306A86.47145,86.47145,0,0,1,241.24463,255.71375Zm83.69079,25.73815a94.13732,94.13732,0,0,1-60.19177,25.8556v-.002h-.01184l.01184,26.66766a81.65277,81.65277,0,0,0,51.73316-22.36865c13.96777-13.38458,21.14453-28.11059,20.98535-42.64154v-2.19726A95.16106,95.16106,0,0,1,324.93542,281.4519ZM241.24463,372.66c-19.5763,18.75629-46.17029,29.08777-74.88184,29.08777a123.81625,123.81625,0,0,1-64.10669-18.19305L0,321.49811v24.67737l108.60107,65.90771A111.60534,111.60534,0,0,0,166.36279,428.499c24.92212,0,48.80127-8.803,66.41919-25.6864,12.87708-12.34167,19.99024-27.12939,19.67981-41.49316l-.00207-1.78925A86.98289,86.98289,0,0,1,241.24463,372.66Zm85.74475-210.20623c-.67859.68664-1.34534,1.37329-2.054,2.05194A99.29568,99.29568,0,0,1,302.7041,180.193a94.67991,94.67991,0,0,1-26.2456,8.71143,98.08664,98.08664,0,0,1-14.16089,1.56634c.50561,1.61213.90368,3.25007,1.25,4.902a53.15974,53.15974,0,0,1,1.13843,12.00128l.0039,9.65284h.05371A84.26983,84.26983,0,0,0,290.08789,211.48a80.95382,80.95382,0,0,0,26.38892-16.82178c.802-.7702,1.50464-1.55835,2.26294-2.33654a82.04872,82.04872,0,0,0,7.92724-9.38019,63.32792,63.32792,0,0,0,6.28321-10.77527,48.44218,48.44218,0,0,0,4.319-16.44165c.09155-1.236.205-2.47388.193-3.70789v-2.048q-1.08069,1.55245-2.257,3.08893A97.66566,97.66566,0,0,1,326.98938,162.45374Zm-.03186,77.921c-.68652.69458-1.30566,1.4071-2.0221,2.09375a94.13054,94.13054,0,0,1-60.19177,25.8576v-.002h-.02978l.012,26.6676h.01392l.0039.002v-.002a81.65282,81.65282,0,0,0,51.73316-22.36865,73.5466,73.5466,0,0,0,16.47339-22.492,48.45386,48.45386,0,0,0,4.319-16.44159c.09155-1.238.205-2.47393.193-3.7099v-2.19323c-.74439,1.0747-1.46485,2.15344-2.27283,3.21624A97.104,97.104,0,0,1,326.95752,240.37476Zm0-38.98145c-.68652.69464-1.30359,1.40717-2.0221,2.09381a97.185,97.185,0,0,1-22.25122,15.67536,95.66871,95.66871,0,0,1-37.94055,10.18023H264.696l.01185,26.6676h.0299l.00586.002v-.002a81.65068,81.65068,0,0,0,51.73316-22.37066c.802-.7702,1.50464-1.55835,2.26294-2.33655A82.05256,82.05256,0,0,0,326.667,221.923a63.33031,63.33031,0,0,0,6.28321-10.77533,48.4418,48.4418,0,0,0,4.319-16.44159c.09155-1.236.205-2.47393.193-3.70788v-2.1933c-.74439,1.07477-1.46485,2.1535-2.27283,3.21631A97.33693,97.33693,0,0,1,326.95752,201.39331Z"/></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

View File

@ -62,6 +62,8 @@ const Image = (props: Props) => {
return '/static/media/placeholder_pkg_kyverno.png';
case RepositoryKind.KnativeClientPlugin:
return '/static/media/placeholder_pkg_knative.png';
case RepositoryKind.Backstage:
return '/static/media/placeholder_pkg_backstage.png';
default:
return PLACEHOLDER_SRC;
}

View File

@ -128,6 +128,13 @@ describe('RepositoryIcon', () => {
expect(icon).toHaveProperty('src', 'http://localhost/static/media/knative-light.svg');
});
it('renders Backstage plugin icon', () => {
render(<RepositoryIcon kind={RepositoryKind.Backstage} type="white" />);
const icon = screen.getByAltText('Icon');
expect(icon).toBeInTheDocument();
expect(icon).toHaveProperty('src', 'http://localhost/static/media/backstage-light.svg');
});
it('renders Chart icon - default type', () => {
render(<RepositoryIcon kind={RepositoryKind.Helm} />);
const icons = screen.getAllByAltText('Icon');

View File

@ -77,6 +77,10 @@ const ICONS = {
default: '/static/media/knative.svg',
white: '/static/media/knative-light.svg',
},
[RepositoryKind.Backstage]: {
default: '/static/media/backstage.svg',
white: '/static/media/backstage-light.svg',
},
};
const RepositoryIcon = (props: Props) => {

View File

@ -82,6 +82,10 @@ jest.mock('../../utils/getSampleQueries', () => () => {
name: 'Knative client plugings',
querystring: 'kind=16',
},
{
name: 'Backstage plugings',
querystring: 'kind=17',
},
];
});

View File

@ -431,6 +431,17 @@ const RepositoryModal = (props: Props) => {
</ExternalLink>
);
break;
case RepositoryKind.Backstage:
link = (
<ExternalLink
href="/docs/topics/repositories/backstage-plugins"
className="text-primary fw-bold"
label="Open documentation"
>
Backstage plugins
</ExternalLink>
);
break;
}
if (isUndefined(link)) return;
@ -455,6 +466,7 @@ const RepositoryModal = (props: Props) => {
case RepositoryKind.Gatekeeper:
case RepositoryKind.Kyverno:
case RepositoryKind.KnativeClientPlugin:
case RepositoryKind.Backstage:
return (
<>
<p
@ -843,6 +855,7 @@ const RepositoryModal = (props: Props) => {
RepositoryKind.Gatekeeper,
RepositoryKind.Kyverno,
RepositoryKind.KnativeClientPlugin,
RepositoryKind.Backstage,
].includes(selectedKind) && (
<div>
<InputField
@ -984,6 +997,7 @@ const RepositoryModal = (props: Props) => {
RepositoryKind.Gatekeeper,
RepositoryKind.Kyverno,
RepositoryKind.KnativeClientPlugin,
RepositoryKind.Backstage,
].includes(selectedKind) && (
<div className="mt-4 mb-3">
<div className="form-check form-switch ps-0">

View File

@ -59,6 +59,11 @@ exports[`Repository Modal - repositories section creates snapshot 1`] = `
name="repoKind"
required=""
>
<option
value="17"
>
Backstage plugins
</option>
<option
value="12"
>

View File

@ -34,6 +34,7 @@
.aboutIcon {
width: 75px;
max-height: 75px;
}
.legend {
@ -75,6 +76,7 @@
.aboutIcon {
width: 55px;
max-height: 55px;
}
.extraInfo,
@ -99,6 +101,7 @@
.aboutIcon {
width: 35px;
max-height: 35px;
}
.logo {

View File

@ -332,7 +332,7 @@ exports[`Home index creates snapshot 1`] = `
<div
class="text-center px-3 px-xs-0"
>
Artifact Hub is a web-based application that enables finding, installing, and publishing packages and configurations for CNCF projects. For example, this could include Helm charts and plugins, Falco configurations, Open Policy Agent (OPA) and Gatekeeper policies, OLM operators, Tinkerbell actions, kubectl plugins, Tekton tasks and pipelines, KEDA scalers, CoreDNS plugins, Keptn integrations, container images, Kubewarden policies, Kyverno policies and Knative client plugins.
Artifact Hub is a web-based application that enables finding, installing, and publishing packages and configurations for CNCF projects. For example, this could include Helm charts and plugins, Falco configurations, Open Policy Agent (OPA) and Gatekeeper policies, OLM operators, Tinkerbell actions, kubectl plugins, Tekton tasks and pipelines, KEDA scalers, CoreDNS plugins, Keptn integrations, container images, Kubewarden policies, Kyverno policies, Knative client and Backstage plugins.
<div
class="mx-0 mx-md-3 mx-lg-5 my-4 my-sm-5 d-flex flex-row align-items-stretch justify-content-around"
>
@ -606,9 +606,6 @@ exports[`Home index creates snapshot 1`] = `
<div
class="mx-0 mx-md-3 mx-lg-5 my-4 my-sm-5 d-flex flex-row align-items-stretch justify-content-around"
>
<div
class="col"
/>
<a
aria-label="Open Container Initiative site"
class="link col iconLink"
@ -713,9 +710,32 @@ exports[`Home index creates snapshot 1`] = `
</div>
</div>
</a>
<a
aria-label="Open Backstage web"
class="link col iconLink"
href="https://backstage.io/plugins"
rel="noopener noreferrer"
role="button"
tabindex="-1"
target="_blank"
>
<div
class="col"
class="d-flex flex-column justify-content-between align-items-center h-100"
>
<img
alt="Icon"
class="aboutIcon"
src="/static/media/backstage-light.svg"
/>
<div
class="d-none d-sm-block text-light mt-2 legendIcon"
>
<small>
Backstage plugins
</small>
</div>
</div>
</a>
</div>
Discovering artifacts to use with CNCF projects can be difficult. If every CNCF project that needs to share artifacts creates its own Hub this creates a fair amount of repeat work for each project and a fractured experience for those trying to find the artifacts to consume. The Artifact Hub attempts to solve that by providing a single experience for consumers that any CNCF project can leverage.
</div>

View File

@ -131,7 +131,7 @@ describe('Home index', () => {
await waitFor(() => expect(API.getStats).toHaveBeenCalledTimes(1));
const links = await screen.findAllByRole('button');
expect(links).toHaveLength(21);
expect(links).toHaveLength(22);
expect(links[2]).toHaveProperty('href', 'https://github.com/artifacthub/hub');
expect(links[3]).toHaveProperty('href', 'https://cloud-native.slack.com/channels/artifact-hub');
@ -155,8 +155,9 @@ describe('Home index', () => {
expect(links[17]).toHaveProperty('href', 'https://www.kubewarden.io/');
expect(links[18]).toHaveProperty('href', 'https://www.kyverno.io/');
expect(links[19]).toHaveProperty('href', 'https://github.com/knative/client');
expect(links[20]).toHaveProperty('href', 'https://backstage.io/plugins');
expect(links[20]).toHaveProperty('href', 'https://www.cncf.io/sandbox-projects/');
expect(links[21]).toHaveProperty('href', 'https://www.cncf.io/sandbox-projects/');
});
});
});

View File

@ -235,7 +235,7 @@ const HomeView = (props: Props) => {
configurations for CNCF projects. For example, this could include Helm charts and plugins, Falco
configurations, Open Policy Agent (OPA) and Gatekeeper policies, OLM operators, Tinkerbell actions,
kubectl plugins, Tekton tasks and pipelines, KEDA scalers, CoreDNS plugins, Keptn integrations,
container images, Kubewarden policies, Kyverno policies and Knative client plugins.
container images, Kubewarden policies, Kyverno policies, Knative client and Backstage plugins.
<div className="mx-0 mx-md-3 mx-lg-5 my-4 my-sm-5 d-flex flex-row align-items-stretch justify-content-around">
<ExternalLink href="https://helm.sh" className={`col ${styles.iconLink}`} label="Open Helm site">
<div className="d-flex flex-column justify-content-between align-items-center h-100">
@ -341,7 +341,6 @@ const HomeView = (props: Props) => {
</ExternalLink>
</div>
<div className="mx-0 mx-md-3 mx-lg-5 my-4 my-sm-5 d-flex flex-row align-items-stretch justify-content-around">
<div className="col" />
<ExternalLink
href="https://opencontainers.org"
className={`col ${styles.iconLink}`}
@ -394,8 +393,18 @@ const HomeView = (props: Props) => {
</div>
</div>
</ExternalLink>
<div className="col" />
<ExternalLink
href="https://backstage.io/plugins"
className={`col ${styles.iconLink}`}
label="Open Backstage web"
>
<div className="d-flex flex-column justify-content-between align-items-center h-100">
<RepositoryIcon kind={RepositoryKind.Backstage} type="white" className={styles.aboutIcon} />
<div className={`d-none d-sm-block text-light mt-2 ${styles.legendIcon}`}>
<small>Backstage plugins</small>
</div>
</div>
</ExternalLink>
</div>
Discovering artifacts to use with CNCF projects can be difficult. If every CNCF project that needs to
share artifacts creates its own Hub this creates a fair amount of repeat work for each project and a

View File

@ -18,6 +18,7 @@ export enum RepositoryKind {
Gatekeeper,
Kyverno,
KnativeClientPlugin,
Backstage,
}
export enum KeptnData {

View File

@ -88,6 +88,15 @@ export interface RepoKindDef {
// Sorted alphabetically
export const REPOSITORY_KINDS: RepoKindDef[] = [
{
kind: RepositoryKind.Backstage,
label: 'backstage',
name: 'Backstage plugins',
singular: 'Backstage plugin',
plural: 'Backstage plugins',
icon: <RepositoryIcon kind={RepositoryKind.Backstage} className="mw-100 mh-100" />,
active: true,
},
{
kind: RepositoryKind.Container,
label: 'container',
@ -795,4 +804,4 @@ export const CVSS_V3_VECTORS: { [key: string]: CVSSVectorMetric[] } = {
export const OCI_PREFIX = 'oci://';
export const PKG_DETAIL_PATH =
/^\/packages\/(helm|falco|opa|olm|tbaction|krew|helm-plugin|tekton-task|keda-scaler|coredns|keptn|tekton-pipeline|kubewarden|gatekeeper|kyverno|knative-client-plugin|container)\//;
/^\/packages\/(helm|falco|opa|olm|tbaction|krew|helm-plugin|tekton-task|keda-scaler|coredns|keptn|tekton-pipeline|kubewarden|gatekeeper|kyverno|knative-client-plugin|backstage|container)\//;

View File

@ -71,6 +71,10 @@ describe('repoKind', () => {
expect(methods.getRepoKind('knative-client-plugin')).toBe(RepositoryKind.KnativeClientPlugin);
});
it('backstage', () => {
expect(methods.getRepoKind('backstage')).toBe(RepositoryKind.Backstage);
});
it('unknown', () => {
expect(methods.getRepoKind('unknown')).toBeNull();
});
@ -145,6 +149,10 @@ describe('repoKind', () => {
expect(methods.getRepoKindName(RepositoryKind.KnativeClientPlugin)).toBe('knative-client-plugin');
});
it('backstage kind', () => {
expect(methods.getRepoKindName(RepositoryKind.Backstage)).toBe('backstage');
});
it('unknown kind', () => {
expect(methods.getRepoKindName(20)).toBeNull();
});

View File

@ -36,6 +36,8 @@ const getRepoKind = (repoName: string): RepositoryKind | null => {
return RepositoryKind.Kyverno;
case 'knative-client-plugin':
return RepositoryKind.KnativeClientPlugin;
case 'backstage':
return RepositoryKind.Backstage;
default:
return null;
}
@ -77,6 +79,8 @@ const getRepoKindName = (repoKind: RepositoryKind): string | null => {
return 'kyverno';
case RepositoryKind.KnativeClientPlugin:
return 'knative-client-plugin';
case RepositoryKind.Backstage:
return 'backstage';
default:
return null;
}

View File

@ -1,18 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>Artifact Hub widget</title>
</head>
<body>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div class="artifacthub-widget-group" data-url="http://localhost:8000/packages/search?kind=16&sort=relevance&page=1" data-theme="light" data-header="false" data-stars="true" data-color="#417598" data-responsive="true" data-loading="true"></div>
<div class="artifacthub-widget-group" data-url="http://localhost:8000/packages/search" data-theme="light" data-header="false" data-stars="true" data-color="#417598" data-responsive="true" data-loading="true"></div>
<div class="artifacthub-widget" data-url="https://artifacthub.io/packages/helm/artifact-hub/artifact-hub" data-theme="light" data-header="true" data-stars="false" data-responsive="false"><blockquote><p lang="en" dir="ltr"><b>artifact-hub</b>: Artifact Hub is a web-based application that enables finding, installing, and publishing Kubernetes packages.</p>&mdash; Open in <a href="https://artifacthub.io/packages/helm/artifact-hub/artifact-hub">Artifact Hub</a></blockquote></div>
<div class="artifacthub-widget-group" data-url="https://artifacthub.io/api/v1/packages/search" data-theme="dark" data-header="false" data-stars="false" data-color="#417598" data-responsive="true" data-loading="true"></div>
<div class="artifacthub-widget-group" data-url="https://artifacthub.io/packages/search?page=1&ts_query_web=hub" data-theme="light" data-header="false" data-color="#417598" data-responsive="true" data-loading="true"></div>
</body>
<div class="artifacthub-widget-group" data-url="http://localhost:8000/packages/search?kind=17&sort=relevance&page=1"
data-theme="light" data-header="false" data-stars="true" data-color="#417598" data-responsive="true"
data-loading="true"></div>
<div class="artifacthub-widget-group" data-url="http://localhost:8000/packages/search" data-theme="light"
data-header="false" data-stars="true" data-color="#417598" data-responsive="true" data-loading="true"></div>
<div class="artifacthub-widget" data-url="https://artifacthub.io/packages/helm/artifact-hub/artifact-hub"
data-theme="light" data-header="true" data-stars="false" data-responsive="false">
<blockquote>
<p lang="en" dir="ltr"><b>artifact-hub</b>: Artifact Hub is a web-based application that enables finding,
installing, and publishing Kubernetes packages.</p>&mdash; Open in <a
href="https://artifacthub.io/packages/helm/artifact-hub/artifact-hub">Artifact Hub</a>
</blockquote>
</div>
<div class="artifacthub-widget-group" data-url="https://artifacthub.io/api/v1/packages/search" data-theme="dark"
data-header="false" data-stars="false" data-color="#417598" data-responsive="true" data-loading="true"></div>
<div class="artifacthub-widget-group" data-url="https://artifacthub.io/packages/search?page=1&ts_query_web=hub"
data-theme="light" data-header="false" data-color="#417598" data-responsive="true" data-loading="true"></div>
</body>
</html>

View File

@ -83,6 +83,8 @@ const getRepoKindName = (repoKind: RepositoryKind): string | null => {
return 'kyverno';
case RepositoryKind.KnativeClientPlugin:
return 'knative-client-plugin';
case RepositoryKind.Backstage:
return 'backstage';
default:
return null;
}

View File

@ -144,6 +144,13 @@ describe('Image', () => {
expect(image).toHaveProperty('src', 'https://localhost:8000/static/media/placeholder_pkg_knative.png');
});
it('renders Backstage plugin icon', () => {
render(<Image {...defaultProps} kind={RepositoryKind.Backstage} />);
const image = screen.getByAltText('alt image');
expect(image).toBeInTheDocument();
expect(image).toHaveProperty('src', 'https://localhost:8000/static/media/placeholder_pkg_backstage.png');
});
it('renders placeholder icon', () => {
render(<Image {...defaultProps} placeholderIcon={<>icon</>} />);
expect(screen.getByText('icon')).toBeInTheDocument();

View File

@ -63,6 +63,8 @@ const Image = (props: Props) => {
return '/static/media/placeholder_pkg_kyverno.png';
case RepositoryKind.KnativeClientPlugin:
return '/static/media/placeholder_pkg_knative.png';
case RepositoryKind.Backstage:
return '/static/media/placeholder_pkg_backstage.png';
default:
return PLACEHOLDER_SRC;
}

View File

@ -29,6 +29,7 @@ const ICONS: IconsList = {
[RepositoryKind.Gatekeeper]: <SVGIcons name="gatekeeper" />,
[RepositoryKind.Kyverno]: <SVGIcons name="kyverno" />,
[RepositoryKind.KnativeClientPlugin]: <SVGIcons name="knative" />,
[RepositoryKind.Backstage]: <SVGIcons name="backstage" />,
};
const RepositoryIcon = (props: Props) => (

View File

@ -84,6 +84,10 @@ const REPOSITORY_KINDS: RepoKindDef[] = [
kind: RepositoryKind.KnativeClientPlugin,
name: 'Knative client plugin',
},
{
kind: RepositoryKind.Backstage,
name: 'Backstage plugin',
},
];
const Wrapper = styled('span')`

View File

@ -108,6 +108,11 @@ describe('SVGIcons', () => {
expect(screen.getByTitle('knative'));
});
it('renders backstage icon', () => {
render(<SVGIcons name="backstage" />);
expect(screen.getByTitle('backstage'));
});
it('does not render when name is not in the list', () => {
render(<SVGIcons name="not-listed" />);
expect(screen.getByTestId('iconWrapper')).toBeEmptyDOMElement();

View File

@ -904,6 +904,19 @@ const SVGIcons = (props: Props) => (
</svg>
);
case 'backstage':
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 337.465 428.499">
<title>{props.name}</title>
<path
d="M303.029 166.048a80.384 80.384 0 0 0 13.448-10.371c.794-.762 1.55-1.53 2.3-2.3a82.049 82.049 0 0 0 7.93-9.379 63.424 63.424 0 0 0 6.27-10.765 48.616 48.616 0 0 0 4.358-16.398c1.483-19.391-9.967-38.675-35.622-54.227L198.557 0 78.297 115.227 0 190.247l108.601 65.909a111.605 111.605 0 0 0 57.762 16.415c24.922 0 48.801-8.803 66.419-25.686 19.158-18.362 25.52-42.128 13.697-61.872a49.009 49.009 0 0 0-6.799-8.868 89.326 89.326 0 0 0 19.286 2.143c.052 0 .101.004.151.004a85.012 85.012 0 0 0 30.97-5.793 80.536 80.536 0 0 0 12.942-6.45Zm-100.584 59.808c-19.32 18.51-50.398 21.236-75.7 5.9l-75.132-45.608 67.444-64.643 76.417 46.386c27.537 16.693 26.017 39.716 6.971 57.965Zm8.934-82.218-70.647-42.888 64.407-61.769 69.37 42.115c25.94 15.724 29.31 37.04 10.55 55.017a60.705 60.705 0 0 1-73.68 7.525Zm29.866 190.04c-19.577 18.757-46.17 29.088-74.882 29.088a123.816 123.816 0 0 1-64.107-18.193L0 282.517v24.677l108.601 65.908a111.605 111.605 0 0 0 57.762 16.415c24.922 0 48.801-8.802 66.419-25.686 12.877-12.342 19.99-27.13 19.68-41.493l-.002-1.791a87.095 87.095 0 0 1-11.215 13.132Zm0-38.983c-19.577 18.756-46.17 29.088-74.882 29.088a123.816 123.816 0 0 1-64.107-18.193L0 243.533v24.68l108.601 65.907a111.606 111.606 0 0 0 57.762 16.416c24.922 0 48.801-8.803 66.419-25.686 12.877-12.344 19.99-27.13 19.68-41.495l-.002-1.79a86.98 86.98 0 0 1-11.215 13.13Zm0-38.981c-19.577 18.756-46.17 29.088-74.882 29.088a123.816 123.816 0 0 1-64.107-18.194L0 204.552v24.677l108.601 65.908a111.606 111.606 0 0 0 57.762 16.416c24.922 0 48.801-8.803 66.419-25.687 12.877-12.341 19.99-27.13 19.68-41.493l-.002-1.823a86.471 86.471 0 0 1-11.215 13.164Zm83.69 25.738a94.137 94.137 0 0 1-60.191 25.856v-.002h-.012l.012 26.667a81.653 81.653 0 0 0 51.733-22.368c13.968-13.385 21.144-28.111 20.985-42.642v-2.197a95.161 95.161 0 0 1-12.527 14.686Zm-83.69 91.208c-19.577 18.756-46.17 29.088-74.882 29.088a123.816 123.816 0 0 1-64.107-18.193L0 321.498v24.677l108.601 65.908a111.605 111.605 0 0 0 57.762 16.416c24.922 0 48.801-8.803 66.419-25.686 12.877-12.342 19.99-27.13 19.68-41.494l-.002-1.789a86.983 86.983 0 0 1-11.215 13.13Zm85.744-210.206c-.678.686-1.345 1.373-2.054 2.052a99.296 99.296 0 0 1-22.23 15.687 94.68 94.68 0 0 1-26.247 8.711 98.087 98.087 0 0 1-14.16 1.567c.505 1.612.903 3.25 1.25 4.902a53.16 53.16 0 0 1 1.138 12.001l.004 9.653h.054a84.27 84.27 0 0 0 25.344-5.547 80.954 80.954 0 0 0 26.389-16.822c.802-.77 1.504-1.558 2.263-2.336a82.049 82.049 0 0 0 7.927-9.38 63.328 63.328 0 0 0 6.283-10.776 48.442 48.442 0 0 0 4.32-16.441c.09-1.236.204-2.474.192-3.708v-2.048q-1.08 1.552-2.257 3.089a97.666 97.666 0 0 1-8.216 9.396Zm-.031 77.92c-.687.695-1.306 1.408-2.023 2.095a94.13 94.13 0 0 1-60.191 25.857v-.002h-.03l.012 26.668h.014l.004.002v-.002a81.653 81.653 0 0 0 51.733-22.369 73.547 73.547 0 0 0 16.473-22.492 48.454 48.454 0 0 0 4.32-16.442c.09-1.238.204-2.473.192-3.71v-2.193c-.744 1.075-1.465 2.154-2.273 3.217a97.104 97.104 0 0 1-8.231 9.372Zm0-38.98c-.687.694-1.304 1.406-2.023 2.093a97.185 97.185 0 0 1-22.25 15.675 95.669 95.669 0 0 1-37.941 10.18h-.048l.012 26.668h.03l.006.002v-.002a81.65 81.65 0 0 0 51.733-22.37c.802-.77 1.504-1.559 2.263-2.337a82.053 82.053 0 0 0 7.927-9.38 63.33 63.33 0 0 0 6.283-10.775 48.442 48.442 0 0 0 4.32-16.442c.09-1.236.204-2.474.192-3.708v-2.193c-.744 1.075-1.465 2.153-2.273 3.216a97.337 97.337 0 0 1-8.231 9.372Z"
style={{
fill: '#7df3e1',
}}
/>
</svg>
);
default:
return null;
}

View File

@ -40,6 +40,7 @@ export enum RepositoryKind {
Gatekeeper,
Kyverno,
KnativeClientPlugin,
Backstage,
}
export interface SearchResults {