This is an automated email from the ASF dual-hosted git repository.

squakez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit de30f1654be3c0ab0b0f111c0fc9ef6e56e40c42
Author: SunilKumarPradhan <[email protected]>
AuthorDate: Thu Oct 22 16:34:01 2026 +0530

    Fix #6874: make the Git username configurable for builds from Git
    
    Builds from Git (spec.git) authenticated the clone with the hardcoded
    username "camel-k". Some Git servers validate it, for example Bitbucket
    Cloud access tokens require the username "x-token-auth", so those
    projects could not be built.
    
    Add the optional `username` field to the Git configuration (default
    `camel-k`, backward compatible) and use it, together with the token
    stored in `secret`, when cloning the project.
---
 .../modules/ROOT/pages/running/build-from-git.adoc |  3 +
 docs/modules/ROOT/partials/apis/camel-k-crds.adoc  |  8 +++
 helm/camel-k/crds/camel-k-crds.yaml                | 20 ++++++
 pkg/apis/camel/v1/build_types.go                   |  3 +
 pkg/builder/git.go                                 |  6 +-
 pkg/builder/git_test.go                            | 82 ++++++++++++++++++++++
 .../applyconfiguration/camel/v1/gitconfigspec.go   | 11 +++
 .../config/crd/bases/camel.apache.org_builds.yaml  | 10 +++
 .../crd/bases/camel.apache.org_integrations.yaml   |  5 ++
 .../config/crd/bases/camel.apache.org_pipes.yaml   |  5 ++
 10 files changed, 152 insertions(+), 1 deletion(-)

diff --git a/docs/modules/ROOT/pages/running/build-from-git.adoc 
b/docs/modules/ROOT/pages/running/build-from-git.adoc
index df5ee08a3..bb068cfbe 100644
--- a/docs/modules/ROOT/pages/running/build-from-git.adoc
+++ b/docs/modules/ROOT/pages/running/build-from-git.adoc
@@ -21,10 +21,13 @@ spec:
   git:
     url: https://github.com/squakez/sample.git
     secret: my-secret (optional)
