@@ -18,6 +18,7 @@ package controllers
1818
1919import (
2020 "context"
21+ "crypto/sha256"
2122 "crypto/tls"
2223 "crypto/x509"
2324 "errors"
@@ -60,6 +61,7 @@ import (
6061 "github.com/fluxcd/pkg/runtime/events"
6162 "github.com/fluxcd/pkg/runtime/patch"
6263 "github.com/fluxcd/pkg/runtime/predicates"
64+ "github.com/fluxcd/pkg/sourceignore"
6365 "github.com/fluxcd/pkg/untar"
6466 "github.com/fluxcd/pkg/version"
6567 sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
@@ -418,8 +420,10 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
418420 conditions .MarkTrue (obj , sourcev1 .SourceVerifiedCondition , meta .SucceededReason , "verified signature of revision %s" , revision )
419421 }
420422
421- // Skip pulling if the artifact revision hasn't changes
422- if obj .GetArtifact ().HasRevision (revision ) {
423+ // Skip pulling if the artifact revision and the content config checksum has
424+ // not changed.
425+ if obj .GetArtifact ().HasRevision (revision ) &&
426+ r .calculateContentConfigChecksum (obj ) == obj .Status .ContentConfigChecksum {
423427 conditions .Delete (obj , sourcev1 .FetchFailedCondition )
424428 return sreconcile .ResultSuccess , nil
425429 }
@@ -922,17 +926,22 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
922926 artifact := r .Storage .NewArtifactFor (obj .Kind , obj , revision ,
923927 fmt .Sprintf ("%s.tar.gz" , r .digestFromRevision (revision )))
924928
929+ // Calculate the content config checksum.
930+ ccc := r .calculateContentConfigChecksum (obj )
931+
925932 // Set the ArtifactInStorageCondition if there's no drift.
926933 defer func () {
927- if obj .GetArtifact ().HasRevision (artifact .Revision ) {
934+ if obj .GetArtifact ().HasRevision (artifact .Revision ) &&
935+ obj .Status .ContentConfigChecksum == ccc {
928936 conditions .Delete (obj , sourcev1 .ArtifactOutdatedCondition )
929937 conditions .MarkTrue (obj , sourcev1 .ArtifactInStorageCondition , meta .SucceededReason ,
930938 "stored artifact for digest '%s'" , artifact .Revision )
931939 }
932940 }()
933941
934942 // The artifact is up-to-date
935- if obj .GetArtifact ().HasRevision (artifact .Revision ) {
943+ if obj .GetArtifact ().HasRevision (artifact .Revision ) &&
944+ obj .Status .ContentConfigChecksum == ccc {
936945 r .eventLogf (ctx , obj , events .EventTypeTrace , sourcev1 .ArtifactUpToDateReason ,
937946 "artifact up-to-date with remote revision: '%s'" , artifact .Revision )
938947 return sreconcile .ResultSuccess , nil
@@ -984,7 +993,20 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
984993 return sreconcile .ResultEmpty , e
985994 }
986995 default :
987- if err := r .Storage .Archive (& artifact , dir , nil ); err != nil {
996+ // Load ignore rules for archiving.
997+ ignoreDomain := strings .Split (dir , string (filepath .Separator ))
998+ ps , err := sourceignore .LoadIgnorePatterns (dir , ignoreDomain )
999+ if err != nil {
1000+ return sreconcile .ResultEmpty , serror .NewGeneric (
1001+ fmt .Errorf ("failed to load source ignore patterns from repository: %w" , err ),
1002+ "SourceIgnoreError" ,
1003+ )
1004+ }
1005+ if obj .Spec .Ignore != nil {
1006+ ps = append (ps , sourceignore .ReadPatterns (strings .NewReader (* obj .Spec .Ignore ), ignoreDomain )... )
1007+ }
1008+
1009+ if err := r .Storage .Archive (& artifact , dir , SourceIgnoreFilter (ps , ignoreDomain )); err != nil {
9881010 e := serror .NewGeneric (
9891011 fmt .Errorf ("unable to archive artifact to storage: %s" , err ),
9901012 sourcev1 .ArchiveOperationFailedReason ,
@@ -997,6 +1019,7 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
9971019 // Record it on the object
9981020 obj .Status .Artifact = artifact .DeepCopy ()
9991021 obj .Status .Artifact .Metadata = metadata .Metadata
1022+ obj .Status .ContentConfigChecksum = ccc
10001023
10011024 // Update symlink on a "best effort" basis
10021025 url , err := r .Storage .Symlink (artifact , "latest.tar.gz" )
@@ -1125,3 +1148,21 @@ func (r *OCIRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *so
11251148 }
11261149 }
11271150}
1151+
1152+ // calculateContentConfigChecksum calculates a checksum of all the
1153+ // configurations that result in a change in the source artifact. It can be used
1154+ // to decide if further reconciliation is needed when an artifact already exists
1155+ // for a set of configurations.
1156+ func (r * OCIRepositoryReconciler ) calculateContentConfigChecksum (obj * sourcev1.OCIRepository ) string {
1157+ c := []byte {}
1158+ // Consider the ignore rules.
1159+ if obj .Spec .Ignore != nil {
1160+ c = append (c , []byte (* obj .Spec .Ignore )... )
1161+ }
1162+ // Consider the layer selector.
1163+ if obj .Spec .LayerSelector != nil {
1164+ c = append (c , []byte (obj .GetLayerMediaType ()+ obj .GetLayerOperation ())... )
1165+ }
1166+
1167+ return fmt .Sprintf ("sha256:%x" , sha256 .Sum256 (c ))
1168+ }
0 commit comments