Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/modules/ROOT/pages/running/build-from-git.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,38 @@ The operator will start a Build custom resource, whose goal is to build and pack

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

== Specifying Branch, Tag or Commit

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:

=== Using CLI Options

```bash
# Clone specific branch
kamel run --git https://github.com/michalvavrik/sample.git --git-branch feature/xyz

# Clone specific tag
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
```

=== Using YAML Configuration

```yaml
apiVersion: camel.apache.org/v1
kind: Integration
metadata:
name: sample
spec:
git:
url: https://github.com/michalvavrik/sample.git
branch: feature/xyz # Use specific branch
# tag: v1.2.3 # Or use specific tag
# commit: f2b9bd064a62263ab53b3bfe6ac2b71e68dba45b # Or use specific commit
```

== Rebuild

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.
Expand Down
21 changes: 21 additions & 0 deletions docs/modules/ROOT/partials/apis/camel-k-crds.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,27 @@ string

the Kubernetes secret where token is stored

|`branch` +
string
|


the git branch to check out

|`tag` +
string
|


the git tag to check out

|`commit` +
string
|


the git commit (full SHA) to check out


|===

Expand Down
36 changes: 36 additions & 0 deletions helm/camel-k/crds/camel-k-crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,18 @@ spec:
description: the configuration of the project to build on
Git
properties:
branch:
description: the git branch to check out
type: string
commit:
description: the git commit (full SHA) to check out
type: string
secret:
description: the Kubernetes secret where token is stored
type: string
tag:
description: the git tag to check out
type: string
url:
description: the URL of the project
type: string
Expand Down Expand Up @@ -1262,9 +1271,18 @@ spec:
description: the configuration of the project to build on
Git
properties:
branch:
description: the git branch to check out
type: string
commit:
description: the git commit (full SHA) to check out
type: string
secret:
description: the Kubernetes secret where token is stored
type: string
tag:
description: the git tag to check out
type: string
url:
description: the URL of the project
type: string
Expand Down Expand Up @@ -12195,9 +12213,18 @@ spec:
git:
description: the configuration of the project to build on Git
properties:
branch:
description: the git branch to check out
type: string
commit:
description: the git commit (full SHA) to check out
type: string
secret:
description: the Kubernetes secret where token is stored
type: string
tag:
description: the git tag to check out
type: string
url:
description: the URL of the project
type: string
Expand Down Expand Up @@ -24168,9 +24195,18 @@ spec:
git:
description: the configuration of the project to build on Git
properties:
branch:
description: the git branch to check out
type: string
commit:
description: the git commit (full SHA) to check out
type: string
secret:
description: the Kubernetes secret where token is stored
type: string
tag:
description: the git tag to check out
type: string
url:
description: the URL of the project
type: string
Expand Down
6 changes: 6 additions & 0 deletions pkg/apis/camel/v1/build_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ type GitConfigSpec struct {
URL string `json:"url,omitempty"`
// the Kubernetes secret where token is stored
Secret string `json:"secret,omitempty"`
// the git branch to check out
Branch string `json:"branch,omitempty"`
// the git tag to check out
Tag string `json:"tag,omitempty"`
// the git commit (full SHA) to check out
Commit string `json:"commit,omitempty"`
}

// MavenBuildSpec defines the Maven configuration plus additional repositories to use.
Expand Down
49 changes: 46 additions & 3 deletions pkg/builder/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ limitations under the License.
package builder