+    username: my-username (optional)
 ```
 
 If the project is not public (like it probably happens) you will need to 
provide the token as expected by the Git technology used. The secret has to be 
a regular Kubernetes Secret in the same namespace of the Integration.
 
+The token is sent together with a username. By default the operator uses 
`camel-k`, which is accepted by most Git servers (ie, GitHub) as they only 
validate the token. Some Git servers, however, require a specific username. For 
example, Bitbucket Cloud access tokens require `x-token-auth`. In this case, 
you can set it with the `username` field, which is used together with the token 
stored in the `secret`.
+
 The operator will start a Build custom resource, whose goal is to build and 
package the project into a container how it is happening for any other 
Integration. You can continue to use normally any trait, although certain build 
traits will be ignored as it also happens in Self Managed Build Integrations.
 
 == CLI
diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc 
b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index c300cc9d2..8dbe5f7fe 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -2380,6 +2380,14 @@ string
 
 the Kubernetes secret where token is stored
 
+|`username` +
+string
+|
+
+
+the username used to authenticate against the Git server, together with the 
token stored in `secret` (default `camel-k`).
+Some Git servers validate it, for example Bitbucket Cloud access tokens 
require `x-token-auth`.
+
 |`branch` +
 string
 |
diff --git a/helm/camel-k/crds/camel-k-crds.yaml 
b/helm/camel-k/crds/camel-k-crds.yaml
index 752032c30..fddd2a143 100644
--- a/helm/camel-k/crds/camel-k-crds.yaml
+++ b/helm/camel-k/crds/camel-k-crds.yaml
@@ -377,6 +377,11 @@ spec:
                             url:
                               description: the URL of the project
                               type: string
+                            username:
+                              description: |-
+                                the username used to authenticate against the 
Git server, together with the token stored in `secret` (default `camel-k`).
+                                Some Git servers validate it, for example 
Bitbucket Cloud access tokens require `x-token-auth`.
+                              type: string
                           type: object
                         maven:
                           description: the configuration required by Maven for 
the
@@ -1316,6 +1321,11 @@ spec:
                             url:
                               description: the URL of the project
                               type: string
+                            username:
+                              description: |-
+                                the username used to authenticate against the 
Git server, together with the token stored in `secret` (default `camel-k`).
+                                Some Git servers validate it, for example 
Bitbucket Cloud access tokens require `x-token-auth`.
+                              type: string
                           type: object
                         maven:
                           description: the configuration required by Maven for 
the
@@ -13795,6 +13805,11 @@ spec:
                   url:
                     description: the URL of the project
                     type: string
+                  username:
+                    description: |-
+                      the username used to authenticate against the Git 
server, together with the token stored in `secret` (default `camel-k`).
+                      Some Git servers validate it, for example Bitbucket 
Cloud access tokens require `x-token-auth`.
+                    type: string
                 type: object
               integrationKit:
                 description: the reference of the `IntegrationKit` which is 
used for
@@ -27141,6 +27156,11 @@ spec:
                       url:
                         description: the URL of the project
                         type: string
+                      username:
+                        description: |-
+                          the username used to authenticate against the Git 
server, together with the token stored in `secret` (default `camel-k`).
+                          Some Git servers validate it, for example Bitbucket 
Cloud access tokens require `x-token-auth`.
+                        type: string
                     type: object
                   integrationKit:
                     description: the reference of the `IntegrationKit` which 
is used
diff --git a/pkg/apis/camel/v1/build_types.go b/pkg/apis/camel/v1/build_types.go
index e3add9950..d25ff1c78 100644
--- a/pkg/apis/camel/v1/build_types.go
+++ b/pkg/apis/camel/v1/build_types.go
@@ -126,6 +126,9 @@ type GitConfigSpec struct {
        URL string `json:"url,omitempty"`
        // the Kubernetes secret where token is stored
        Secret string `json:"secret,omitempty"`
+       // the username used to authenticate against the Git server, together 
with the token stored in `secret` (default `camel-k`).
+       // Some Git servers validate it, for example Bitbucket Cloud access 
tokens require `x-token-auth`.
+       Username string `json:"username,omitempty"`
        // the git branch to check out
        Branch string `json:"branch,omitempty"`
        // the git tag to check out
diff --git a/pkg/builder/git.go b/pkg/builder/git.go
index 7935c471e..d4156a822 100644
--- a/pkg/builder/git.go
+++ b/pkg/builder/git.go
@@ -75,7 +75,11 @@ func cloneProject(ctx *builderContext) error {
        if ctx.Build.Git.Path != "" {
                gitClonePath = filepath.Join(ctx.Path, "repo")
        }
-       if _, err := util.CloneGitProject(*ctx.Build.Git, gitClonePath, 
util.DefaultGitUsername, secretToken); err != nil {
+       username := ctx.Build.Git.Username
+       if username == "" {
+               username = util.DefaultGitUsername
+       }
+       if _, err := util.CloneGitProject(*ctx.Build.Git, gitClonePath, 
username, secretToken); err != nil {
                return err
        }
        if ctx.Build.Git.Path != "" {
diff --git a/pkg/builder/git_test.go b/pkg/builder/git_test.go
index 63ccdc643..636cab8b0 100644
--- a/pkg/builder/git_test.go
+++ b/pkg/builder/git_test.go
@@ -19,16 +19,22 @@ package builder
 
 import (
        "context"
+       "net/http"
+       "net/http/httptest"
        "os"
        "path"
+       "sync"
        "testing"
 
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+       "github.com/apache/camel-k/v2/pkg/internal"
        "github.com/apache/camel-k/v2/pkg/util"
        "github.com/apache/camel-k/v2/pkg/util/boolean"
        "github.com/apache/camel-k/v2/pkg/util/jib"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 func TestGitPublicRepo(t *testing.T) {
@@ -194,3 +200,79 @@ func TestGitPublicRepoWithPath(t *testing.T) {
        require.NoError(t, err)
        assert.Contains(t, f.Name(), "test.yaml")
 }
+
+// gitBasicAuthRecorder is a fake Git HTTP server which records the basic auth 
credentials it receives
+// and rejects every request.
+type gitBasicAuthRecorder struct {
+       mu       sync.Mutex
+       called   bool
+       ok       bool
+       username string
+       password string
+}
+
+func (r *gitBasicAuthRecorder) ServeHTTP(w http.ResponseWriter, req 
*http.Request) {
+       r.mu.Lock()
+       defer r.mu.Unlock()
+       r.called = true
+       r.username, r.password, r.ok = req.BasicAuth()
+       w.WriteHeader(http.StatusUnauthorized)
+}
+
+func TestGitCloneUsername(t *testing.T) {
+       tests := []struct {
+               name             string
+               username         string
+               expectedUsername string
+       }{
+               {
+                       name:             "default username",
+                       expectedUsername: "camel-k",
+               },
+               {
+                       name:             "custom username",
+                       username:         "x-token-auth",
+                       expectedUsername: "x-token-auth",
+               },
+       }
+
+       for _, tc := range tests {
+               t.Run(tc.name, func(t *testing.T) {
+                       recorder := &gitBasicAuthRecorder{}
+                       server := httptest.NewServer(recorder)
+                       defer server.Close()
+
+                       c, err := internal.NewFakeClient(&corev1.Secret{
+                               ObjectMeta: metav1.ObjectMeta{
+                                       Namespace: "ns",
+                                       Name:      "git-secret",
+                               },
+                               Data: map[string][]byte{"token": 
[]byte("my-token")},
+                       })
+                       require.NoError(t, err)
+
+                       ctx := &builderContext{
+                               C:         context.TODO(),
+                               Client:    c,
+                               Namespace: "ns",
+                               Path:      t.TempDir(),
+                               Build: v1.BuilderTask{
+                                       Git: &v1.GitConfigSpec{
+                                               URL:      server.URL + 
"/repo.git",
+                                               Secret:   "git-secret",
+                                               Username: tc.username,
+                                       },
+                               },
+                       }
+
+                       // the fake Git server rejects any request, we only 
care about the credentials received
+                       require.Error(t, cloneProject(ctx))
+                       recorder.mu.Lock()
+                       defer recorder.mu.Unlock()
+                       assert.True(t, recorder.called)
+                       assert.True(t, recorder.ok)
+                       assert.Equal(t, tc.expectedUsername, recorder.username)
+                       assert.Equal(t, "my-token", recorder.password)
+               })
+       }
+}
diff --git a/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go 
b/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go
index 66d410817..766359c99 100644
--- a/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go
+++ b/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go
@@ -28,6 +28,9 @@ type GitConfigSpecApplyConfiguration struct {
        URL *string `json:"url,omitempty"`
        // the Kubernetes secret where token is stored
        Secret *string `json:"secret,omitempty"`
+       // the username used to authenticate against the Git server, together 
with the token stored in `secret` (default `camel-k`).
+       // Some Git servers validate it, for example Bitbucket Cloud access 
tokens require `x-token-auth`.
+       Username *string `json:"username,omitempty"`
        // the git branch to check out
        Branch *string `json:"branch,omitempty"`
        // the git tag to check out
@@ -60,6 +63,14 @@ func (b *GitConfigSpecApplyConfiguration) WithSecret(value 
string) *GitConfigSpe
        return b
 }
 
+// WithUsername sets the Username field in the declarative configuration to 
the given value
+// and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
+// If called multiple times, the Username field is set to the value of the 
last call.
+func (b *GitConfigSpecApplyConfiguration) WithUsername(value string) 
*GitConfigSpecApplyConfiguration {
+       b.Username = &value
+       return b
+}
+
 // WithBranch sets the Branch field in the declarative configuration to the 
given value
 // and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
 // If called multiple times, the Branch field is set to the value of the last 
call.
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_builds.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_builds.yaml
index bf45f1660..eb7692fc3 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_builds.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_builds.yaml
@@ -377,6 +377,11 @@ spec:
                             url:
                               description: the URL of the project
                               type: string
+                            username:
+                              description: |-
+                                the username used to authenticate against the 
Git server, together with the token stored in `secret` (default `camel-k`).
+                                Some Git servers validate it, for example 
Bitbucket Cloud access tokens require `x-token-auth`.
+                              type: string
                           type: object
                         maven:
                           description: the configuration required by Maven for 
the
@@ -1316,6 +1321,11 @@ spec:
                             url:
                               description: the URL of the project
                               type: string
+                            username:
+                              description: |-
+                                the username used to authenticate against the 
Git server, together with the token stored in `secret` (default `camel-k`).
+                                Some Git servers validate it, for example 
Bitbucket Cloud access tokens require `x-token-auth`.
+                              type: string
                           type: object
                         maven:
                           description: the configuration required by Maven for 
the
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
index e70acf6c9..d0afbb9fd 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
@@ -152,6 +152,11 @@ spec:
                   url:
                     description: the URL of the project
                     type: string
+                  username:
+                    description: |-
+                      the username used to authenticate against the Git 
server, together with the token stored in `secret` (default `camel-k`).
+                      Some Git servers validate it, for example Bitbucket 
Cloud access tokens require `x-token-auth`.
+                    type: string
                 type: object
               integrationKit:
                 description: the reference of the `IntegrationKit` which is 
used for
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
index e748e7825..c571e3b5f 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
@@ -148,6 +148,11 @@ spec:
                       url:
                         description: the URL of the project
                         type: string
+                      username:
+                        description: |-
+                          the username used to authenticate against the Git 
server, together with the token stored in `secret` (default `camel-k`).
+                          Some Git servers validate it, for example Bitbucket 
Cloud access tokens require `x-token-auth`.
+                        type: string
                     type: object
                   integrationKit:
                     description: the reference of the `IntegrationKit` which 
is used

Reply via email to