Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADR 43: add the Artifact construction ADR #212

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions ADR/0043-artifact-constructors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# 43. Creating Artifacts from Snapshots for testing and release

Date: 2024-10-21

## Status

Proposed

## Authors

- Krunoslav Pavic
- Andrew McNamara

## Context

This ADR aims to cover the proposed functionality for creating additional Artifacts as part of the Konflux build/test/release process.
These artifacts would vary in type and would cover use cases where either the single built image or entire sets of images
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Will it support non image artifacts, like rpm?
  2. Could you give an example of an artifact that consist of several images? Or you mean a set of images that logically create a single unit (artifact), like k8s operator + bundle?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Yes, it can be rpms or binaries or any other kind of artifact that can be stored somewhere and released.
  2. Exactly, an operator bundle is a good example, or an fbc fragment - these rely on information (mainly images) from multiple components in order to be generated.

from the user's application are needed to generate one or more artifacts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will it allow releasing a few artifacts at once? E.g. I build a few binaries in build pipeline and release them into dedicated location for each?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think releasing more than artifact at the same time should be supported. We are not delving too deep in the Release process here, but I would like to hear from @davidmogar or @johnbieren about their opinions on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I am really following, but isn't this what we already do? We let you say where to release each container image


Some limitations with our current approach that can be mitigated with this ADR:
* The ability to produce multiple artifacts with a single PipelineRun
* Reduced need for in-PR nudging (one of the common use cases for this is the operator bundle builds as mentioned below)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you aiming at replacing nudging completely or just for in-PR testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that nudging for operator bundle builds could potentially be replaced completely, but I don't think that nudging between images in general (e.g. base image -> images that are based on it) would be replaced.



## Use Cases in Detail

* A team produces operands and operators. When integration service creates a Snapshot, it uses a constructor that
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the constructor? Is it a pipeline or operator or ...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the ArtifactConstructor CR that's described in the lower text. Maybe these use cases should go below that section and then reference the CR directly that way?

actually builds a bundle. When releasing, the team releases that single bundle artifact. That constructor also has an extract
operation to list all related images that are referenced, and that extraction generates the list for release service to operate on
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly, that all related images will be released too when releasing the bundle artifact?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I believe that it would be possible to set up the release logic to release the bundle alongside the related images.

* A team produces a set of images with ko. The build task generates/pushes all images with ko and then produces a "build artifact"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using build task here is confusing. You didn't mean build task of the build pipeline, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, maybe calling it an artifact generation task would be more clear.

OCI manifest which includes an immutable reference to each of the ko-built artifacts. When integration service creates a Snapshot,
it uses a constructor that doesn't need to create a new artifact. When releasing, the team releases that single artifact.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm totally confused here. you say that constructor that doesn't need to create a new artifact and then team releases that single artifact. How is it possible when I have several artifacts (images, rpms, bundles, etc.) produced by build pipeline(s)?

The constructor also has an extract operation to list all the ko-built artifacts and that extraction generates the list for release service to operate on.
* A team produces a set of images that are just a group of artifacts that should be released together.
The artifacts are built via separate PipelineRuns. When integration service creates a Snapshot, it uses a constructor
that saves the Snapshot CR as an OCI blob. When releasing, the team releases that single artifact.
The constructor also has an extract operation to list all artifacts that were in the Snapshot and that extraction
generates the list for release service to operate on.


## Decision

A new API will be introduced which instructs the Integration service to create a Tekton pipeline which will generate the
artifact.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a glossary to avoid confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, will add that to the ADR.

Once built, the artifact reference will be added to the Snapshot's metadata so it can be discovered during testing or release process.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have an artifact that consists of several items (e.g. operator + bundle), why do we need snapshots?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The information within the Snapshot (list of images, git references etc.) are used to construct these further artifacts. A single artifact also doesn't need to use all components from the Snapshot, so I think it's valuable to retain the Snapshot as the single point of truth about the whole state of the user's list of components (or Application in current terms).

Additionally, the integration service will wait for the artifact constructor to finish before starting the integration testing pipelines
in order to enable users to run tests using the new artifacts.

### The ArtifactConstructor API

The proposal here is to introduce the new ArtifactConstructor API which will define Tekton pipelines that will generate individual artifacts.
These pipelines would be executed after a Snapshot is generated and before the integration test pipelines start.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm again totally confused. Above you say Once built, the artifact reference will be added to the Snapshot's metadata and now you say API which will define Tekton pipelines that will generate individual artifacts. These pipelines would be executed after a Snapshot is generated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we may need a diagram here for the proposed workflow:

  1. The Snapshot gets created (in response to a build pipeline or manually etc.)
  2. The Artifact generation pipelineRuns are started and generate artifacts based on the information in the Snapshot
  3. References to the generated artifacts will be added to the Snapshot's metadata (annotations) to provide a central place where we can find all generated artifacts and testing information.


When each artifact generation pipelineRun is completed, the reference to the artifact is extracted and added to the original Snapshot.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the artifact you mean "artifact of artifacts"?

After that, the integration testing pipelines castart, and since the artifacts are referenced by the Snapshot,
it is possible to fetch them and run tests on them.

```yaml
apiVersion: appstudio.redhat.com/v2alpha1
kind: ArtifactConstructor
metadata:
name: example--artifact-constructor
spec:
selectors:
- expression: ‘metadata.labels["konflux-ci.dev/application"] == "integration-service" && metadata.annotations["test.pac.appstudio.openshift.io/event-type"] == "pull_request"’
description: “Selects only PR Snapshots associated with integration-service”
params:
- name: source
value: https://github.com/konflux-ci/integration-service
resolverRef:
resolver: git
params:
- name: url
value: https://github.com/konflux-ci/integration-examples
- name: revision
value: main
- name: pathInRepo
value: pipelines/bundle_generator_pipeline.yaml
extractors:
- ref: 'status.results.filter(result,result.name == "IMAGE_URL")[0].value'
name: ‘metadata.labels["appstudio.openshift.io/component"]’

```

Don't take the fields literally. The details will likely change after the ADR has settled. It is
here for illustration purposes.

The `selector` field will be used to identify resources that should trigger the construction of new Artifacts. This will be done using CEL expressions.

The `resolverRef` resource will be used to define the Tekton pipeline definition which can be used to run the artifact pipelineRun.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean PipelineRun that creates an artifact?


The `extractor` resource will use CEL expressions to extract the individual field values from the artifact pipelineRun.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the pipeline just define result(s) with the reference to the produced by the pipelinerun artifact?

The individual artifacts are expected to use a reference that can be used to fetch it, like an image pullSpec or similar URL.
Since the `extractor` resource is a list, it can take multiple extractor entries if the artifact pipeline is expected to provide multiple artifacts.
Each extracted resource will be added to the Snapshot's metadata.

## Consequences

- [integration-service] now executes additional Tekton pipelineRuns which are expected to generate artifacts which
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that individual artifacts (e.g. image or bundle or ...) should be generated by the build pipeline. It does make sense to group individual (let's call "atomic") artifacts produced by build pipeline into a group and the release it as a single unit. But the group of atomic artifacts create an artifact to release which seen somewhat the same as snapshot.

can then be associated with the Snapshot.
- [integration-service] waits for the artifact pipelineRuns to finish before starting the integration testing pipelines
for a given Snapshot.
- this will have implications for the [release service] as it will further remove coupling around an Application and an Application Snapshot
- Potential decrease of a reliance on an Application, which will have implications on [build-service] and the Konflux UI
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build Service does not rely on Application, main resource is a Component. From Build Service point of view, we can delete Application CR even today.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I think that a better term would be the Application/Component model.