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
