Skip to content

Commit

Permalink
Add OS, VCS and CICD metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
devashish-patel committed Jul 2, 2024
1 parent 36b6ca6 commit 6a8a14b
Show file tree
Hide file tree
Showing 7 changed files with 345 additions and 44 deletions.
4 changes: 2 additions & 2 deletions internal/hcp/registry/hcl.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ func (h *HCLRegistry) CompleteBuild(
buildName = cb.Type
}

metadata := cb.GetMetadata()
err := h.bucket.Version.AddMetadataToBuild(ctx, buildName, metadata)
buildMetadata := cb.GetMetadata()
err := h.bucket.Version.AddMetadataToBuild(ctx, buildName, buildMetadata, h.metadata)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/hcp/registry/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (h *JSONRegistry) CompleteBuild(
) ([]sdkpacker.Artifact, error) {
buildName := build.Name()
buildMetadata := build.(*packer.CoreBuild).GetMetadata()
err := h.bucket.Version.AddMetadataToBuild(ctx, buildName, buildMetadata)
err := h.bucket.Version.AddMetadataToBuild(ctx, buildName, buildMetadata, h.metadata)
if err != nil {
return nil, err
}
Expand Down
103 changes: 103 additions & 0 deletions internal/hcp/registry/metadata.cicd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package registry

import (
"fmt"
"os"
)

type CICD interface {
Detect() bool
Env() map[string]string
Type() string
}

type GithubActions struct{}

func (g *GithubActions) Detect() bool {
_, ok := os.LookupEnv("GITHUB_ACTIONS")
return ok
}

func (g *GithubActions) Env() map[string]string {
env := make(map[string]string)
keys := []string{
"GITHUB_REPOSITORY",
"GITHUB_REPOSITORY_ID",
"GITHUB_WORKFLOW_URL",
"GITHUB_SHA",
"GITHUB_REF",
"GITHUB_ACTOR",
"GITHUB_ACTOR_ID",
"GITHUB_TRIGGERING_ACTOR",
"GITHUB_EVENT_NAME",
"GITHUB_JOB",
}

for _, key := range keys {
if value, ok := os.LookupEnv(key); ok {
env[key] = value
}
}

env["GITHUB_WORKFLOW_URL"] = fmt.Sprintf("%s/%s/actions/runs/%s", os.Getenv("GITHUB_SERVER_URL"), os.Getenv("GITHUB_REPOSITORY"), os.Getenv("GITHUB_RUN_ID"))
return env
}

func (g *GithubActions) Type() string {
return "github-actions"
}

type GitlabCI struct{}

func (g *GitlabCI) Detect() bool {
_, ok := os.LookupEnv("GITLAB_CI")
return ok
}

func (g *GitlabCI) Env() map[string]string {
env := make(map[string]string)
keys := []string{
"CI_PROJECT_NAME",
"CI_PROJECT_ID",
"CI_PROJECT_URL",
"CI_COMMIT_SHA",
"CI_COMMIT_REF_NAME",
"GITLAB_USER_NAME",
"GITLAB_USER_ID",
"CI_PIPELINE_SOURCE",
"CI_PIPELINE_URL",
"CI_JOB_URL",
"CI_SERVER_NAME",
"CI_REGISTRY_IMAGE",
}

for _, key := range keys {
if value, ok := os.LookupEnv(key); ok {
env[key] = value
}
}

return env
}

func (g *GitlabCI) Type() string {
return "gitlab-ci"
}

func GetCicdMetadata() map[string]interface{} {
cicd := []CICD{
&GithubActions{},
&GitlabCI{},
}

for _, c := range cicd {
if c.Detect() {
return map[string]interface{}{
"type": c.Type(),
"details": c.Env(),
}
}
}

return nil
}
129 changes: 129 additions & 0 deletions internal/hcp/registry/metadata.os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package registry

import (
"bytes"
"log"
"os/exec"
"runtime"
"strings"
"time"
)

type OSInfo struct {
Name string
Arch string
Version string
}

func GetOSMetadata() map[string]interface{} {
var osInfo OSInfo

switch runtime.GOOS {
case "windows":
osInfo = GetInfoForWindows()
case "darwin":
osInfo = GetInfo("-srm")
case "linux":
osInfo = GetInfo("-srio")
case "freebsd":
osInfo = GetInfo("-sri")
case "openbsd":
osInfo = GetInfo("-srm")
case "netbsd":
osInfo = GetInfo("-srm")
default:
osInfo = OSInfo{
Name: runtime.GOOS,
Arch: runtime.GOARCH,
}
}

return map[string]interface{}{
"type": osInfo.Name,
"details": map[string]interface{}{
"arch": osInfo.Arch,
"version": osInfo.Version,
},
}
}

func GetInfo(flags string) OSInfo {
out, err := _uname(flags)
tries := 0
for strings.Contains(out, "broken pipe") && tries < 3 {
out, err = _uname(flags)
time.Sleep(500 * time.Millisecond)
tries++
}
if strings.Contains(out, "broken pipe") || err != nil {
out = ""
}

if err != nil {
log.Printf("[ERROR] failed to get the OS info: %s", err)
}
core := _retrieveCore(out)
return OSInfo{
Name: runtime.GOOS,
Arch: runtime.GOARCH,
Version: core,
}
}

func _uname(flags string) (string, error) {
cmd := exec.Command("uname", flags)
cmd.Stdin = strings.NewReader("some input")
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
return out.String(), err
}

func _retrieveCore(osStr string) string {
osStr = strings.Replace(osStr, "\n", "", -1)
osStr = strings.Replace(osStr, "\r\n", "", -1)
osInfo := strings.Split(osStr, " ")

var core string
if len(osInfo) > 1 {
core = osInfo[1]
}
return core
}

func GetInfoForWindows() OSInfo {
cmd := exec.Command("cmd", "ver")
cmd.Stdin = strings.NewReader("some input")
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Printf("[ERROR] failed to get the OS info: %s", err)
return OSInfo{
Name: runtime.GOOS,
Arch: runtime.GOARCH,
}
}

osStr := strings.Replace(out.String(), "\n", "", -1)
osStr = strings.Replace(osStr, "\r\n", "", -1)
tmp1 := strings.Index(osStr, "[Version")
tmp2 := strings.Index(osStr, "]")
var ver string
if tmp1 == -1 || tmp2 == -1 {
ver = ""
} else {
ver = osStr[tmp1+9 : tmp2]
}

osInfo := OSInfo{
Name: runtime.GOOS,
Arch: runtime.GOARCH,
Version: ver,
}
return osInfo
}
93 changes: 93 additions & 0 deletions internal/hcp/registry/metadata.vcs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package registry

