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 338818235 feat(git): filter git project path
338818235 is described below
commit 338818235a9a7310e6ce248ce771423eb7a38f28
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Sat Mar 7 10:04:48 2026 +0100
feat(git): filter git project path
Closes #6447
---
.../modules/ROOT/pages/running/build-from-git.adoc | 6 +++
docs/modules/ROOT/partials/apis/camel-k-crds.adoc | 7 ++++
helm/camel-k/crds/camel-k-crds.yaml | 18 +++++++++
pkg/apis/camel/v1/build_types.go | 2 +
pkg/builder/git.go | 27 +++++++++++++-
pkg/builder/git_test.go | 21 +++++++++++
.../applyconfiguration/camel/v1/gitconfigspec.go | 10 +++++
pkg/cmd/run.go | 3 ++
.../config/crd/bases/camel.apache.org_builds.yaml | 10 +++++
.../crd/bases/camel.apache.org_integrations.yaml | 4 ++
.../config/crd/bases/camel.apache.org_pipes.yaml | 4 ++
pkg/util/io/io.go | 43 +++++++++++++++++++++-
12 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/docs/modules/ROOT/pages/running/build-from-git.adoc
b/docs/modules/ROOT/pages/running/build-from-git.adoc
index 902388eca..9c58a97ea 100644
--- a/docs/modules/ROOT/pages/running/build-from-git.adoc
+++ b/docs/modules/ROOT/pages/running/build-from-git.adoc
@@ -48,6 +48,9 @@ kamel run --git https://github.com/michalvavrik/sample.git
--git-tag v1.2.3
# Clone the project and checkout specific commit (full SHA)
kamel run --git https://github.com/michalvavrik/sample.git --git-commit
f2b9bd064a62263ab53b3bfe6ac2b71e68dba45b
+
+# Clone specific path (likely a directory containing the module project you
want to build)
+kamel run --git https://github.com/michalvavrik/sample.git --git-path
path/to/my/module
```
=== Using YAML Configuration
@@ -63,8 +66,11 @@ spec:
# branch: feature/xyz # Use specific branch
# tag: v1.2.3 # Or use specific tag
# commit: f2b9bd064a62263ab53b3bfe6ac2b71e68dba45b # Or use specific
commit
+ # path: path/to/my/module
```
+NOTE: the `path` option can be used in combination with any other git option
such as tag, commit or branch.
+
== Rebuild
In order to trigger a rebuild of an Integration you will need to `kamel
rebuild` or to wipe off the Integration `status` as it normally happens for any
other regular Integration.
diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index b14d94b53..ff0475873 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -2288,6 +2288,13 @@ string
the git commit (full SHA) to check out
+|`path` +
+string
+|
+
+
+the path you want to use for your project. If provided, it must be an existing
directory on the Git repository.
+
|===
diff --git a/helm/camel-k/crds/camel-k-crds.yaml
b/helm/camel-k/crds/camel-k-crds.yaml
index 0ebf7aa71..384688690 100644
--- a/helm/camel-k/crds/camel-k-crds.yaml
+++ b/helm/camel-k/crds/camel-k-crds.yaml
@@ -359,6 +359,11 @@ spec:
commit:
description: the git commit (full SHA) to check
out
type: string
+ path:
+ description: the path you want to use for your
project.
+ If provided, it must be an existing directory
on the
+ Git repository.
+ type: string
secret:
description: the Kubernetes secret where token
is stored
type: string
@@ -1284,6 +1289,11 @@ spec:
commit:
description: the git commit (full SHA) to check
out
type: string
+ path:
+ description: the path you want to use for your
project.
+ If provided, it must be an existing directory
on the
+ Git repository.
+ type: string
secret:
description: the Kubernetes secret where token
is stored
type: string
@@ -13225,6 +13235,10 @@ spec:
commit:
description: the git commit (full SHA) to check out
type: string
+ path:
+ description: the path you want to use for your project. If
provided,
+ it must be an existing directory on the Git repository.
+ type: string
secret:
description: the Kubernetes secret where token is stored
type: string
@@ -26099,6 +26113,10 @@ spec:
commit:
description: the git commit (full SHA) to check out
type: string
+ path:
+ description: the path you want to use for your
project. If
+ provided, it must be an existing directory on the
Git repository.
+ type: string
secret:
description: the Kubernetes secret where token is
stored
type: string
diff --git a/pkg/apis/camel/v1/build_types.go b/pkg/apis/camel/v1/build_types.go
index 25da40e3d..a1a318909 100644
--- a/pkg/apis/camel/v1/build_types.go
+++ b/pkg/apis/camel/v1/build_types.go
@@ -132,6 +132,8 @@ type GitConfigSpec struct {
Tag string `json:"tag,omitempty"`
// the git commit (full SHA) to check out
Commit string `json:"commit,omitempty"`
+ // the path you want to use for your project. If provided, it must be
an existing directory on the Git repository.
+ Path string `json:"path,omitempty"`
}
// MavenBuildSpec defines the Maven configuration plus additional repositories
to use.
diff --git a/pkg/builder/git.go b/pkg/builder/git.go
index fd9fde41d..f1e3b3016 100644
--- a/pkg/builder/git.go
+++ b/pkg/builder/git.go
@@ -18,9 +18,11 @@ limitations under the License.
package builder
import (
+ "os"
"path/filepath"
util "github.com/apache/camel-k/v2/pkg/util/gitops"
+ "github.com/apache/camel-k/v2/pkg/util/io"
)
func init() {
@@ -63,7 +65,28 @@ func cloneProject(ctx *builderContext) error {
return err
}
}
- _, err := util.CloneGitProject(*ctx.Build.Git, filepath.Join(ctx.Path,
"maven"), secretToken)
- return err
+ projectPath := filepath.Join(ctx.Path, "maven")
+ gitClonePath := projectPath
+
+ // If the user wants to use a specific path, then, we need to clone the
entire project first
+ // and later copy the requested path to the project path, which is what
the operator will use to
+ // build the project
+ if ctx.Build.Git.Path != "" {
+ gitClonePath = filepath.Join(ctx.Path, "repo")
+ }
+ if _, err := util.CloneGitProject(*ctx.Build.Git, gitClonePath,
secretToken); err != nil {
+ return err
+ }
+ if ctx.Build.Git.Path != "" {
+ selectedPath := filepath.Join(gitClonePath, ctx.Build.Git.Path)
+ _, err := os.Stat(selectedPath)
+ if err != nil {
+ return err
+ }
+ // only select the given path as a maven project to use
+ return io.CopyDir(selectedPath, projectPath)
+ }
+
+ return nil
}
diff --git a/pkg/builder/git_test.go b/pkg/builder/git_test.go
index 41b83e4f9..63ccdc643 100644
--- a/pkg/builder/git_test.go
+++ b/pkg/builder/git_test.go
@@ -173,3 +173,24 @@ func TestGitCloneCommit(t *testing.T) {
require.NoError(t, err)
assert.Contains(t, f.Name(), "this_is_expected_commit")
}
+
+func TestGitPublicRepoWithPath(t *testing.T) {
+ tmpGitDir := t.TempDir()
+
+ ctx := &builderContext{
+ C: context.TODO(),
+ Path: tmpGitDir,
+ Build: v1.BuilderTask{
+ Git: &v1.GitConfigSpec{
+ URL: "https://github.com/squakez/sample.git",
+ Path: "src/main/resources/camel",
+ },
+ },
+ }
+
+ err := cloneProject(ctx)
+ require.NoError(t, err)
+ f, err := os.Stat(path.Join(tmpGitDir, "maven", "test.yaml"))
+ require.NoError(t, err)
+ assert.Contains(t, f.Name(), "test.yaml")
+}
diff --git a/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go
b/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go
index d40e2ce83..66d410817 100644
--- a/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go
+++ b/pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go
@@ -34,6 +34,8 @@ type GitConfigSpecApplyConfiguration struct {
Tag *string `json:"tag,omitempty"`
// the git commit (full SHA) to check out
Commit *string `json:"commit,omitempty"`
+ // the path you want to use for your project. If provided, it must be
an existing directory on the Git repository.
+ Path *string `json:"path,omitempty"`
}
// GitConfigSpecApplyConfiguration constructs a declarative configuration of
the GitConfigSpec type for use with
@@ -81,3 +83,11 @@ func (b *GitConfigSpecApplyConfiguration) WithCommit(value
string) *GitConfigSpe
b.Commit = &value
return b
}
+
+// WithPath sets the Path 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 Path field is set to the value of the last
call.
+func (b *GitConfigSpecApplyConfiguration) WithPath(value string)
*GitConfigSpecApplyConfiguration {
+ b.Path = &value
+ return b
+}
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index e6d8e9595..862922c70 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -115,6 +115,7 @@ func newCmdRun(rootCmdOptions *RootCmdOptions)
(*cobra.Command, *runCmdOptions)
cmd.Flags().String("git-branch", "", "Git branch to checkout when using
--git option")
cmd.Flags().String("git-tag", "", "Git tag to checkout when using --git
option")
cmd.Flags().String("git-commit", "", "Git commit (full SHA) to checkout
when using --git option")
+ cmd.Flags().String("git-path", "", "Git path (likely a project module)
to checkout when using --git option")
cmd.Flags().Bool("save", false, "Save the run parameters into the
default kamel configuration file (kamel-config.yaml)")
cmd.Flags().Bool("dont-run-after-build", false, "Only build, don't run
the application. "+
"You can run \"kamel deploy\" to run a built Integration.")
@@ -143,6 +144,7 @@ type runCmdOptions struct {
GitBranch string `mapstructure:"git-branch"
yaml:",omitempty"`
GitTag string `mapstructure:"git-tag"
yaml:",omitempty"`
GitCommit string `mapstructure:"git-commit"
yaml:",omitempty"`
+ GitPath string `mapstructure:"git-path"
yaml:",omitempty"`
Profile string `mapstructure:"profile"
yaml:",omitempty"`
IntegrationProfile string `mapstructure:"integration-profile"
yaml:",omitempty"`
OperatorID string `mapstructure:"operator-id"
yaml:",omitempty"`
@@ -598,6 +600,7 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd
*cobra.Command, c client.C
Tag: o.GitTag,
Branch: o.GitBranch,
Commit: o.GitCommit,
+ Path: o.GitPath,
}
} else {
return nil, errors.New("you must provide a source, an image or
a git repository parameters")
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 3d093181d..a1a3683e4 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_builds.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_builds.yaml
@@ -359,6 +359,11 @@ spec:
commit:
description: the git commit (full SHA) to check
out
type: string
+ path:
+ description: the path you want to use for your
project.
+ If provided, it must be an existing directory
on the
+ Git repository.
+ type: string
secret:
description: the Kubernetes secret where token
is stored
type: string
@@ -1284,6 +1289,11 @@ spec:
commit:
description: the git commit (full SHA) to check
out
type: string
+ path:
+ description: the path you want to use for your
project.
+ If provided, it must be an existing directory
on the
+ Git repository.
+ type: string
secret:
description: the Kubernetes secret where token
is stored
type: string
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 53b9cd25c..4b71a819d 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
@@ -139,6 +139,10 @@ spec:
commit:
description: the git commit (full SHA) to check out
type: string
+ path:
+ description: the path you want to use for your project. If
provided,
+ it must be an existing directory on the Git repository.
+ type: string
secret:
description: the Kubernetes secret where token is stored
type: string
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 6cbf3f26d..6b307e25d 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
@@ -135,6 +135,10 @@ spec:
commit:
description: the git commit (full SHA) to check out
type: string
+ path:
+ description: the path you want to use for your
project. If
+ provided, it must be an existing directory on the
Git repository.
+ type: string
secret:
description: the Kubernetes secret where token is
stored
type: string
diff --git a/pkg/util/io/io.go b/pkg/util/io/io.go
index 7a489adca..931c7c009 100644
--- a/pkg/util/io/io.go
+++ b/pkg/util/io/io.go
@@ -17,7 +17,11 @@ limitations under the License.
package io
-import "os"
+import (
+ "io"
+ "os"
+ "path/filepath"
+)
const (
FilePerm600 os.FileMode = 0o600 // For secret files.
@@ -26,3 +30,40 @@ const (
FilePerm700 os.FileMode = 0o700 // For directory
FilePerm400 os.FileMode = 0o400 // For read only files
)
+
+// CopyDir programmatically "cp -r src dst".
+func CopyDir(src, dst string) error {
+ return filepath.WalkDir(src, func(path string, d os.DirEntry, err
error) error {
+ if err != nil {
+ return err
+ }
+ rel, err := filepath.Rel(src, path)
+ if err != nil {
+ return err
+ }
+ target := filepath.Join(dst, rel)
+
+ if d.IsDir() {
+ return os.MkdirAll(target, FilePerm755)
+ }
+
+ return copyFile(path, target)
+ })
+}
+
+func copyFile(src, dst string) error {
+ in, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer in.Close()
+
+ out, err := os.Create(dst)
+ if err != nil {
+ return err
+ }
+ defer out.Close()
+ _, err = io.Copy(out, in)
+
+ return err
+}