Skip to content

Commit

Permalink
Update catalog sub-commands
Browse files Browse the repository at this point in the history
- Update short and long description to make sense
- Add support for catalog-name and resources-tarball-name in generate-from/externals

Signed-off-by: Vincent Demeester <[email protected]>
  • Loading branch information
vdemeester committed Feb 8, 2024
1 parent e859e68 commit 5a61df6
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 55 deletions.
76 changes: 76 additions & 0 deletions docs/catalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
`catalog.yaml`

# Abstract

Describes what the file `catalog.yaml` contains and the use-cases indented for this **contract**. The file will be placed on the root of a CVS repository containing Tekton Pipeline resources (Tasks and Pipelines).

The `catalog.yaml` goal is to serve as a blueprint to find the resources managed on the respective repository, as well to provide information for software supply chain attestation, and describe continuous integration test-cases.

During the release of these repositories the `catalog.yaml` is added to the payload in order to describe the Tekton resource artifacts.

# Use-Cases

The file described on this document is meant to make possible the use-cases described below.

## Repository Root

The primary location for the `catalog.yaml` file is on the root of the (Git?) repository, describing all the elements, providing software supply chain attestation data and as well descring test cases.

For repositories containing the direct YAML payload of Tekton resource files stored, the file will also contain `.catalog.resources` entries, reflecting the location of the data.

### Release Artifacts

The `catalog.yaml` should be present on the repositories release payload, therefore when the maintainers decide to release a new version, the `catalog.yaml` is able to overwrite the entries on `.catalog.resources`.

This ability makes possible to template Tekton resources instead of the plain YAML files, and during the regular releases the resource are assembled.

## Continuous Integration

# `catalog.{yml,yaml}`

The file looks like the example below.

```yml
---
version: v1

catalog:
repository:
description: Tekton Task to interact with Git repositories
attestation:
publicKey: path/to/public.key
annotations:
team: tekton-ecosystem
resources:
tasks:
- name: task-git
version: "0.0.1"
filename: path/to/resource.yaml
sha256sum: resource-sha256-checksum
tri: git://openshift-pipelines/[email protected]
bundle: ghcr.io/openshift-pipelines/task-git:0.0.1-bundle
signature: path/to/signature.sig
pipelines: []
```
The support for the contract file is based on the `version` attribute, as this project moves forward we might change the attributes and the contract version marks breaking changes.

## Repository Metadata (`.catalog.repository`)

Attributes under `.catalog.repository` are meant to describe the repository containing Tekton resources, the `.description` should share a broad view of what the repository contains, what the user will find using the repository contents.

## Supply Chain Attestation (`.catalog.attestation`)

For the software supply chain security, the `.catalog.attestation` hols the elements needed to verify the authors signature. Initially it will contain the public key, either as a direct string or a file, and annotations for the verification processes.

## Tekton Pipeline Resources (`.catalog.resources`)

Under the `.catalog.resources` a inventory of all Tekton resources is recorded, all `.tasks` and `.pipelines` on the respective repository, or release payload, must be described here.

Each entry contains the following:

- `.name`: resource name, the Task's name or Pipeline's name
- `.version` (optional): the resource version, by default the repository's revision takes place
- `.filename`: relative path to the YAML resource file
- `.bundle` (optional): shows the respective OCI bundle image name, where the current resource is stored
- `.signature` (optional): relative path to the signature file, when empty it should search for the respective filename followed by the ".sig" extension, or the signature payload itself directly
11 changes: 9 additions & 2 deletions internal/cmd/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ import (
"github.com/spf13/cobra"
)

const catalogLongDescription = `# catalog-cd catalog
Group of commands to manage a catalog, from generating a full or partial catalog to generate a
GitHub Action matrix strategy compatible json.
`

