This is an automated email from the ASF dual-hosted git repository.
pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/main by this push:
new abb3ab1cf fix(traits): gitops, idempotent push
abb3ab1cf is described below
commit abb3ab1cf432928379eb43dff539daaff9212df8
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Sun Jan 25 09:24:39 2026 +0100
fix(traits): gitops, idempotent push
Closes #6412
---
docs/modules/ROOT/pages/running/gitops.adoc | 3 +++
pkg/controller/integrationplatform/kamelets.go | 6 +++---
pkg/trait/gitops.go | 25 +++++++++++++++++++++++--
pkg/trait/gitops_test.go | 13 ++++++++++---
4 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/docs/modules/ROOT/pages/running/gitops.adoc
b/docs/modules/ROOT/pages/running/gitops.adoc
index 1dd75b93f..28792e400 100644
--- a/docs/modules/ROOT/pages/running/gitops.adoc
+++ b/docs/modules/ROOT/pages/running/gitops.adoc
@@ -32,6 +32,7 @@ spec:
container:
requestMemory: 256Mi
gitops:
+ enabled: true
url: https://github.com/my-org/my-camel-apps.git
secret: my-gh-token
branchPush: cicd-listener
@@ -154,6 +155,7 @@ spec:
- my-env=dev
...
gitops:
+ enabled: true
url: https://github.com/my-org/my-camel-apps.git
secret: my-gh-token
branchPush: cicd-listener-test
@@ -174,6 +176,7 @@ spec:
properties:
- my-env=test
gitops:
+ enabled: true
url: https://github.com/my-org/my-camel-apps.git
secret: my-gh-token
branchPush: cicd-listener-prod
diff --git a/pkg/controller/integrationplatform/kamelets.go
b/pkg/controller/integrationplatform/kamelets.go
index 87b8f8de7..dbe7151e9 100644
--- a/pkg/controller/integrationplatform/kamelets.go
+++ b/pkg/controller/integrationplatform/kamelets.go
@@ -29,7 +29,7 @@ import (
"strings"
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
- "knative.dev/pkg/ptr"
+ "k8s.io/utils/ptr"
"github.com/apache/camel-k/v2/pkg/client"
"github.com/apache/camel-k/v2/pkg/util"
@@ -234,8 +234,8 @@ func loadKamelet(path string, platform
*v1.IntegrationPlatform) (*v1.Kamelet, er
Kind: platform.Kind,
Name: platform.Name,
UID: platform.UID,
- Controller: ptr.Bool(true),
- BlockOwnerDeletion: ptr.Bool(true),
+ Controller: ptr.To(true),
+ BlockOwnerDeletion: ptr.To(true),
},
}
kamelet.SetOwnerReferences(references)
diff --git a/pkg/trait/gitops.go b/pkg/trait/gitops.go
index 9f54b2f45..58a4eab5b 100644
--- a/pkg/trait/gitops.go
+++ b/pkg/trait/gitops.go
@@ -30,6 +30,7 @@ import (
"github.com/apache/camel-k/v2/pkg/util/io"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
+ corev1 "k8s.io/api/core/v1"
"k8s.io/utils/ptr"
git "github.com/go-git/go-git/v5"
@@ -117,7 +118,10 @@ func (t *gitOpsTrait) pushGitOpsItInGitRepo(ctx
context.Context, it *v1.Integrat
nowDate := time.Now().Format("20060102-150405")
branchName := t.BranchPush
if branchName == "" {
- branchName = "cicd/candidate-release-" + nowDate
+ // NOTE: this is important to guarantee idempotency. We make
sure not to create
+ // more than one branch from different reconciliation cycles.
+ branchNameDate :=
it.Status.DeploymentTimestamp.Format("20060102-150405")
+ branchName = "cicd/candidate-release-" + branchNameDate
}
commitMessage := "feat(ci): build completed on " + nowDate
branchRef := plumbing.NewBranchReferenceName(branchName)
@@ -175,9 +179,26 @@ func (t *gitOpsTrait) pushGitOpsItInGitRepo(ctx
context.Context, it *v1.Integrat
RefSpecs: []config.RefSpec{
config.RefSpec(branchRef + ":" + branchRef),
},
+ // Note: this is needed to make the task idempotent without
returning any error.
+ // Even if more parallel reconciliations are kicked off, we
always push the same content,
+ // possibly more than once, without risking to raise an error.
+ Force: true,
}
- return repo.Push(gitPushOptions)
+ err = repo.Push(gitPushOptions)
+ if err != nil {
+ return err
+ }
+
+ // Publish a condition to notify the change was pushed to the branch
+ it.Status.SetCondition(
+ v1.IntegrationConditionType("GitPushed"),
+ corev1.ConditionTrue,
+ "PushedToGit",
+ "Integration changes pushed to branch "+branchName,
+ )
+
+ return nil
}
// gitConf returns the git repo configuration where to pull the project from.
If no value is provided, then, it takes
diff --git a/pkg/trait/gitops_test.go b/pkg/trait/gitops_test.go
index 4acda7c8e..ebc40a046 100644
--- a/pkg/trait/gitops_test.go
+++ b/pkg/trait/gitops_test.go
@@ -26,18 +26,19 @@ import (
"time"
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
- "knative.dev/pkg/ptr"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "k8s.io/utils/ptr"
git "github.com/go-git/go-git/v5"
)
func TestGitOpsAddAction(t *testing.T) {
trait, _ := newGitOpsTrait().(*gitOpsTrait)
- trait.Enabled = ptr.Bool(true)
+ trait.Enabled = ptr.To(true)
env := &Environment{
Integration: &v1.Integration{
Status: v1.IntegrationStatus{
@@ -72,12 +73,18 @@ func TestGitOpsPushRepoDefault(t *testing.T) {
Git: conf,
Sources: []v1.SourceSpec{v1.NewSourceSpec("Test.java", "bogus,
irrelevant for test", v1.LanguageJavaSource)},
}
+ now := metav1.Now().Rfc3339Copy()
it.Status = v1.IntegrationStatus{
- Image: "my-img-recently-baked",
+ Image: "my-img-recently-baked",
+ DeploymentTimestamp: &now,
}
err = trait.pushGitOpsItInGitRepo(context.TODO(), &it, tmpGitDir,
"fake")
require.NoError(t, err)
+ assert.Contains(t,
+
it.Status.GetCondition(v1.IntegrationConditionType("GitPushed")).Message,
+ "Integration changes pushed to branch cicd/candidate-release",
+ )
lastCommitMessage, err := getLastCommitMessage(tmpGitDir)
require.NoError(t, err)