From 4c2b33af0dde4bf88c233c61f1381c3a7f800e5c Mon Sep 17 00:00:00 2001 From: Ilya Lesikov Date: Fri, 14 Jan 2022 22:05:21 +0300 Subject: [PATCH] feat(build): expose commit info in werf templates New Map {{ .Commit }} available in werf.yaml. --- cmd/werf/common/common.go | 2 +- pkg/build/stage/git_mapping.go | 2 +- pkg/config/parser.go | 18 ++++++++++++ pkg/git_repo/base.go | 40 ++++++++++++++++++++++++++- pkg/git_repo/git_repo.go | 10 +++++-- pkg/git_repo/local.go | 22 +++++++++------ pkg/git_repo/remote.go | 7 ++++- pkg/git_repo/repo_handle/handle.go | 4 +++ pkg/git_repo/repo_handle/interface.go | 1 + 9 files changed, 92 insertions(+), 14 deletions(-) diff --git a/cmd/werf/common/common.go b/cmd/werf/common/common.go index 642fde6cc4..3955cf34c8 100644 --- a/cmd/werf/common/common.go +++ b/cmd/werf/common/common.go @@ -1189,7 +1189,7 @@ func GetGiterminismManager(cmdData *CmdData) (giterminism_manager.Interface, err return nil, err } - headCommit, err := localGitRepo.HeadCommit(BackgroundContext()) + headCommit, err := localGitRepo.HeadCommitHash(BackgroundContext()) if err != nil { return nil, err } diff --git a/pkg/build/stage/git_mapping.go b/pkg/build/stage/git_mapping.go index ac6e997c04..66440a8d9a 100644 --- a/pkg/build/stage/git_mapping.go +++ b/pkg/build/stage/git_mapping.go @@ -204,7 +204,7 @@ func (gm *GitMapping) getLatestCommit(ctx context.Context) (string, error) { return gm.GitRepo().LatestBranchCommit(ctx, gm.Branch) } - commit, err := gm.GitRepo().HeadCommit(ctx) + commit, err := gm.GitRepo().HeadCommitHash(ctx) if err != nil { return "", err } diff --git a/pkg/config/parser.go b/pkg/config/parser.go index 9f422f4e9f..3fbdb9adfd 100644 --- a/pkg/config/parser.go +++ b/pkg/config/parser.go @@ -204,6 +204,24 @@ func renderWerfConfigYaml(ctx context.Context, customWerfConfigRelPath, customWe } templateData["Env"] = env + headHash, err := giterminismManager.LocalGitRepo().HeadCommitHash(ctx) + if err != nil { + return "", "", fmt.Errorf("unable to get HEAD commit hash: %s", err) + } + + headTime, err := giterminismManager.LocalGitRepo().HeadCommitTime(ctx) + if err != nil { + return "", "", fmt.Errorf("unable to get HEAD commit time: %s", err) + } + + templateData["Commit"] = map[string]interface{}{ + "Hash": headHash, + "Date": map[string]string{ + "Human": headTime.String(), + "Unix": strconv.FormatInt(headTime.Unix(), 10), + }, + } + config, err := executeTemplate(tmpl, "werfConfig", templateData) return configPath, config, err diff --git a/pkg/git_repo/base.go b/pkg/git_repo/base.go index a4c90ff6f5..6db55e9621 100644 --- a/pkg/git_repo/base.go +++ b/pkg/git_repo/base.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" "sync" + "time" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" @@ -66,7 +67,11 @@ func (repo *Base) initRepoHandleBackedByWorkTree(ctx context.Context, commit str return repo.initRepoHandleBackedByWorkTreeFunc(ctx, commit) } -func (repo *Base) HeadCommit(ctx context.Context) (string, error) { +func (repo *Base) HeadCommitHash(ctx context.Context) (string, error) { + panic("not implemented") +} + +func (repo *Base) HeadCommitTime(ctx context.Context) (*time.Time, error) { panic("not implemented") } @@ -1019,3 +1024,36 @@ func (repo *Base) ListCommitFilesWithGlob(ctx context.Context, commit string, di return result, nil } + +func baseHeadCommitTime(repo gitRepo, ctx context.Context) (*time.Time, error) { + headCommitHash, err := repo.HeadCommitHash(ctx) + if err != nil { + return nil, fmt.Errorf("unable to get HEAD hash: %s", err) + } + + var time *time.Time + if err := repo.withRepoHandle(ctx, headCommitHash, func(repoHandle repo_handle.Handle) error { + headHash, err := newHash(headCommitHash) + if err != nil { + return fmt.Errorf("unable to create new Hash object from commit SHA %q: %s", headCommitHash, err) + } + + repo := repoHandle.Repository() + if repo == nil { + return fmt.Errorf("unable to get repository from repoHandle") + } + + commit, err := repo.CommitObject(headHash) + if err != nil { + return fmt.Errorf("unable to get commit object for ref %q: %s", headCommitHash, err) + } + + time = &commit.Author.When + + return nil + }); err != nil { + return nil, err + } + + return time, nil +} diff --git a/pkg/git_repo/git_repo.go b/pkg/git_repo/git_repo.go index b5696638f5..12b1b35ef5 100644 --- a/pkg/git_repo/git_repo.go +++ b/pkg/git_repo/git_repo.go @@ -3,6 +3,7 @@ package git_repo import ( "context" "path/filepath" + "time" "github.com/werf/werf/pkg/git_repo/repo_handle" "github.com/werf/werf/pkg/path_matcher" @@ -45,7 +46,8 @@ type GitRepo interface { GetOrCreateArchive(ctx context.Context, opts ArchiveOptions) (Archive, error) GetOrCreateChecksum(ctx context.Context, opts ChecksumOptions) (string, error) GetOrCreatePatch(ctx context.Context, opts PatchOptions) (Patch, error) - HeadCommit(ctx context.Context) (string, error) + HeadCommitHash(ctx context.Context) (string, error) + HeadCommitTime(ctx context.Context) (*time.Time, error) IsAncestor(ctx context.Context, ancestorCommit, descendantCommit string) (bool, error) IsCommitDirectoryExist(ctx context.Context, commit, path string) (bool, error) IsCommitExists(ctx context.Context, commit string) (bool, error) @@ -62,8 +64,12 @@ type GitRepo interface { ResolveCommitFilePath(ctx context.Context, commit, path string) (string, error) TagCommit(ctx context.Context, tag string) (string, error) WalkCommitFiles(ctx context.Context, commit string, dir string, pathMatcher path_matcher.PathMatcher, fileFunc func(notResolvedPath string) error) error +} + +type gitRepo interface { + GitRepo - initRepoHandleBackedByWorkTree(ctx context.Context, commit string) (repo_handle.Handle, error) + withRepoHandle(ctx context.Context, commit string, f func(handle repo_handle.Handle) error) error } type Patch interface { diff --git a/pkg/git_repo/local.go b/pkg/git_repo/local.go index 27927ed0c3..bf9bec12a3 100644 --- a/pkg/git_repo/local.go +++ b/pkg/git_repo/local.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "sync" + "time" "github.com/go-git/go-git/v5" @@ -27,7 +28,7 @@ type Local struct { WorkTreeDir string GitDir string - headCommit string + headCommitHash string statusResult *status.Result mutex sync.Mutex @@ -81,7 +82,7 @@ func OpenLocalRepo(ctx context.Context, name, workTreeDir string, opts OpenLocal l.GitDir, l.WorkTreeDir, l.getRepoWorkTreeCacheDir(l.getRepoID()), - l.headCommit, + l.headCommitHash, true_git.SyncSourceWorktreeWithServiceBranchOptions{ ServiceBranchPrefix: opts.ServiceBranchOptions.Prefix, GlobExcludeList: opts.ServiceBranchOptions.GlobExcludeList, @@ -91,7 +92,7 @@ func OpenLocalRepo(ctx context.Context, name, workTreeDir string, opts OpenLocal return l, err } - l.headCommit = devHeadCommit + l.headCommitHash = devHeadCommit } } @@ -105,9 +106,9 @@ func newLocal(name, workTreeDir, gitDir string) (l *Local, err error) { } l = &Local{ - WorkTreeDir: workTreeDir, - GitDir: gitDir, - headCommit: headCommit, + WorkTreeDir: workTreeDir, + GitDir: gitDir, + headCommitHash: headCommit, } l.Base = NewBase(name, l.initRepoHandleBackedByWorkTree) @@ -223,8 +224,13 @@ func (repo *Local) RemoteOriginUrl(_ context.Context) (string, error) { return repo.remoteOriginUrl(repo.WorkTreeDir) } -func (repo *Local) HeadCommit(_ context.Context) (string, error) { - return repo.headCommit, nil +func (repo *Local) HeadCommitHash(_ context.Context) (string, error) { + return repo.headCommitHash, nil +} + +func (repo *Local) HeadCommitTime(ctx context.Context) (*time.Time, error) { + time, err := baseHeadCommitTime(repo, ctx) + return time, err } func (repo *Local) GetOrCreatePatch(ctx context.Context, opts PatchOptions) (Patch, error) { diff --git a/pkg/git_repo/remote.go b/pkg/git_repo/remote.go index b073f0acb9..4f7e2818fe 100644 --- a/pkg/git_repo/remote.go +++ b/pkg/git_repo/remote.go @@ -225,10 +225,15 @@ func (repo *Remote) Fetch(ctx context.Context) error { }) } -func (repo *Remote) HeadCommit(_ context.Context) (string, error) { +func (repo *Remote) HeadCommitHash(_ context.Context) (string, error) { return getHeadCommit(repo.GetClonePath()) } +func (repo *Remote) HeadCommitTime(ctx context.Context) (*time.Time, error) { + time, err := baseHeadCommitTime(repo, ctx) + return time, err +} + func (repo *Remote) findReference(rawRepo *git.Repository, reference string) (string, error) { refs, err := rawRepo.References() if err != nil { diff --git a/pkg/git_repo/repo_handle/handle.go b/pkg/git_repo/repo_handle/handle.go index 3d4ebf7c01..bb174198bc 100644 --- a/pkg/git_repo/repo_handle/handle.go +++ b/pkg/git_repo/repo_handle/handle.go @@ -79,6 +79,10 @@ func (h *handle) Submodules() []SubmoduleHandle { return h.submoduleHandleList } +func (h *handle) Repository() *git.Repository { + return h.repository +} + type submoduleHandle struct { Handle config *config.Submodule diff --git a/pkg/git_repo/repo_handle/interface.go b/pkg/git_repo/repo_handle/interface.go index 3fe5971500..65fba9b1d5 100644 --- a/pkg/git_repo/repo_handle/interface.go +++ b/pkg/git_repo/repo_handle/interface.go @@ -14,6 +14,7 @@ import ( // caching the necessary data from the worktree during initialization, // and then working exclusively with git objects. type Handle interface { + Repository() *git.Repository Submodule(submodulePath string) (SubmoduleHandle, error) Submodules() []SubmoduleHandle ReadBlobObjectContent(hash plumbing.Hash) ([]byte, error)