Skip to content

Commit f0493e2

Browse files
michalvavriksquakez
authored andcommitted
feat(api): Add Integration Git Branch, Commit, Tag options
- Allows to select branch, tag or commit for Git source - closes: #6135 Changes: - make the project cloning for the default branch shallow (depth 1 commit) - add option to checkout Git tag and test it - add option to checkout Git branch and test it - add option to checkout Git commit and test it (this is the least efficient of the 3 as it requires the full project history checkout)
1 parent 8c80436 commit f0493e2

File tree

13 files changed

+383
-5
lines changed

13 files changed

+383
-5
lines changed

docs/modules/ROOT/pages/running/build-from-git.adoc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,38 @@ The operator will start a Build custom resource, whose goal is to build and pack
3333

3434
The `kamel` CLI is equipped with a `--git` option that you can use to provide the project repository.
3535

36+
== Specifying Branch, Tag or Commit
37+
38+
By default, Camel K clones the repository's default branch (usually `main`). You can specify a different branch, tag, or specific commit using either CLI options or YAML configuration:
39+
40+
=== Using CLI Options
41+
42+
```bash
43+
# Clone specific branch
44+
kamel run --git https://github.com/michalvavrik/sample.git --git-branch feature/xyz
45+
46+
# Clone specific tag
47+
kamel run --git https://github.com/michalvavrik/sample.git --git-tag v1.2.3
48+
49+
# Clone the project and checkout specific commit (full SHA)
50+
kamel run --git https://github.com/michalvavrik/sample.git --git-commit f2b9bd064a62263ab53b3bfe6ac2b71e68dba45b
51+
```
52+
53+
=== Using YAML Configuration
54+
55+
```yaml
56+
apiVersion: camel.apache.org/v1
57+
kind: Integration
58+
metadata:
59+
name: sample
60+
spec:
61+
git:
62+
url: https://github.com/michalvavrik/sample.git
63+
branch: feature/xyz # Use specific branch
64+
# tag: v1.2.3 # Or use specific tag
65+
# commit: f2b9bd064a62263ab53b3bfe6ac2b71e68dba45b # Or use specific commit
66+
```
67+
3668
== Rebuild
3769

3870
In order to trigger a rebuild of an Integration you will need to `kamel reset` or to wipe off the Integration `status` as it normally happens for any other regular Integration.

docs/modules/ROOT/partials/apis/camel-k-crds.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,27 @@ string
22622262
22632263
the Kubernetes secret where token is stored
22642264
2265+
|`branch` +
2266+
string
2267+
|
2268+
2269+
2270+
the git branch to check out
2271+
2272+
|`tag` +
2273+
string
2274+
|
2275+
2276+
2277+
the git tag to check out
2278+
2279+
|`commit` +
2280+
string
2281+
|
2282+
2283+
2284+
the git commit (full SHA) to check out
2285+
22652286
22662287
|===
22672288

helm/camel-k/crds/camel-k-crds.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,18 @@ spec:
349349
description: the configuration of the project to build on
350350
Git
351351
properties:
352+
branch:
353+
description: the git branch to check out
354+
type: string
355+
commit:
356+
description: the git commit (full SHA) to check out
357+
type: string
352358
secret:
353359
description: the Kubernetes secret where token is stored
354360
type: string
361+
tag:
362+
description: the git tag to check out
363+
type: string
355364
url:
356365
description: the URL of the project
357366
type: string
@@ -1262,9 +1271,18 @@ spec:
12621271
description: the configuration of the project to build on
12631272
Git
12641273
properties:
1274+
branch:
1275+
description: the git branch to check out
1276+
type: string
1277+
commit:
1278+
description: the git commit (full SHA) to check out
1279+
type: string
12651280
secret:
12661281
description: the Kubernetes secret where token is stored
12671282
type: string
1283+
tag:
1284+
description: the git tag to check out
1285+
type: string
12681286
url:
12691287
description: the URL of the project
12701288
type: string
@@ -12195,9 +12213,18 @@ spec:
1219512213
git:
1219612214
description: the configuration of the project to build on Git
1219712215
properties:
12216+
branch:
12217+
description: the git branch to check out
12218+
type: string
12219+
commit:
12220+
description: the git commit (full SHA) to check out
12221+
type: string
1219812222
secret:
1219912223
description: the Kubernetes secret where token is stored
1220012224
type: string
12225+
tag:
12226+
description: the git tag to check out
12227+
type: string
1220112228
url:
1220212229
description: the URL of the project
1220312230
type: string
@@ -24168,9 +24195,18 @@ spec:
2416824195
git:
2416924196
description: the configuration of the project to build on Git
2417024197
properties:
24198+
branch:
24199+
description: the git branch to check out
24200+
type: string
24201+
commit:
24202+
description: the git commit (full SHA) to check out
24203+
type: string
2417124204
secret:
2417224205
description: the Kubernetes secret where token is stored
2417324206
type: string
24207+
tag:
24208+
description: the git tag to check out
24209+
type: string
2417424210
url:
2417524211
description: the URL of the project
2417624212
type: string

