Skip to content
Merged
Show file tree
Hide file tree
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
18 changes: 10 additions & 8 deletions api/v1beta2/componentgroup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ type ComponentGroupSpec struct {
// +required
Comment thread
14rcole marked this conversation as resolved.
Components []ComponentReference `json:"components"`

// Dependents is a list of ComponentGroup names that are dependent on this ComponentGroup.
// When a snapshot is created for this ComponentGroup, snapshots will also be created for all dependents.
// +optional
Dependents []string `json:"dependents,omitempty"`

// TestGraph describes the desired order in which tests associated with the ComponentGroup should be executed.
Comment thread
14rcole marked this conversation as resolved.
Comment thread
14rcole marked this conversation as resolved.
Comment thread
14rcole marked this conversation as resolved.
Comment thread
14rcole marked this conversation as resolved.
Comment thread
14rcole marked this conversation as resolved.
Comment thread
14rcole marked this conversation as resolved.
// If not specified, all tests will run in parallel.
// The map key is the test scenario name, and the value is a list of parent test scenarios it depends on.
Expand All @@ -58,17 +53,24 @@ type ComponentGroupSpec struct {
SnapshotCreator *SnapshotCreatorSpec `json:"snapshotCreator,omitempty"`
}

// ComponentReference references a Component and its specific branch/version
// ComponentReference references a Component or ComponentGroup and its specific branch/version
type ComponentReference struct {
// Name is the name of the Component
// Name is the name of the Component or ComponentGroup
// +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
// +required
Name string `json:"name"`

// Kind is the type of resource being referenced
Comment thread
14rcole marked this conversation as resolved.
// Must be 'component' or 'componentGroup', case-insensitive
// +kubebuilder:default:="component"
// +kubebuilder:validation:Pattern=`(?i)^(component|componentGroup)$`
Kind string `json:"kind,omitempty"`

// ComponentVersion references the ComponentVersion for this Component.
// Can only be set if 'Kind' is set to 'Component' or empty
// The ComponentVersion CRD will be implemented by the build team as part of STONEBLD-3604.
// For now, this contains the branch name and GCL (Global Candidate List) information.
Comment thread
14rcole marked this conversation as resolved.
// +required
// +optional
ComponentVersion ComponentVersionReference `json:"componentVersion"`
}

Expand Down
10 changes: 0 additions & 10 deletions api/v1beta2/componentgroup_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ func TestComponentGroupSpec(t *testing.T) {
},
},
},
Dependents: []string{"child-cg-1", "child-cg-2"},
TestGraph: map[string][]TestGraphNode{
"verify": {
{Name: "clamav-scan"},
Expand Down Expand Up @@ -116,10 +115,6 @@ func TestComponentGroupSpec(t *testing.T) {
t.Errorf("Expected second component branch 'components/second-component', got '%s'", cg.Spec.Components[1].ComponentVersion.Name)
}

if len(cg.Spec.Dependents) != 2 {
t.Errorf("Expected 2 dependents, got %d", len(cg.Spec.Dependents))
}

if len(cg.Spec.TestGraph) != 2 {
t.Errorf("Expected 2 test graph entries, got %d", len(cg.Spec.TestGraph))
}
Expand Down Expand Up @@ -192,9 +187,6 @@ func TestComponentGroupMinimalSpec(t *testing.T) {
if cg.Spec.Components[0].ComponentVersion.Revision != "" {
t.Errorf("Expected empty Revision, got '%s'", cg.Spec.Components[0].ComponentVersion.Revision)
}
if len(cg.Spec.Dependents) != 0 {
t.Errorf("Expected 0 dependents, got %d", len(cg.Spec.Dependents))
}
if cg.Spec.TestGraph != nil {
t.Error("Expected nil TestGraph")
}
Expand Down Expand Up @@ -257,7 +249,6 @@ func TestComponentGroupDeepCopy(t *testing.T) {
},
},
},
Dependents: []string{"dependent-1"},
},
}