func CatalogCmd(cfg *config.Config) *cobra.Command {
catalogCmd := &cobra.Command{
Use: "catalog",
Long: `Catalog management commands.`,
Use: "catalog",
Short: `Catalog management commands.`,
Long: catalogLongDescription,
}

catalogCmd.AddCommand(runner.NewRunner(cfg, NewCatalogGenerateCmd()).Cmd())
Expand Down
26 changes: 16 additions & 10 deletions internal/cmd/externals.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ var _ runner.SubCommand = &ExternalsCmd{}

const externalsLongDescription = `# catalog-cd externals
TODO
Generate a GitHub matrix strategy-compatible json from an externals.yaml file.
$ catalog-cd catalog externals --config=./externals.yaml
`

// Cmd exposes the cobra command instance.
Expand Down Expand Up @@ -58,10 +60,12 @@ func (v *ExternalsCmd) Validate() error {
}

type GitHubRunObject struct {
Name string `json:"name"`
URL string `json:"url"`
Type string `json:"type"`
IgnoreVersions string `json:"ignoreVersions"`
Name string `json:"name"`
URL string `json:"url"`
Type string `json:"type"`
IgnoreVersions string `json:"ignoreVersions"`
CatalogName string `json:"catalog-name"`
ResourcesTarballName string `json:"resources-tarball-name"`
}

type GitHubMatrixObject struct {
Expand Down Expand Up @@ -90,10 +94,12 @@ func (v *ExternalsCmd) Run(cfg *config.Config) error {
name = path.Base(repository.URL)
}
o := GitHubRunObject{
Name: name,
URL: repository.URL,
Type: t,
IgnoreVersions: ignoreVersions,
Name: name,
URL: repository.URL,
Type: t,
IgnoreVersions: ignoreVersions,
CatalogName: repository.CatalogName,
ResourcesTarballName: repository.ResourcesTarballName,
}
m.Include = append(m.Include, o)
}
Expand All @@ -113,7 +119,7 @@ func NewCatalogExternalsCmd() runner.SubCommand {
Use: "externals",
Args: cobra.ExactArgs(0),
Long: externalsLongDescription,
Short: "Verifies the resource file signature",
Short: "Generate a GitHub matrix strategy-compatible json from an externals.yaml file.",
SilenceUsage: true,
},
}
Expand Down
36 changes: 22 additions & 14 deletions internal/cmd/generate-from.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,33 @@ import (
"github.com/cli/go-gh/v2/pkg/api"
"github.com/openshift-pipelines/catalog-cd/internal/catalog"
"github.com/openshift-pipelines/catalog-cd/internal/config"
"github.com/openshift-pipelines/catalog-cd/internal/contract"
fc "github.com/openshift-pipelines/catalog-cd/internal/fetcher/config"
"github.com/openshift-pipelines/catalog-cd/internal/runner"
"github.com/spf13/cobra"
)

// GenerateFromExternalCmd represents the "generate" subcommand to generate the signature of a resource file.
type GenerateFromExternalCmd struct {
cmd *cobra.Command // cobra command definition
name string // name of the repository to pull (a bit useless)
url string // url of the repository to pull
resourceType string // type of resource to pull
ignoreVersions string // versions to ignore while pulling
target string // path to the folder where we want to generate the catalog
cmd *cobra.Command // cobra command definition
name string // name of the repository to pull (a bit useless)
url string // url of the repository to pull
resourceType string // type of resource to pull
ignoreVersions string // versions to ignore while pulling
target string // path to the folder where we want to generate the catalog
catalogName string // name of the contract file to pull (default catalog.yaml)
resourceTarballName string // name of the resources file to pull (default resources.tar.gz)
}

var _ runner.SubCommand = &GenerateFromExternalCmd{}