import (
"errors"
"path/filepath"

git "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/transport/http"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -57,8 +59,31 @@ var Git = gitSteps{
}

func cloneProject(ctx *builderContext) error {
depth := 1
if ctx.Build.Git.Commit != "" {
// only the commit checkout requires full git project history
depth = 0
}
gitCloneOptions := &git.CloneOptions{
URL: ctx.Build.Git.URL,
URL: ctx.Build.Git.URL,
Depth: depth,
}

if ctx.Build.Git.Branch != "" {
if ctx.Build.Git.Tag != "" {
return errors.New("illegal arguments: cannot specify both git branch and tag")
}
if ctx.Build.Git.Commit != "" {
return errors.New("illegal arguments: cannot specify both git branch and commit")
}
gitCloneOptions.ReferenceName = plumbing.NewBranchReferenceName(ctx.Build.Git.Branch)
gitCloneOptions.SingleBranch = true
} else if ctx.Build.Git.Tag != "" {
if ctx.Build.Git.Commit != "" {
return errors.New("illegal arguments: cannot specify both git tag and commit")
}
gitCloneOptions.ReferenceName = plumbing.NewTagReferenceName(ctx.Build.Git.Tag)
gitCloneOptions.SingleBranch = true
}

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

_, err := git.PlainClone(filepath.Join(ctx.Path, "maven"), false, gitCloneOptions)
repo, err := git.PlainClone(filepath.Join(ctx.Path, "maven"), false, gitCloneOptions)

if err != nil {
return err
}

if ctx.Build.Git.Commit != "" {
worktree, err := repo.Worktree()
if err != nil {
return err
}
commitHash := plumbing.NewHash(ctx.Build.Git.Commit)
err = worktree.Checkout(&git.CheckoutOptions{
Hash: commitHash,
})
if err != nil {
return err
}
}

return err
return nil
}
81 changes: 81 additions & 0 deletions pkg/builder/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,84 @@ func TestGitPrivateRepoFail(t *testing.T) {
require.Error(t, err)
assert.Contains(t, err.Error(), "no such file or directory")
}

func TestGitCloneBranch(t *testing.T) {
tmpGitDir := t.TempDir()

ctx := &builderContext{
C: context.TODO(),
Path: tmpGitDir,
Build: v1.BuilderTask{
Git: &v1.GitConfigSpec{
// the project URL for the https://github.com/squakez/sample.git fork
URL: "https://github.com/michalvavrik/sample.git",
// only difference between the main branch and this branch is the 'this_is_expected_branch' empty file
Branch: "feature/branch-checkout-test",
},
},
}

err := cloneProject(ctx)
require.NoError(t, err)
f, err := os.Stat(path.Join(tmpGitDir, "maven", "pom.xml"))
require.NoError(t, err)
assert.Contains(t, f.Name(), "pom.xml")

f, err = os.Stat(path.Join(tmpGitDir, "maven", "this_is_expected_branch"))
require.NoError(t, err)
assert.Contains(t, f.Name(), "this_is_expected_branch")
}

func TestGitCloneTag(t *testing.T) {
tmpGitDir := t.TempDir()

ctx := &builderContext{
C: context.TODO(),
Path: tmpGitDir,
Build: v1.BuilderTask{
Git: &v1.GitConfigSpec{
// the project URL for the https://github.com/squakez/sample.git fork
URL: "https://github.com/michalvavrik/sample.git",
// only difference between the main branch and this tag is the 'this_is_expected_tag' empty file
Tag: "v1.2.3",
},
},
}

err := cloneProject(ctx)
require.NoError(t, err)
f, err := os.Stat(path.Join(tmpGitDir, "maven", "pom.xml"))
require.NoError(t, err)
assert.Contains(t, f.Name(), "pom.xml")

f, err = os.Stat(path.Join(tmpGitDir, "maven", "this_is_expected_tag"))
require.NoError(t, err)
assert.Contains(t, f.Name(), "this_is_expected_tag")
}

func TestGitCloneCommit(t *testing.T) {
tmpGitDir := t.TempDir()

ctx := &builderContext{
C: context.TODO(),
Path: tmpGitDir,
Build: v1.BuilderTask{
Git: &v1.GitConfigSpec{
// the project URL for the https://github.com/squakez/sample.git fork
URL: "https://github.com/michalvavrik/sample.git",
// only difference between the main branch and this commit is the 'this_is_expected_commit' empty file
Commit: "f2b9bd064a62263ab53b3bfe6ac2b71e68dba45b",
},
},
}

err := cloneProject(ctx)
require.NoError(t, err)
f, err := os.Stat(path.Join(tmpGitDir, "maven", "pom.xml"))
require.NoError(t, err)
assert.Contains(t, f.Name(), "pom.xml")

f, err = os.Stat(path.Join(tmpGitDir, "maven", "this_is_expected_commit"))
require.NoError(t, err)
assert.Contains(t, f.Name(), "this_is_expected_commit")
}
27 changes: 27 additions & 0 deletions pkg/client/camel/applyconfiguration/camel/v1/gitconfigspec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 22 additions & 1 deletion pkg/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions)
cmd.Flags().String("service-account", "", "The SA to use to run this Integration")
cmd.Flags().Bool("force", false, "Force creation of integration regardless of potential misconfiguration.")
cmd.Flags().String("git", "", "A Git repository containing the project to build.")
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().Bool("save", false, "Save the run parameters into the default kamel configuration file (kamel-config.yaml)")

// completion support
Expand All @@ -138,6 +141,9 @@ type runCmdOptions struct {
IntegrationName string `mapstructure:"name" yaml:",omitempty"`
ContainerImage string `mapstructure:"image" yaml:",omitempty"`
GitRepo string `mapstructure:"git" yaml:",omitempty"`
GitBranch string `mapstructure:"git-branch" yaml:",omitempty"`
GitTag string `mapstructure:"git-tag" yaml:",omitempty"`
GitCommit string `mapstructure:"git-commit" yaml:",omitempty"`
Profile string `mapstructure:"profile" yaml:",omitempty"`
IntegrationProfile string `mapstructure:"integration-profile" yaml:",omitempty"`
OperatorID string `mapstructure:"operator-id" yaml:",omitempty"`
Expand Down Expand Up @@ -565,8 +571,23 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
// Self Managed Integration as the user provided a container image built externally
o.Traits = append(o.Traits, fmt.Sprintf("container.image=%s", o.ContainerImage))
} else if o.GitRepo != "" {
if o.GitBranch != "" && o.GitTag != "" {
err := errors.New("illegal arguments: cannot specify both git branch and tag")
return nil, err
}
if o.GitBranch != "" && o.GitCommit != "" {
err := errors.New("illegal arguments: cannot specify both git branch and commit")
return nil, err
}
if o.GitTag != "" && o.GitCommit != "" {
err := errors.New("illegal arguments: cannot specify both git tag and commit")
return nil, err
}
integration.Spec.Git = &v1.GitConfigSpec{
URL: o.GitRepo,
URL: o.GitRepo,
Tag: o.GitTag,
Branch: o.GitBranch,
Commit: o.GitCommit,
}
} else {
return nil, errors.New("you must provide a source, an image or a git repository parameters")
Expand Down
Loading
Loading