import (
"log"
"os"

gt "github.com/go-git/go-git/v5"
)

type VCS interface {
Detect(wd string) error
Details() map[string]interface{}
Type() string
}

type Git struct {
repo *gt.Repository
}

func (g *Git) Detect(wd string) error {
repo, err := gt.PlainOpenWithOptions(wd, &gt.PlainOpenOptions{DetectDotGit: true})
if err != nil {
return err
}

g.repo = repo
return nil
}

func (g *Git) hasUncommittedChanges() bool {
worktree, err := g.repo.Worktree()
if err != nil {
log.Printf("[ERROR] failed to get the git worktree: %s", err)
return false
}

status, err := worktree.Status()
if err != nil {
log.Printf("[ERROR] failed to get the git worktree status: %s", err)
return false
}
return !status.IsClean()
}

func (g *Git) Type() string {
return "git"
}

func (g *Git) Details() map[string]interface{} {
resp := map[string]interface{}{}

headRef, err := g.repo.Head()
if err != nil {
log.Printf("[ERROR] failed to get the git branch name: %s", err)
} else {
resp["ref"] = headRef.Name().Short()
}

commit, err := g.repo.CommitObject(headRef.Hash())
if err != nil {
log.Printf("[ERROR] failed to get the git commit hash: %s", err)
} else {
resp["commit"] = commit.Hash.String()
resp["author"] = commit.Author.Name + " <" + commit.Author.Email + ">"
}

resp["has_uncommitted_changes"] = g.hasUncommittedChanges()
return resp
}

func GetVcsMetadata() map[string]interface{} {
wd, err := os.Getwd()
if err != nil {
log.Printf("[ERROR] unable to retrieve current directory: %s", err)
return map[string]interface{}{}
}

vcsSystems := []VCS{
&Git{},
}

for _, vcs := range vcsSystems {
err := vcs.Detect(wd)
if err == nil {
return map[string]interface{}{
"type": vcs.Type(),
"details": vcs.Details(),
}
}
}

return nil
}
Loading

0 comments on commit 6a8a14b

Please sign in to comment.