const generateLongFromExternalDescription = `# catalog-cd generate
const generateLongFromExternalDescription = `# catalog-cd generate-partial
Generates a file-based catalog in the target folder, based of a configuration file.
Generates a partial file-based catalog in the target folder, based of a set of flags.
$ catalog-cd generate \
--config="/path/to/external.yaml" \
$ catalog-cd generate-from \
--name="foo" --url="https://github.com/openshift-pipelines/task-containers" \
--type="tasks" \
/path/to/catalog/target
`

Expand Down Expand Up @@ -80,9 +84,11 @@ func (v *GenerateFromExternalCmd) Run(cfg *config.Config) error {

e := fc.External{
Repositories: []fc.Repository{{
Name: name,
URL: v.url,
IgnoreVersions: ignoreVersions,
Name: name,
URL: v.url,
IgnoreVersions: ignoreVersions,
CatalogName: v.catalogName,
ResourcesTarballName: v.resourceTarballName,
}},
}
c, err := catalog.FetchFromExternals(e, ghclient)
Expand All @@ -100,7 +106,7 @@ func NewCatalogGenerateFromExternalCmd() runner.SubCommand {
Use: "generate-from",
Args: cobra.ExactArgs(1),
Long: generateLongFromExternalDescription,
Short: "Verifies the resource file signature",
Short: "Generates a partial file-based catalog in the target folder, based of a set of flags.",
SilenceUsage: true,
},
}
Expand All @@ -110,6 +116,8 @@ func NewCatalogGenerateFromExternalCmd() runner.SubCommand {
f.StringVar(&v.url, "url", "", "url of the repository to pull")
f.StringVar(&v.resourceType, "type", "", "type of resource to pull")
f.StringVar(&v.ignoreVersions, "ignore-versions", "", "versions to ignore while pulling")
f.StringVar(&v.catalogName, "catalog-name", contract.Filename, "contract name to pull")
f.StringVar(&v.resourceTarballName, "resource-tarball-name", contract.ResourcesName, "resource file to pull")

return v
}
2 changes: 1 addition & 1 deletion internal/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func NewCatalogGenerateCmd() runner.SubCommand {
Use: "generate",
Args: cobra.ExactArgs(1),
Long: generateLongDescription,
Short: "Verifies the resource file signature",
Short: "Generates a file-based catalog in the target folder, based of a configuration file.",
SilenceUsage: true,
},
}
Expand Down
2 changes: 1 addition & 1 deletion internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var Version string
func NewRootCmd(stream *tkncli.Stream) *cobra.Command {
rootCmd := &cobra.Command{
Use: "catalog-cd",
Long: `TODO`,
Long: `The catalog-cd is the tool(kit) to manage a catalog repository as well as helping Tekton resources (Task, Pipeline, …) authors management in external repostiories.`,
}

cfg := config.NewConfigWithFlags(stream, rootCmd.PersistentFlags())
Expand Down
27 changes: 0 additions & 27 deletions internal/contract/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"os"
"path"

"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
"gopkg.in/yaml.v3"
)

Expand All @@ -30,34 +29,12 @@ type Repository struct {
Description string `json:"description"`
}

// ResourceProbe describes a single test-case for a Tekton resource managed by the
// repository, serves as inputs for "catalog-cd probe".
type ResourceProbe struct {
// Name testa-case unique name.
Name string `json:"name"`
// ResourceName the name of the Tekton resource, present on ".catalog.resources".
ResourceName string `json:"resourceName"`
// Workspaces slice of Tekton workspace-bindings for the test-case.
Workspaces []v1beta1.WorkspaceBinding `json:"workspaces"`
// Params slice of Tekton Params for the test-case
Params []v1beta1.Param `json:"params"`
}

// Probe contains all the test-cases for the Tekton resources managed by the repository.
type Probe struct {
// Tasks Tekton Tasks tests.
Tasks []ResourceProbe `json:"tasks"`
// Pipelines Tekton Pipelines tests.
Pipelines []ResourceProbe `json:"pipelines"`
}

// Catalog describes the contents of a repository part of a "catalog" of Tekton resources,
// including repository metadata, inventory of Tekton resources, test-cases and more.
type Catalog struct {
Repository *Repository `json:"repository"` // repository long description
Attestation *Attestation `json:"attestation"` // software supply provenance
Resources *Resources `json:"resources"` // inventory of Tekton resources
Probe *Probe `json:"probe"` // test-cases for the managed resources
}

// Contract contains a versioned catalog.
Expand Down Expand Up @@ -106,10 +83,6 @@ func NewContractEmpty() *Contract {
Tasks: []*TektonResource{},
Pipelines: []*TektonResource{},
},
Probe: &Probe{
Tasks: []ResourceProbe{},
Pipelines: []ResourceProbe{},
},
},
}
}
Expand Down

0 comments on commit 5a61df6

Please sign in to comment.