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
+}

Reply via email to