Expand Down Expand Up @@ -360,7 +351,6 @@ func TestComponentGroupSpecDeepCopy(t *testing.T) {
Components: []ComponentReference{
{Name: "comp-1", ComponentVersion: ComponentVersionReference{Name: "main"}},
},
Dependents: []string{"dep-1"},
TestGraph: map[string][]TestGraphNode{
"test-1": {{Name: "node-1", FailFast: true}},
},
Expand Down
5 changes: 0 additions & 5 deletions api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions config/crd/bases/appstudio.redhat.com_componentgroups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,13 @@ spec:
Components is a list of Components (name and branch) that belong to the ComponentGroup.
This is the source of truth for logical groupings of versioned Components.
items:
description: ComponentReference references a Component and its specific
branch/version
description: ComponentReference references a Component or ComponentGroup
and its specific branch/version
properties:
componentVersion:
description: |-
ComponentVersion references the ComponentVersion for this Component.
Can only be set if 'Kind' is set to 'Component' or empty
The ComponentVersion CRD will be implemented by the build team as part of STONEBLD-3604.
For now, this contains the branch name and GCL (Global Candidate List) information.
properties:
Expand All @@ -82,22 +83,21 @@ spec:
required:
- name
type: object
kind:
default: component
description: |-
Kind is the type of resource being referenced
Must be 'component' or 'componentGroup', case-insensitive
Comment thread
14rcole marked this conversation as resolved.
pattern: (?i)^(component|componentGroup)$
type: string
name:
description: Name is the name of the Component
description: Name is the name of the Component or ComponentGroup
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- componentVersion
- name
type: object
type: array
dependents:
description: |-
Dependents is a list of ComponentGroup names that are dependent on this ComponentGroup.
When a snapshot is created for this ComponentGroup, snapshots will also be created for all dependents.
items:
type: string
type: array
snapshotCreator:
description: |-
SnapshotCreator is an optional field that allows custom logic for Snapshot creation.
Expand Down
7 changes: 3 additions & 4 deletions config/samples/appstudio_v1beta2_componentgroup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,16 @@ spec:
componentVersion:
name: "main"
- name: second-component
kind: component
componentBranch:
name: "v1"
revision: "v1branch"
context: "components/second-component"
- name: python-component
componentBranch:
name: "3.12.4"
Comment thread
14rcole marked this conversation as resolved.
dependents:
# when a snapshot for this ComponentGroup is created,
# the integration service will also create one for child-cg
- child-cg
- name: child-cg
kind: componentGroup
testGraph:
# in this graph clamav-scan, dast-tests, and deployment would run first
# e2e-test would start when clamav-scan finishes
Expand Down
33 changes: 33 additions & 0 deletions gitops/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ const (
// SnapshotAutoReleasedCondition is the condition for marking if Snapshot was auto-released released with AppStudio.
SnapshotAutoReleasedCondition = "AutoReleased"

// ParentSnapshotsCreatedCondition is the condition marking whether snapshots for all parent ComponentGroups for the
// ComponentGroup that the snapshot belongs to have been created
ParentSnapshotsCreatedCondition = "ParentSnapshotsCreated"

// SnapshotAddedToGlobalCandidateListCondition is the condition for marking if Snapshot's component was added to
// the global candidate list.
SnapshotAddedToGlobalCandidateListCondition = "AddedToGlobalCandidateList"
Expand Down Expand Up @@ -328,6 +332,10 @@ const (
GitCommentPolicyAnnotation = "test.appstudio.openshift.io/comment_strategy"
// GitCommentPolicyAllDisabled is the value to disable all test comments for the component got pac repository
GitCommentPolicyAllDisabled = "disable_all"

// ChildSnapshotAnnotation is used in nested snapshots. Denotes the name of the child snapshot whose creation triggered the creation of the snapshot
// on which the annotation is set
ChildSnapshotAnnotation = TestLabelPrefix + "/child-snapshot"
)

var (
Expand Down Expand Up @@ -670,6 +678,31 @@ func MarkSnapshotAsAutoReleased(ctx context.Context, adapterClient client.Client
return nil
}

func ParentSnapshotsCreated(snapshot *applicationapiv1alpha1.Snapshot) bool {
return IsSnapshotStatusConditionSet(snapshot, ParentSnapshotsCreatedCondition, metav1.ConditionTrue, "")
}

func SetParentSnapshotsCreatedCondition(snapshot *applicationapiv1alpha1.Snapshot, status metav1.ConditionStatus, reason, message string) {
condition := metav1.Condition{
Type: ParentSnapshotsCreatedCondition,
Status: status,
Reason: reason,
Message: message,
}
meta.SetStatusCondition(&snapshot.Status.Conditions, condition)
}

func AddParentSnapshotDataToSnapshotStatus(snapshot *applicationapiv1alpha1.Snapshot, created bool, parentCG, parentSnapshot, message string) {
if snapshot.Status.ParentSnapshots == nil {
snapshot.Status.ParentSnapshots = make(map[string]applicationapiv1alpha1.ParentSnapshotData)
}
snapshot.Status.ParentSnapshots[parentCG] = applicationapiv1alpha1.ParentSnapshotData{
Created: created,
Name: parentSnapshot,
Message: message,
}
}

// IsSnapshotMarkedAsAddedToGlobalCandidateList returns true if snapshot's AddedToGlobalCandidateListAnnotation result is marked as true to global candidate list
func IsSnapshotMarkedAsAddedToGlobalCandidateList(snapshot *applicationapiv1alpha1.Snapshot) bool {
annotationValue, ok := snapshot.GetAnnotations()[AddedToGlobalCandidateListAnnotation]
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.25.0

require (
codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v3 v3.0.0
github.com/konflux-ci/application-api v0.0.0-20260312190025-5154ad273e17
github.com/konflux-ci/application-api v0.0.0-20260603073049-dd8c9b1a64c2
github.com/konflux-ci/coverport/instrumentation/go v0.0.0-20251127115143-b5207b335f8b
github.com/konflux-ci/image-controller v0.0.0-20241128141349-9986c9955e05
github.com/konflux-ci/operator-toolkit v0.0.0-20251118152634-b4f41f073069
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3J
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/konflux-ci/application-api v0.0.0-20260312190025-5154ad273e17 h1:auNv0idITCdlV3fP9i+V6EeT2MbZc/9+05GtKzOk1Ss=
github.com/konflux-ci/application-api v0.0.0-20260312190025-5154ad273e17/go.mod h1:948Z+a1IbfRT0RtoHzWWSN9YEucSbMJTHaMhz7dVICc=
github.com/konflux-ci/application-api v0.0.0-20260603073049-dd8c9b1a64c2 h1:ldBiggDxskW+X1Edqa1REuonbCo+hVmdwA4bC8v674Q=
github.com/konflux-ci/application-api v0.0.0-20260603073049-dd8c9b1a64c2/go.mod h1:948Z+a1IbfRT0RtoHzWWSN9YEucSbMJTHaMhz7dVICc=
github.com/konflux-ci/coverport/instrumentation/go v0.0.0-20251127115143-b5207b335f8b h1:NoriO1KRc+7d2/JA07JizqxP0LlA2oJdD5AuQOvEIjE=
github.com/konflux-ci/coverport/instrumentation/go v0.0.0-20251127115143-b5207b335f8b/go.mod h1:WVMHU9A2464s/vjH1xOTm4LJDD4xP+VlEiU+KM0gkSU=
github.com/konflux-ci/image-controller v0.0.0-20241128141349-9986c9955e05 h1:5Xawkybl99uEiXhkdkxWtHDWitgnf+kAjpNVTanVGRE=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func (a *Adapter) EnsureSnapshotExists() (result controller.OperationResult, err
}

for _, componentGroup := range *a.componentGroups {
expectedSnapshot, err := snapshot.PrepareSnapshotForPipelineRun(a.context, a.client, a.pipelineRun, a.component.Name, &componentGroup)
expectedSnapshot, err := snapshot.PrepareSnapshotForPipelineRun(a.context, a.client, a.pipelineRun, a.component.Name, &componentGroup, a.loader)
if err != nil {
return a.updatePipelineRunWithCustomizedError(&canRemoveFinalizer, err, a.context, a.pipelineRun, a.client, a.logger)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
ContextKey: loader.ComponentGroupContextKey,
Resource: hasCompGroup,
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
{
ContextKey: loader.ComponentContextKey,
Resource: hasComp,
Expand Down Expand Up @@ -804,6 +808,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
ContextKey: loader.ComponentGroupContextKey,
Resource: hasCompGroup,
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
{
ContextKey: loader.ComponentContextKey,
Resource: hasComp,
Expand All @@ -823,7 +831,7 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
},
},
})
_, err := snapshot.PrepareSnapshotForPipelineRun(adapter.context, adapter.client, adapter.pipelineRun, adapter.component.Name, hasCompGroup)
_, err := snapshot.PrepareSnapshotForPipelineRun(adapter.context, adapter.client, adapter.pipelineRun, adapter.component.Name, hasCompGroup, adapter.loader)
Expect(helpers.IsInvalidImageDigestError(err)).To(BeTrue())
Eventually(func() bool {
result, err := adapter.EnsureSnapshotExists()
Expand Down Expand Up @@ -1386,6 +1394,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
ContextKey: loader.ComponentGroupContextKey,
Resource: hasCompGroup,
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
{
ContextKey: loader.ComponentContextKey,
Resource: hasComp,
Expand Down Expand Up @@ -1426,6 +1438,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
ContextKey: loader.ComponentGroupContextKey,
Resource: hasCompGroup,
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
{
ContextKey: loader.ComponentContextKey,
Resource: hasComp,
Expand Down Expand Up @@ -1804,6 +1820,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
hasCompGroup.Name: nil,
},
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
})

Eventually(func() bool {
Expand Down Expand Up @@ -2091,6 +2111,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
Resource: nil,
Err: notFoundErr,
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
})

Eventually(func() bool {
Expand Down Expand Up @@ -2126,6 +2150,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
Resource: buildPipelineRun,
Err: conflictErr,
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
})

Eventually(func() bool {
Expand Down Expand Up @@ -2167,6 +2195,10 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
ContextKey: loader.AllSnapshotsContextKey,
Resource: []applicationapiv1alpha1.Snapshot{*hasSnapshot},
},
{
ContextKey: loader.NestedComponentGroupsContextKey,
Resource: []v1beta2.ComponentGroup{},
},
})

Eventually(func() bool {
Expand Down
Loading
Loading