Add support for Tekton StepActions (#3745)

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 2024-04-03 09:42:24 +02:00 committed by GitHub
parent 65d791479d
commit 503df63a01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 399 additions and 33 deletions

View File

@ -1,3 +1,4 @@
helm-extra-args: --timeout 180s
chart-repos:
- stable=https://charts.helm.sh/stable
validate-maintainers: false

View File

@ -34,7 +34,7 @@ At the moment, the following artifacts kinds are supported *(with plans to suppo
- [Kyverno policies](https://kyverno.io)
- [OLM operators](https://github.com/operator-framework)
- [Open Policy Agent (OPA) policies](https://www.openpolicyagent.org/)
- [Tekton tasks and pipelines](https://tekton.dev/)
- [Tekton tasks, pipelines and stepactions](https://tekton.dev/)
- [Tinkerbell actions](https://tinkerbell.org/)
You can use Artifact Hub to:

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.17.1-0
version: 1.17.1-1
appVersion: 1.17.0
kubeVersion: ">= 1.19.0-0"
home: https://artifacthub.io

View File

@ -1162,7 +1162,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, backstage, argo-template, kubearmor, kcl, headlamp, inspektor-gadget",
"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, argo-template, kubearmor, kcl, headlamp, inspektor-gadget, tekton-stepaction",
"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: argo-template, backstage, coredns, falco, gatekeeper, headlamp, helm, helm-plugin, inspektor-gadget, kcl, keda-scaler, keptn, knative-client-plugin, krew, kubearmor, kubewarden, kyverno, olm, opa, tbaction, tekton-task, tekton-pipeline")
lintCmd.Flags().StringVarP(&opts.kind, "kind", "k", "helm", "repository kind: argo-template, backstage, coredns, falco, gatekeeper, headlamp, helm, helm-plugin, inspektor-gadget, kcl, keda-scaler, keptn, knative-client-plugin, krew, kubearmor, kubewarden, kyverno, olm, opa, tbaction, tekton-task, tekton-pipeline, tekton-stepaction")
lintCmd.Flags().StringVarP(&opts.path, "path", "p", ".", "repository's packages path")
return lintCmd
}
@ -134,7 +134,7 @@ func lint(opts *lintOptions, out *output) error {
report = lintKrew(opts.path)
case hub.OLM:
report = lintOLM(opts.path)
case hub.TektonTask, hub.TektonPipeline:
case hub.TektonTask, hub.TektonPipeline, hub.TektonStepAction:
report = lintTekton(opts.path, kind)
default:
return errors.New("kind not supported yet")
@ -376,9 +376,9 @@ func lintOLM(basePath string) *lintReport {
return report
}
// lintTekton checks if the Tekton tasks or pipelines available in the path
// provided are ready to be processed by the Tekton tracker source and listed
// on Artifact Hub.
// lintTekton checks if the Tekton tasks, pipelines or stepactions available in
// the path provided are ready to be processed by the Tekton tracker source and
// listed on Artifact Hub.
func lintTekton(basePath string, kind hub.RepositoryKind) *lintReport {
report := &lintReport{}
repository := &hub.Repository{

View File

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

View File

@ -564,7 +564,8 @@ select results_eq(
(19, 'KubeArmor policies'),
(20, 'KCL modules'),
(21, 'Headlamp plugins'),
(22, 'Inspektor gadgets')
(22, 'Inspektor gadgets'),
(23, 'Tekton stepactions')
$$,
'Repository kinds should exist'
);

View File

@ -1621,6 +1621,30 @@ paths:
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/tekton-stepaction/{repoName}/{packageName}":
get:
tags:
- Packages
summary: Get package details
description: Get package details
operationId: getTektonStepActionDetails
parameters:
- $ref: "#/components/parameters/RepoNameParam"
- $ref: "#/components/parameters/PackageNameParam"
responses:
"200":
description: ""
content:
application/json:
schema:
$ref: "#/components/schemas/TektonStepActionPackage"
"404":
$ref: "#/components/responses/NotFoundResponse"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/tekton-task/{repoName}/{packageName}":
get:
tags:
@ -2172,6 +2196,30 @@ paths:
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/tekton-stepaction/{repoName}/{packageName}/{version}":
get:
tags:
- Packages
summary: Get package version details
description: Get package version details
operationId: getTektonStepActionVersionDetails
parameters:
- $ref: "#/components/parameters/RepoNameParam"
- $ref: "#/components/parameters/PackageNameParam"
- $ref: "#/components/parameters/VersionParam"
responses:
"200":
description: ""
content:
application/json:
schema:
$ref: "#/components/schemas/TektonStepActionPackage"
"404":
$ref: "#/components/responses/NotFoundResponse"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalServerError"
"/packages/tekton-task/{repoName}/{packageName}/{version}":
get:
tags:
@ -4396,6 +4444,32 @@ components:
type: string
nullable: false
example: darwin/amd64
TektonStepActionPackage:
allOf:
- $ref: "#/components/schemas/Package"
- type: object
properties:
data:
type: object
properties:
pipelines.minVersion:
type: string
example: 2.0.0
manifestRaw:
type: string
additionalProperties:
type: string
example: "apiVersion: tekton.dev/v1beta1"
examples:
type: object
nullable: false
additionalProperties: true
platforms:
type: array
items:
type: string
nullable: false
example: darwin/amd64
TektonTaskPackage:
allOf:
- $ref: "#/components/schemas/Package"
@ -4832,6 +4906,7 @@ components:
* `20` - KCL packages
* `21` - Headlamp plugins
* `22` - Inspektor gadgets
* `23` - Tekton stepactions
RepositoryKindParam:
type: string
enum:
@ -4858,6 +4933,7 @@ components:
- kcl
- headlamp
- inspektor-gadget
- tekton-stepaction
description: |
Repository kind name:
* `helm` - Helm charts
@ -4883,6 +4959,7 @@ components:
* `kcl` - KCL packages
* `headlamp` - Headlamp plugins
* `inspektor-gadget` - Inspektor gadgets
* `tekton-stepaction` - Tekton stepactions
RepositorySummary:
type: object
required:
@ -5425,6 +5502,7 @@ components:
* `20` - KCL packages
* `21` - Headlamp plugins
* `22` - Inspektor gadgets
* `23` - Tekton stepactions
PackageNameParam:
in: path
name: packageName

View File

@ -25,6 +25,7 @@ The following repositories kinds are supported at the moment:
- [OPA policies repositories](https://github.com/artifacthub/hub/blob/master/docs/opa_policies_repositories.md)
- [Tekton pipelines repositories](https://github.com/artifacthub/hub/blob/master/docs/tekton_pipelines_repositories.md)
- [Tekton tasks repositories](https://github.com/artifacthub/hub/blob/master/docs/tekton_tasks_repositories.md)
- [Tekton stepactions repositories](https://github.com/artifacthub/hub/blob/master/docs/tekton_stepactions_repositories.md)
- [Tinkerbell actions repositories](https://github.com/artifacthub/hub/blob/master/docs/tinkerbell_actions_repositories.md)
This guide also contains additional information about the following repositories topics:

View File

@ -18,9 +18,9 @@ Artifact Hub will try to extract the containers images used by Helm charts from
The images used by an OLM operator are extracted from the `containerImage` annotation in the [CSV file metadata section](https://github.com/operator-framework/community-operators/blob/master/docs/packaging-required-fields.md), as well as from the `related images` section in the CSV spec. Most of the OLM operators currently listed in Artifact Hub provide that information already, so security reports for them are already available in Artifact Hub with no extra effort required.
### Tekton tasks and pipelines
### Tekton tasks, pipelines and stepactions
The images used by Tekton tasks and pipelines are extracted from the [`task.step.image`](https://github.com/tektoncd/pipeline/blob/main/docs/tasks.md#running-scripts-within-steps) fields of the resource yaml file. If the `image` value is specified by [`params`](https://github.com/tektoncd/pipeline/blob/main/docs/tasks.md#specifying-parameters), the default value of the params (if provided) is used to run the security report. You can find examples with explanations [here](https://github.com/tektoncd/community/blob/main/teps/0079-tekton-catalog-support-tiers.md#extract-container-images-from-catalogs). Please note that the security reports do not include user-provided container images if the default value of the image `params` are overwritten by `pipelineRun` or `taskRun` at run time.
The images used by Tekton tasks, pipelines and stepactions are extracted from the [`task.step.image`](https://github.com/tektoncd/pipeline/blob/main/docs/tasks.md#running-scripts-within-steps) fields of the resource yaml file. If the `image` value is specified by [`params`](https://github.com/tektoncd/pipeline/blob/main/docs/tasks.md#specifying-parameters), the default value of the params (if provided) is used to run the security report. You can find examples with explanations [here](https://github.com/tektoncd/community/blob/main/teps/0079-tekton-catalog-support-tiers.md#extract-container-images-from-catalogs). Please note that the security reports do not include user-provided container images if the default value of the image `params` are overwritten by `pipelineRun` or `taskRun` at run time.
### CoreDNS plugins, KEDA scalers, Keptn integrations, OPA policies and Tinkerbell actions

View File

@ -0,0 +1,3 @@
## Tekton stepactions repositories
Tekton stepactions repositories are expected to follow the same rules as Tekton tasks repositories. Please see the [Tekton tasks repositories](https://github.com/artifacthub/hub/blob/master/docs/tekton_tasks_repositories.md) documentation for more details.

View File

@ -0,0 +1,6 @@
---
title: "Tekton stepactions"
aliases: [
"/tekton_stepactions_repositories",
]
---

View File

@ -265,7 +265,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|^backstage|^argo-template|^kubearmor|^kcl|^headlamp|^inspektor-gadget$}/{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|^argo-template|^kubearmor|^kcl|^headlamp|^inspektor-gadget|^tekton-stepaction$}/{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)
@ -430,7 +430,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|^backstage|^argo-template|^kubearmor|^kcl|^headlamp|^inspektor-gadget$}/{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|^argo-template|^kubearmor|^kcl|^headlamp|^inspektor-gadget|^tekton-stepaction$}/{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

@ -2177,6 +2177,17 @@ func TestBuildURL(t *testing.T) {
"2.0.0",
baseURL + "/packages/inspektor-gadget/repo1/pkg1/2.0.0",
},
{
&hub.Package{
NormalizedName: "pkg1",
Repository: &hub.Repository{
Kind: hub.TektonStepAction,
Name: "repo1",
},
},
"2.0.0",
baseURL + "/packages/tekton-stepaction/repo1/pkg1/2.0.0",
},
}
for _, tc := range testCases {
tc := tc

View File

@ -115,6 +115,9 @@ const (
// InspektorGadget represents a repository with Inspektor Gadgets.
InspektorGadget RepositoryKind = 22
// TektonStepAction represents a repository with Tekton stepactions.
TektonStepAction RepositoryKind = 23
)
// GetKindName returns the name of the provided repository kind.
@ -166,6 +169,8 @@ func GetKindName(kind RepositoryKind) string {
return "tekton-pipeline"
case TektonTask:
return "tekton-task"
case TektonStepAction:
return "tekton-stepaction"
default:
return ""
}
@ -221,6 +226,8 @@ func GetKindFromName(kind string) (RepositoryKind, error) {
return TektonPipeline, nil
case "tekton-task":
return TektonTask, nil
case "tekton-stepaction":
return TektonStepAction, nil
default:
return -1, errors.New("invalid kind name")
}

View File

@ -101,6 +101,7 @@ var (
hub.TBAction,
hub.TektonPipeline,
hub.TektonTask,
hub.TektonStepAction,
}
)
@ -300,7 +301,8 @@ func (m *Manager) ClaimOwnership(ctx context.Context, repoName, orgName string)
hub.OPA,
hub.TBAction,
hub.TektonPipeline,
hub.TektonTask:
hub.TektonTask,
hub.TektonStepAction:
tmpDir, packagesPath, err := m.rc.CloneRepository(ctx, r)
if err != nil {
return err
@ -480,7 +482,8 @@ func (m *Manager) locateMetadataFile(r *hub.Repository, basePath string) string
hub.OPA,
hub.TBAction,
hub.TektonPipeline,
hub.TektonTask:
hub.TektonTask,
hub.TektonStepAction:
mdFile = filepath.Join(basePath, hub.RepositoryMetadataFile)
}
return mdFile
@ -579,7 +582,7 @@ func (m *Manager) GetRemoteDigest(ctx context.Context, r *hub.Repository) (strin
case GitRepoURLRE.MatchString(r.URL):
// Do not track repo's digest for Tekton repos using git based versioning
if (r.Kind == hub.TektonTask || r.Kind == hub.TektonPipeline) && r.Data != nil {
if (r.Kind == hub.TektonTask || r.Kind == hub.TektonPipeline || r.Kind == hub.TektonStepAction) && r.Data != nil {
var data *hub.TektonData
if err := json.Unmarshal(r.Data, &data); err != nil {
return "", fmt.Errorf("invalid tekton repository data: %w", err)
@ -844,7 +847,8 @@ func (m *Manager) validateURL(r *hub.Repository) error {
hub.OPA,
hub.TBAction,
hub.TektonPipeline,
hub.TektonTask:
hub.TektonTask,
hub.TektonStepAction:
if SchemeIsHTTP(u) && !GitRepoURLRE.MatchString(r.URL) {
return errors.New("invalid url format")
}

View File

@ -129,7 +129,7 @@ func SetupSource(i *hub.TrackerSourceInput) hub.TrackerSource {
hub.OPA,
hub.TBAction:
source = generic.NewTrackerSource(i)
case hub.TektonTask, hub.TektonPipeline:
case hub.TektonTask, hub.TektonPipeline, hub.TektonStepAction:
source = tekton.NewTrackerSource(i)
}
return source

View File

@ -22,6 +22,7 @@ import (
"github.com/go-git/go-git/v5/plumbing"
"github.com/hashicorp/go-multierror"
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
v1alpha "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
pipelinerun "github.com/tektoncd/pipeline/pkg/reconciler/pipelinerun/resources"
taskrun "github.com/tektoncd/pipeline/pkg/reconciler/taskrun/resources"
"sigs.k8s.io/yaml"
@ -278,7 +279,7 @@ func (s *TrackerSource) warn(err error) {
}
// GetManifest reads, parses and validates the package manifest, which can be a
// Tekton task or a pipeline manifest.
// Tekton task, pipeline or stepaction manifest.
func GetManifest(kind hub.RepositoryKind, pkgName, pkgPath string) (interface{}, []byte, error) {
manifestPath := path.Join(pkgPath, pkgName+".yaml")
manifestData, err := os.ReadFile(manifestPath)
@ -291,6 +292,8 @@ func GetManifest(kind hub.RepositoryKind, pkgName, pkgPath string) (interface{},
manifest = &v1.Task{}
case hub.TektonPipeline:
manifest = &v1.Pipeline{}
case hub.TektonStepAction:
manifest = &v1alpha.StepAction{}
}
if err := yaml.Unmarshal(manifestData, &manifest); err != nil {
return nil, nil, err
@ -316,6 +319,10 @@ func validateManifest(manifest interface{}) error {
name = m.Name
version = m.Labels[versionLabelTKey]
description = m.Spec.Description
case *v1alpha.StepAction:
name = m.Name
version = m.Labels[versionLabelTKey]
description = "Tekton StepAction" // TODO: description missing in v1alpha.StepAction
}
// Validate manifest data
@ -335,7 +342,7 @@ func validateManifest(manifest interface{}) error {
}
// PreparePackageInput represents the information required to prepare a package
// of Tekton task and pipelines kinds.
// of Tekton task, pipeline and stepaction kinds.
type PreparePackageInput struct {
R *hub.Repository
Tag string
@ -388,6 +395,16 @@ func PreparePackage(i *PreparePackageInput) (*hub.Package, error) {
"run_after": mts.RunAfter,
})
}
case *v1alpha.StepAction:
tektonKind = "stepaction"
name = m.Name
version = m.Labels[versionLabelTKey]
descriptionPrefix := m.Annotations[displayNameTKey]
if descriptionPrefix == "" {
descriptionPrefix = name
}
description = fmt.Sprintf("%s StepAction", descriptionPrefix)
annotations = m.Annotations
}
// Prepare version

View File

@ -271,4 +271,97 @@ func TestTrackerSource(t *testing.T) {
assert.NoError(t, err)
sw.AssertExpectations(t)
})
t.Run("one package returned (tekton-stepaction), no errors", func(t *testing.T) {
t.Parallel()
// Setup services and expectations
sw := source.NewTestsServicesWrapper()
i := &hub.TrackerSourceInput{
Repository: &hub.Repository{
Kind: hub.TektonStepAction,
URL: "https://github.com/user/repo/path",
Data: json.RawMessage(fmt.Sprintf(`{"versioning": "%s"}`, hub.TektonDirBasedVersioning)),
},
BasePath: "testdata/path5",
Svc: sw.Svc,
}
// Run test and check expectations
manifestRaw, _ := os.ReadFile("testdata/path5/stepaction1/0.1/stepaction1.yaml")
var tasks []map[string]interface{}
p := &hub.Package{
Name: "stepaction1",
DisplayName: "StepAction 1",
Description: "StepAction 1 StepAction",
Keywords: []string{"tekton", "stepaction", "tag1", "tag2"},
Readme: "This is just a test stepaction\n",
Version: "0.1.0",
Provider: "Some organization",
ContentURL: "https://github.com/user/repo/raw/master/path/stepaction1/0.1/stepaction1.yaml",
Digest: "530682380f55de185372b1f2c776c0ef82b75273e33f9af34fa0279a9fb8ee0f",
Repository: i.Repository,
License: "Apache-2.0",
Links: []*hub.Link{
{
Name: "source",
URL: "https://github.com/user/repo/blob/master/path/stepaction1/0.1/stepaction1.yaml",
},
{
Name: "link1",
URL: "https://link1.url",
},
{
Name: "link2",
URL: "https://link2.url",
},
},
Maintainers: []*hub.Maintainer{
{
Name: "user1",
Email: "user1@email.com",
},
{
Name: "user2",
Email: "user2@email.com",
},
},
Changes: []*hub.Change{
{
Description: "Added cool feature",
},
{
Description: "Fixed minor bug",
},
},
Recommendations: []*hub.Recommendation{
{
URL: "https://artifacthub.io/packages/helm/artifact-hub/artifact-hub",
},
},
Screenshots: []*hub.Screenshot{
{
Title: "Screenshot 1",
URL: "https://artifacthub.io/screenshot1.jpg",
},
},
Data: map[string]interface{}{
PipelinesMinVersionKey: "0.54.0",
RawManifestKey: string(manifestRaw),
TasksKey: tasks,
PlatformsKey: []string{"linux/amd64", "linux/arm64"},
ExamplesKey: map[string]string{
"sample1.yaml": "sample content\n",
},
},
Signatures: []string{tekton},
Signed: true,
}
packages, err := NewTrackerSource(i).GetPackagesAvailable()
assert.Equal(t, map[string]*hub.Package{
pkg.BuildKey(p): p,
}, packages)
assert.NoError(t, err)
sw.AssertExpectations(t)
})
}

View File

@ -0,0 +1 @@
This is just a test stepaction

View File

@ -0,0 +1 @@
sample content

View File

@ -0,0 +1,37 @@
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: stepaction1
labels:
app.kubernetes.io/version: "0.1.0"
annotations:
artifacthub.io/changes: |
- Added cool feature
- Fixed minor bug
artifacthub.io/license: Apache-2.0
artifacthub.io/links: |
- name: link1
url: https://link1.url
- name: link2
url: https://link2.url
artifacthub.io/maintainers: |
- name: user1
email: user1@email.com
- name: user2
email: user2@email.com
artifacthub.io/provider: Some organization
artifacthub.io/recommendations: |
- url: https://artifacthub.io/packages/helm/artifact-hub/artifact-hub
artifacthub.io/screenshots: |
- title: Screenshot 1
url: https://artifacthub.io/screenshot1.jpg
tekton.dev/pipelines.minVersion: "0.54.0"
tekton.dev/platforms: "linux/amd64,linux/arm64"
tekton.dev/tags: tag1, tag2
tekton.dev/displayName: "StepAction 1"
tekton.dev/signature: "stepaction signature val"
spec:
description: Test stepaction
params:
- name: param1
description: param1 description

View File

@ -203,7 +203,8 @@ func (t *Tracker) cloneRepository() (string, string, error) {
hub.OPA,
hub.TBAction,
hub.TektonPipeline,
hub.TektonTask:
hub.TektonTask,
hub.TektonStepAction:
tmpDir, packagesPath, err = t.svc.Rc.CloneRepository(t.svc.Ctx, t.r)
}

View File

@ -28,6 +28,7 @@ cat docs/www/headers/olm_operators_repositories docs/olm_operators_repositories.
cat docs/www/headers/opa_policies_repositories docs/opa_policies_repositories.md > docs/www/content/topics/repositories/opa-policies.md
cat docs/www/headers/tekton_pipelines_repositories docs/tekton_pipelines_repositories.md > docs/www/content/topics/repositories/tekton-pipelines.md
cat docs/www/headers/tekton_tasks_repositories docs/tekton_tasks_repositories.md > docs/www/content/topics/repositories/tekton-tasks.md
cat docs/www/headers/tekton_stepactions_repositories docs/tekton_stepactions_repositories.md > docs/www/content/topics/repositories/tekton-stepactions.md
cat docs/www/headers/tinkerbell_actions_repositories docs/tinkerbell_actions_repositories.md > docs/www/content/topics/repositories/tinkerbell-actions.md
cat docs/www/headers/security_report docs/security_report.md > docs/www/content/topics/security_report.md
cat docs/www/headers/cli docs/cli.md > docs/www/content/topics/cli.md

View File

@ -45,6 +45,7 @@ const Image = (props: Props) => {
return '/static/media/placeholder_pkg_krew.png';
case RepositoryKind.TektonTask:
case RepositoryKind.TektonPipeline:
case RepositoryKind.TektonStepAction:
return '/static/media/placeholder_pkg_tekton-task.png';
case RepositoryKind.KedaScaler:
return '/static/media/placeholder_pkg_keda-scaler.png';

View File

@ -142,6 +142,13 @@ describe('RepositoryIcon', () => {
expect(icon).toHaveProperty('src', 'http://localhost/static/media/inspektor-gadget-light.svg');
});
it('renders Tekton StepAction icon', () => {
render(<RepositoryIcon kind={RepositoryKind.TektonStepAction} type="white" />);
const icon = screen.getByAltText('Icon');
expect(icon).toBeInTheDocument();
expect(icon).toHaveProperty('src', 'http://localhost/static/media/tekton-pkg-light.svg');
});
it('renders empty icon', () => {
render(<RepositoryIcon kind={101 as RepositoryKind} type="white" />);
expect(() => screen.getByAltText('Icon')).toThrow();

View File

@ -101,6 +101,10 @@ const ICONS = {
default: '/static/media/inspektor-gadget.svg',
white: '/static/media/inspektor-gadget-light.svg',
},
[RepositoryKind.TektonStepAction]: {
default: '/static/media/tekton-pkg.svg',
white: '/static/media/tekton-pkg-light.svg',
},
};
const RepositoryIcon = (props: Props) => {

View File

@ -30,6 +30,7 @@ const Signed = (props: Props) => {
RepositoryKind.Kubewarden,
RepositoryKind.TektonPipeline,
RepositoryKind.TektonTask,
RepositoryKind.TektonStepAction,
].includes(props.repoKind);
return (

View File

@ -191,7 +191,11 @@ const RepositoryModal = (props: Props) => {
};
}
if ([RepositoryKind.TektonTask, RepositoryKind.TektonPipeline].includes(selectedKind)) {
if (
[RepositoryKind.TektonTask, RepositoryKind.TektonPipeline, RepositoryKind.TektonStepAction].includes(
selectedKind
)
) {
repository.data = {
versioning: versioning,
};
@ -497,6 +501,17 @@ const RepositoryModal = (props: Props) => {
</ExternalLink>
);
break;
case RepositoryKind.TektonStepAction:
link = (
<ExternalLink
href="/docs/topics/repositories/tekton-stepactions"
className="text-primary fw-bold"
label="Open documentation"
>
Tekton stepactions
</ExternalLink>
);
break;
}
if (isUndefined(link)) return;
@ -527,6 +542,7 @@ const RepositoryModal = (props: Props) => {
case RepositoryKind.KCL:
case RepositoryKind.Headlamp:
case RepositoryKind.InspektorGadget:
case RepositoryKind.TektonStepAction:
return (
<>
<p
@ -921,6 +937,7 @@ const RepositoryModal = (props: Props) => {
RepositoryKind.KCL,
RepositoryKind.Headlamp,
RepositoryKind.InspektorGadget,
RepositoryKind.TektonStepAction,
].includes(selectedKind) && (
<div>
<InputField
@ -941,7 +958,9 @@ const RepositoryModal = (props: Props) => {
</div>
)}
{[RepositoryKind.TektonTask, RepositoryKind.TektonPipeline].includes(selectedKind) && (
{[RepositoryKind.TektonTask, RepositoryKind.TektonPipeline, RepositoryKind.TektonStepAction].includes(
selectedKind
) && (
<>
<label className={`form-label fw-bold ${styles.label}`}>Versioning</label>
@ -1068,6 +1087,7 @@ const RepositoryModal = (props: Props) => {
RepositoryKind.KCL,
RepositoryKind.Headlamp,
RepositoryKind.InspektorGadget,
RepositoryKind.TektonStepAction,
].includes(selectedKind) && (
<div className="mt-4 mb-3">
<div className="form-check form-switch ps-0">

View File

@ -164,6 +164,11 @@ exports[`Repository Modal - repositories section creates snapshot 1`] = `
>
Tekton pipelines
</option>
<option
value="23"
>
Tekton stepactions
</option>
<option
value="7"
>

View File

@ -310,7 +310,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, Knative client, Backstage plugins, Argo templates, KubeArmor policies, KCL modules, Headlamp plugins and Inspektor gadgets.
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, pipelines and stepactions, KEDA scalers, CoreDNS plugins, Keptn integrations, container images, Kubewarden policies, Kyverno policies, Knative client, Backstage plugins, Argo templates, KubeArmor policies, KCL modules, Headlamp plugins and Inspektor gadgets.
<div
class="py-0 py-lg-5"
>
@ -820,7 +820,7 @@ exports[`Home index creates snapshot 1`] = `
class="d-none d-sm-block text-light mt-2 legendIcon"
>
<small>
Tekton tasks and pipelines
Tekton packages
</small>
</div>
</div>

View File

@ -230,9 +230,9 @@ const HomeView = () => {
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, Backstage plugins, Argo
templates, KubeArmor policies, KCL modules, Headlamp plugins and Inspektor gadgets.
kubectl plugins, Tekton tasks, pipelines and stepactions, KEDA scalers, CoreDNS plugins, Keptn
integrations, container images, Kubewarden policies, Kyverno policies, Knative client, Backstage
plugins, Argo templates, KubeArmor policies, KCL modules, Headlamp plugins and Inspektor gadgets.
<div className="py-0 py-lg-5">
<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
@ -453,7 +453,7 @@ const HomeView = () => {
<div className="d-flex flex-column justify-content-between align-items-center h-100">
<RepositoryIcon kind={RepositoryKind.TektonTask} type="white" className={styles.aboutIcon} />
<div className={`d-none d-sm-block text-light mt-2 ${styles.legendIcon}`}>
<small>Tekton tasks and pipelines</small>
<small>Tekton packages</small>
</div>
</div>
</ExternalLink>

View File

@ -325,6 +325,7 @@ const Details = (props: Props) => {
);
case RepositoryKind.TektonTask:
case RepositoryKind.TektonStepAction:
return (
<>
{props.package.data && props.package.data.pipelinesMinVersion && (

View File

@ -13,7 +13,7 @@ interface Props {
}
export const URL_regex =
/^https:\/\/([^\/?]+)\/packages\/(helm|falco|opa|olm|tbaction|krew|helm-plugin|tekton-task|keda-scaler|coredns|keptn|tekton-pipeline|kubewarden|gatekeeper|kyverno|knative-client-plugin|backstage|argo-template|kubearmor|inspektor-gadget|container)\/([a-z0-9-]+)\/([a-z0-9-]+)$/; // eslint-disable-line
/^https:\/\/([^\/?]+)\/packages\/(helm|falco|opa|olm|tbaction|krew|helm-plugin|tekton-task|keda-scaler|coredns|keptn|tekton-pipeline|kubewarden|gatekeeper|kyverno|knative-client-plugin|backstage|argo-template|kubearmor|inspektor-gadget|tekton-stepaction|container)\/([a-z0-9-]+)\/([a-z0-9-]+)$/; // eslint-disable-line
const prepareRecommendations = (recommendations?: Recommendation[]): RecommendedPackage[] => {
let list: RecommendedPackage[] = [];

View File

@ -1086,6 +1086,7 @@ const PackageView = () => {
switch (detail.repository.kind) {
case RepositoryKind.TektonTask:
case RepositoryKind.TektonPipeline:
case RepositoryKind.TektonStepAction:
return (
<>
<div className="d-none d-lg-block">

View File

@ -11,10 +11,28 @@ interface Props {
}
const TektonInstall = (props: Props) => {
const type = props.repository.kind === RepositoryKind.TektonPipeline ? 'pipeline' : 'task';
let type: string = 'task';
switch (props.repository.kind) {
case RepositoryKind.TektonPipeline:
type = 'pipeline';
break;
case RepositoryKind.TektonStepAction:
type = 'stepaction';
break;
}
let url = props.contentUrl;
if (isUndefined(url) || url === '') {
url = type === 'pipeline' ? 'PIPELINE_RAW_YAML_URL' : 'TASK_RAW_YAML_URL';
switch (props.repository.kind) {
case RepositoryKind.TektonPipeline:
url = 'PIPELINE_RAW_YAML_URL';
break;
case RepositoryKind.TektonStepAction:
url = 'STEPACTION_RAW_YAML_URL';
break;
case RepositoryKind.TektonTask:
url = 'TASK_RAW_YAML_URL';
break;
}
}
return (

View File

@ -24,6 +24,7 @@ export enum RepositoryKind {
KCL,
Headlamp,
InspektorGadget,
TektonStepAction,
}
export enum PackageCategory {

View File

@ -276,6 +276,15 @@ export const REPOSITORY_KINDS: RepoKindDef[] = [
icon: <RepositoryIcon kind={RepositoryKind.TektonPipeline} className="mw-100 mh-100" />,
active: true,
},
{
kind: RepositoryKind.TektonStepAction,
label: 'tekton-stepaction',
name: 'Tekton stepactions',
singular: 'Tekton stepaction',
plural: 'Tekton stepactions',
icon: <RepositoryIcon kind={RepositoryKind.TektonStepAction} className="mw-100 mh-100" />,
active: true,
},
{
kind: RepositoryKind.TektonTask,
label: 'tekton-task',
@ -795,7 +804,7 @@ 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|backstage|argo-template|kubearmor|kcl|headlamp|inspektor-gadget|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|argo-template|kubearmor|kcl|headlamp|inspektor-gadget|tekton-stepaction|container)\//;
export const HOME_ROUTES = [
'/verify-email',

View File

@ -260,6 +260,7 @@ const getInstallMethods = (props: PackageInfo): InstallMethodOutput => {
break;
case RepositoryKind.TektonTask:
case RepositoryKind.TektonPipeline:
case RepositoryKind.TektonStepAction:
if (isUndefined(pkg.install)) {
output.methods.push({
label: 'kubectl',

View File

@ -79,6 +79,10 @@ describe('repoKind', () => {
expect(methods.getRepoKind('inspektor-gadget')).toBe(RepositoryKind.InspektorGadget);
});
it('tekton-stepaction', () => {
expect(methods.getRepoKind('tekton-stepaction')).toBe(RepositoryKind.TektonStepAction);
});
it('unknown', () => {
expect(methods.getRepoKind('unknown')).toBeNull();
});
@ -161,6 +165,10 @@ describe('repoKind', () => {
expect(methods.getRepoKindName(RepositoryKind.InspektorGadget)).toBe('inspektor-gadget');
});
it('tekton-stepaction kind', () => {
expect(methods.getRepoKindName(RepositoryKind.TektonStepAction)).toBe('tekton-stepaction');
});
it('unknown kind', () => {
expect(methods.getRepoKindName(50 as RepositoryKind)).toBeNull();
});

View File

@ -48,6 +48,8 @@ const getRepoKind = (repoName: string): RepositoryKind | null => {
return RepositoryKind.Headlamp;
case 'inspektor-gadget':
return RepositoryKind.InspektorGadget;
case 'tekton-stepaction':
return RepositoryKind.TektonStepAction;
default:
return null;
}
@ -101,6 +103,8 @@ const getRepoKindName = (repoKind: RepositoryKind): string | null => {
return 'headlamp';
case RepositoryKind.InspektorGadget:
return 'inspektor-gadget';
case RepositoryKind.TektonStepAction:
return 'tekton-stepaction';
default:
return null;
}

View File

@ -11,6 +11,7 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div class="artifacthub-widget-group" data-url="http://localhost:8000/packages/search?user=cynthia-sg&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?kind=22&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?kind=21&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?kind=21&sort=relevance&page=1" data-theme="dark" data-header="false" data-stars="true" data-color="#417598" data-responsive="true" data-loading="true"></div>

View File

@ -95,6 +95,8 @@ const getRepoKindName = (repoKind: RepositoryKind): string | null => {
return 'headlamp';
case RepositoryKind.InspektorGadget:
return 'inspektor-gadget';
case RepositoryKind.TektonStepAction:
return 'tekton-stepaction';
default:
return null;
}

View File

@ -172,6 +172,13 @@ describe('Image', () => {
expect(image).toHaveProperty('src', 'https://localhost:8000/static/media/placeholder_pkg_inspektor-gadget.png');
});
it('renders Tekton stepaction icon', () => {
render(<Image {...defaultProps} kind={RepositoryKind.TektonStepAction} />);
const image = screen.getByAltText('alt image');
expect(image).toBeInTheDocument();
expect(image).toHaveProperty('src', 'https://localhost:8000/static/media/placeholder_pkg_tekton-task.png');
});
it('renders placeholder icon', () => {
render(<Image {...defaultProps} placeholderIcon={<>icon</>} />);
expect(screen.getByText('icon')).toBeInTheDocument();

View File

@ -46,6 +46,7 @@ const Image = (props: Props) => {
return '/static/media/placeholder_pkg_krew.png';
case RepositoryKind.TektonTask:
case RepositoryKind.TektonPipeline:
case RepositoryKind.TektonStepAction:
return '/static/media/placeholder_pkg_tekton-task.png';
case RepositoryKind.KedaScaler:
return '/static/media/placeholder_pkg_keda-scaler.png';

View File

@ -35,6 +35,7 @@ const ICONS: IconsList = {
[RepositoryKind.KCL]: <SVGIcons name="kcl" />,
[RepositoryKind.Headlamp]: <SVGIcons name="headlamp" />,
[RepositoryKind.InspektorGadget]: <SVGIcons name="inspektor-gadget" />,
[RepositoryKind.TektonStepAction]: <SVGIcons name="tekton" />,
};
const RepositoryIcon = (props: Props) => (

View File

@ -108,6 +108,10 @@ const REPOSITORY_KINDS: RepoKindDef[] = [
kind: RepositoryKind.InspektorGadget,
name: 'Inspektor Gadget',
},
{
kind: RepositoryKind.TektonStepAction,
name: 'Tekton stepaction',
},
];
const Wrapper = styled('span')`

View File

@ -50,6 +50,7 @@ export enum RepositoryKind {
KCL,
Headlamp,
InspektorGadget,
TektonStepAction,
}
export interface SearchResults {