Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new git flags #1322

Merged
merged 7 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 8 additions & 1 deletion cmd/executor/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ func addKanikoOptionsFlags() {
RootCmd.PersistentFlags().VarP(&opts.Labels, "label", "", "Set metadata for an image. Set it repeatedly for multiple labels.")
RootCmd.PersistentFlags().BoolVarP(&opts.SkipUnusedStages, "skip-unused-stages", "", false, "Build only used stages if defined to true. Otherwise it builds by default all stages, even the unnecessaries ones until it reaches the target stage / end of Dockerfile")
RootCmd.PersistentFlags().BoolVarP(&opts.RunV2, "use-new-run", "", false, "Experimental run command to detect file system changes. This new run command does no rely on snapshotting to detect changes.")
RootCmd.PersistentFlags().StringVarP(&opts.Git.Branch, "git-branch", "", "", "Branch to clone if build context is a git repository")
caarlos0 marked this conversation as resolved.
Show resolved Hide resolved
RootCmd.PersistentFlags().BoolVarP(&opts.Git.SingleBranch, "git-single-branch", "", false, "Whether to clone a single branch")
RootCmd.PersistentFlags().BoolVarP(&opts.Git.RecurseSubmodules, "git-recurse-submodules", "", false, "Whether to clone recursing submodules")
}

// addHiddenFlags marks certain flags as hidden from the executor help text
Expand Down Expand Up @@ -266,7 +269,11 @@ func resolveSourceContext() error {
opts.SrcContext = opts.Bucket
}
}
contextExecutor, err := buildcontext.GetBuildContext(opts.SrcContext)
contextExecutor, err := buildcontext.GetBuildContext(opts.SrcContext, buildcontext.BuildOptions{
GitBranch: opts.Git.Branch,
GitSingleBranch: opts.Git.SingleBranch,
GitRecurseSubmodules: opts.Git.RecurseSubmodules,
})
if err != nil {
return err
}
Expand Down
10 changes: 8 additions & 2 deletions pkg/buildcontext/buildcontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const (
TarBuildContextPrefix = "tar://"
)

type BuildOptions struct {
GitBranch string
GitSingleBranch bool
GitRecurseSubmodules bool
}

// BuildContext unifies calls to download and unpack the build context.
type BuildContext interface {
// Unpacks a build context and returns the directory where it resides
Expand All @@ -36,7 +42,7 @@ type BuildContext interface {

// GetBuildContext parses srcContext for the prefix and returns related buildcontext
// parser
func GetBuildContext(srcContext string) (BuildContext, error) {
func GetBuildContext(srcContext string, opts BuildOptions) (BuildContext, error) {
split := strings.SplitAfter(srcContext, "://")
if len(split) > 1 {
prefix := split[0]
Expand All @@ -50,7 +56,7 @@ func GetBuildContext(srcContext string) (BuildContext, error) {
case constants.LocalDirBuildContextPrefix:
return &Dir{context: context}, nil
case constants.GitBuildContextPrefix:
return &Git{context: context}, nil
return &Git{context: context, opts: opts}, nil
case constants.HTTPSBuildContextPrefix:
if util.ValidAzureBlobStorageHost(srcContext) {
return &AzureBlob{context: srcContext}, nil
Expand Down
71 changes: 68 additions & 3 deletions pkg/buildcontext/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@ limitations under the License.
package buildcontext

import (
"fmt"
"os"
"strings"

"github.com/GoogleContainerTools/kaniko/pkg/constants"
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/storage/filesystem"
"github.com/sirupsen/logrus"
)

const (
Expand All @@ -43,24 +49,83 @@ var (
// Git unifies calls to download and unpack the build context.
type Git struct {
context string
opts BuildOptions
}

// UnpackTarFromBuildContext will provide the directory where Git Repository is Cloned
func (g *Git) UnpackTarFromBuildContext() (string, error) {
directory := constants.BuildContextDir
parts := strings.Split(g.context, "#")
url := getGitPullMethod() + "://" + parts[0]
options := git.CloneOptions{
URL: getGitPullMethod() + "://" + parts[0],
Auth: getGitAuth(),
Progress: os.Stdout,
URL: url,
Auth: getGitAuth(),
Progress: os.Stdout,
SingleBranch: g.opts.GitSingleBranch,
RecurseSubmodules: getRecurseSubmodules(g.opts.GitRecurseSubmodules),
}
if len(parts) > 1 {
options.ReferenceName = plumbing.ReferenceName(parts[1])
}

if branch := g.opts.GitBranch; branch != "" {
ref, err := getGitReferenceName(directory, url, branch)
if err != nil {
return directory, err
}
options.ReferenceName = ref
}

logrus.Debugf("Getting source from reference %s", options.ReferenceName)
_, err := git.PlainClone(directory, false, &options)
return directory, err
}

func getGitReferenceName(directory string, url string, branch string) (plumbing.ReferenceName, error) {
var remote = git.NewRemote(
filesystem.NewStorage(
osfs.New(directory),
cache.NewObjectLRUDefault(),
),
&config.RemoteConfig{
URLs: []string{url},
},
)

refs, err := remote.List(&git.ListOptions{
Auth: getGitAuth(),
})
if err != nil {
return plumbing.HEAD, err
}

if ref := plumbing.NewBranchReferenceName(branch); gitRefExists(ref, refs) {
return ref, nil
}

if ref := plumbing.NewTagReferenceName(branch); gitRefExists(ref, refs) {
return ref, nil
}

return plumbing.HEAD, fmt.Errorf("invalid branch: %s", branch)
}

func gitRefExists(ref plumbing.ReferenceName, refs []*plumbing.Reference) bool {
for _, ref2 := range refs {
if ref.String() == ref2.Name().String() {
return true
}
}
return false
}

func getRecurseSubmodules(v bool) git.SubmoduleRescursivity {
if v {
return git.DefaultSubmoduleRecursionDepth
}
return git.NoRecurseSubmodules
}

func getGitAuth() transport.AuthMethod {
username := os.Getenv(gitAuthUsernameEnvKey)
password := os.Getenv(gitAuthPasswordEnvKey)
Expand Down
7 changes: 7 additions & 0 deletions pkg/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ type KanikoOptions struct {
IgnoreVarRun bool
SkipUnusedStages bool
RunV2 bool
Git KanikoGitOptions
}

type KanikoGitOptions struct {
Branch string
SingleBranch bool
RecurseSubmodules bool
}

// WarmerOptions are options that are set by command line arguments to the cache warmer.
Expand Down