pkg/apis/camel/v1/build_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ type GitConfigSpec struct {
117117
URL string `json:"url,omitempty"`
118118
// the Kubernetes secret where token is stored
119119
Secret string `json:"secret,omitempty"`
120+
// the git branch to check out
121+
Branch string `json:"branch,omitempty"`
122+
// the git tag to check out
123+
Tag string `json:"tag,omitempty"`
124+
// the git commit (full SHA) to check out
125+
Commit string `json:"commit,omitempty"`
120126
}
121127

122128
// MavenBuildSpec defines the Maven configuration plus additional repositories to use.

pkg/builder/git.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ limitations under the License.
1818
package builder
1919

2020
import (
21+
"errors"
2122
"path/filepath"
2223

2324
git "github.com/go-git/go-git/v5"
25+
"github.com/go-git/go-git/v5/plumbing"
2426
"github.com/go-git/go-git/v5/plumbing/transport/http"
2527
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2628
)
@@ -57,8 +59,31 @@ var Git = gitSteps{
5759
}
5860

5961
func cloneProject(ctx *builderContext) error {
62+
depth := 1
63+
if ctx.Build.Git.Commit != "" {
64+
// only the commit checkout requires full git project history
65+
depth = 0
66+
}
6067
gitCloneOptions := &git.CloneOptions{
61-
URL: ctx.Build.Git.URL,
68+
URL: ctx.Build.Git.URL,
69+
Depth: depth,
70+
}
71+
72+
if ctx.Build.Git.Branch != "" {
73+
if ctx.Build.Git.Tag != "" {
74+
return errors.New("illegal arguments: cannot specify both git branch and tag")
75+
}
76+
if ctx.Build.Git.Commit != "" {
77+
return errors.New("illegal arguments: cannot specify both git branch and commit")
78+
}
79+
gitCloneOptions.ReferenceName = plumbing.NewBranchReferenceName(ctx.Build.Git.Branch)
80+
gitCloneOptions.SingleBranch = true
81+
} else if ctx.Build.Git.Tag != "" {
82+
if ctx.Build.Git.Commit != "" {
83+
return errors.New("illegal arguments: cannot specify both git tag and commit")
84+
}
85+
gitCloneOptions.ReferenceName = plumbing.NewTagReferenceName(ctx.Build.Git.Tag)
86+
gitCloneOptions.SingleBranch = true
6287
}
6388

6489
if ctx.Build.Git.Secret != "" {
@@ -78,7 +103,25 @@ func cloneProject(ctx *builderContext) error {
78103
}
79104
}
80105

81-
_, err := git.PlainClone(filepath.Join(ctx.Path, "maven"), false, gitCloneOptions)
106+
repo, err := git.PlainClone(filepath.Join(ctx.Path, "maven"), false, gitCloneOptions)
107+
108+
if err != nil {
109+
return err
110+
}
111+
112+
if ctx.Build.Git.Commit != "" {
113+
worktree, err := repo.Worktree()
114+
if err != nil {
115+
return err
116+
}
117+
commitHash := plumbing.NewHash(ctx.Build.Git.Commit)
118+
err = worktree.Checkout(&git.CheckoutOptions{
119+
Hash: commitHash,
120+
})
121+
if err != nil {
122+
return err
123+
}
124+
}
82125

83-
return err
126+
return nil
84127
}

pkg/builder/git_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,84 @@ func TestGitPrivateRepoFail(t *testing.T) {
9292
require.Error(t, err)
9393
assert.Contains(t, err.Error(), "no such file or directory")
9494
}
95+
96+
func TestGitCloneBranch(t *testing.T) {
97+
tmpGitDir := t.TempDir()
98+
99+
ctx := &builderContext{
100+
C: context.TODO(),
101+
Path: tmpGitDir,
102+
Build: v1.BuilderTask{
103+
Git: &v1.GitConfigSpec{
104+
// the project URL for the https://github.com/squakez/sample.git fork
105+
URL: "https://github.com/michalvavrik/sample.git",
106+
// only difference between the main branch and this branch is the 'this_is_expected_branch' empty file
107+
Branch: "feature/branch-checkout-test",
108+
},
109+
},
110+
}
111+
112+
err := cloneProject(ctx)
113+
require.NoError(t, err)
114+
f, err := os.Stat(path.Join(tmpGitDir, "maven", "pom.xml"))
115+
require.NoError(t, err)
116+
assert.Contains(t, f.Name(), "pom.xml")
117+
118+
f, err = os.Stat(path.Join(tmpGitDir, "maven", "this_is_expected_branch"))
119+
require.NoError(t, err)
120+
assert.Contains(t, f.Name(), "this_is_expected_branch")
121+
}
122+
123+
func TestGitCloneTag(t *testing.T) {
124+
tmpGitDir := t.TempDir()
125+
126+
ctx := &builderContext{
127+
C: context.TODO(),
128+
Path: tmpGitDir,
129+
Build: v1.BuilderTask{
130+
Git: &v1.GitConfigSpec{
131+
// the project URL for the https://github.com/squakez/sample.git fork
132+
URL: "https://github.com/michalvavrik/sample.git",
133+
// only difference between the main branch and this tag is the 'this_is_expected_tag' empty file
134+
Tag: "v1.2.3",
135+
},
136+
},
137+
}
138+
139+
err := cloneProject(ctx)
140+
require.NoError(t, err)
141+
f, err := os.Stat(path.Join(tmpGitDir, "maven", "pom.xml"))
142+
require.NoError(t, err)
143+
assert.Contains(t, f.Name(), "pom.xml")
144+
145+
f, err = os.Stat(path.Join(tmpGitDir, "maven", "this_is_expected_tag"))
146+
require.NoError(t, err)
147+
assert.Contains(t, f.Name(), "this_is_expected_tag")
148+
}
149+
150+
func TestGitCloneCommit(t *testing.T) {
151+
tmpGitDir := t.TempDir()
152+
153+
ctx := &builderContext{
154+
C: context.TODO(),
155+
Path: tmpGitDir,
156+
Build: v1.BuilderTask{
157+
Git: &v1.GitConfigSpec{
158+
// the project URL for the https://github.com/squakez/sample.git fork
159+
URL: "https://github.com/michalvavrik/sample.git",
160+
// only difference between the main branch and this commit is the 'this_is_expected_commit' empty file
161+
Commit: "f2b9bd064a62263ab53b3bfe6ac2b71e68dba45b",
162+
},
163+
},
164+
}
165+
166+
err := cloneProject(ctx)
167+
require.NoError(t, err)
168+
f, err := os.Stat(path.Join(tmpGitDir, "maven", "pom.xml"))
169+
require.NoError(t, err)
170+
assert.Contains(t, f.Name(), "pom.xml")
171+
172+
f, err = os.Stat(path.Join(tmpGitDir, "maven", "this_is_expected_commit"))
173+
require.NoError(t, err)
174+
assert.Contains(t, f.Name(), "this_is_expected_commit")
175+
}

pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cmd/run.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions)
117117
cmd.Flags().String("service-account", "", "The SA to use to run this Integration")
118118
cmd.Flags().Bool("force", false, "Force creation of integration regardless of potential misconfiguration.")
119119
cmd.Flags().String("git", "", "A Git repository containing the project to build.")
120+
cmd.Flags().String("git-branch", "", "Git branch to checkout when using --git option")
121+
cmd.Flags().String("git-tag", "", "Git tag to checkout when using --git option")
122+
cmd.Flags().String("git-commit", "", "Git commit (full SHA) to checkout when using --git option")
120123
cmd.Flags().Bool("save", false, "Save the run parameters into the default kamel configuration file (kamel-config.yaml)")
121124

122125
// completion support
@@ -138,6 +141,9 @@ type runCmdOptions struct {
138141
IntegrationName string `mapstructure:"name" yaml:",omitempty"`
139142
ContainerImage string `mapstructure:"image" yaml:",omitempty"`
140143
GitRepo string `mapstructure:"git" yaml:",omitempty"`
144+
GitBranch string `mapstructure:"git-branch" yaml:",omitempty"`
145+
GitTag string `mapstructure:"git-tag" yaml:",omitempty"`
146+
GitCommit string `mapstructure:"git-commit" yaml:",omitempty"`
141147
Profile string `mapstructure:"profile" yaml:",omitempty"`
142148
IntegrationProfile string `mapstructure:"integration-profile" yaml:",omitempty"`
143149
OperatorID string `mapstructure:"operator-id" yaml:",omitempty"`
@@ -565,8 +571,23 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
565571
// Self Managed Integration as the user provided a container image built externally
566572
o.Traits = append(o.Traits, fmt.Sprintf("container.image=%s", o.ContainerImage))
567573
} else if o.GitRepo != "" {
574+
if o.GitBranch != "" && o.GitTag != "" {
575+
err := errors.New("illegal arguments: cannot specify both git branch and tag")
576+
return nil, err
577+
}
578+
if o.GitBranch != "" && o.GitCommit != "" {
579+
err := errors.New("illegal arguments: cannot specify both git branch and commit")
580+
return nil, err
581+
}
582+
if o.GitTag != "" && o.GitCommit != "" {
583+
err := errors.New("illegal arguments: cannot specify both git tag and commit")
584+
return nil, err
585+
}
568586
integration.Spec.Git = &v1.GitConfigSpec{
569-
URL: o.GitRepo,
587+
URL: o.GitRepo,
588+
Tag: o.GitTag,
589+
Branch: o.GitBranch,
590+
Commit: o.GitCommit,
570591
}
571592
} else {
572593
return nil, errors.New("you must provide a source, an image or a git repository parameters")

0 commit comments

Comments
 (0)