-
Notifications
You must be signed in to change notification settings - Fork 44
/
discover.go
119 lines (107 loc) · 2.99 KB
/
discover.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package ruby
import (
"context"
"fmt"
"regexp"
"strings"
"chainguard.dev/melange/pkg/config"
wgit "github.com/wolfi-dev/wolfictl/pkg/git"
"github.com/wolfi-dev/wolfictl/pkg/melange"
)
type Package struct {
// Name is the name of the package, package.name in the melange yaml
Name string
// Repo is a URL struct representing the git repo for a ruby package
Repo *wgit.URL
// Ref is the version of the ruby package, used to query github
Ref string
}
// DiscoverRubyPackages searches a given path for melange yaml files using
// packages named ruby-${RubyVersion}. It takes a path to a directory or an
// individual file. A list of RubyPackages will be returned to the caller.
func (o *Options) DiscoverRubyPackages(ctx context.Context) ([]Package, error) {
pkgs, err := melange.ReadAllPackagesFromRepo(ctx, o.Path)
if err != nil {
return nil, fmt.Errorf("error discovering ruby packages, %w", err)
}
var rubyFiles []Package
for _, pkg := range pkgs {
if o.isRubyPackage(pkg.Config) {
gitURL, err := wgit.ParseGitURL(parseRepo(pkg))
if err != nil {
// fmt.Printf("
continue
}
rubyFiles = append(rubyFiles, Package{
Name: pkg.Config.Name(),
Repo: gitURL,
Ref: parseRef(pkg),
})
}
}
if len(rubyFiles) < 1 {
return nil, fmt.Errorf("did not find any ruby references [%s]", o.Path)
}
return rubyFiles, nil
}
// isRubyPackage looks for ruby-${RubyVersion} in the melange yaml package list
func (o *Options) isRubyPackage(conf config.Configuration) bool {
rubyPkg := fmt.Sprintf("%s%s", rubyKey, o.RubyVersion)
rubyDevPkg := fmt.Sprintf("%s-dev", rubyPkg)
for _, pkg := range conf.Environment.Contents.Packages {
if pkg == rubyPkg || pkg == rubyDevPkg {
return true
}
}
for _, pkg := range conf.Package.Dependencies.Runtime {
if pkg == rubyPkg || pkg == rubyDevPkg {
return true
}
}
return false
}
// parseRepo tries to extract the repository from the fetch or git-checkout
// pipelines.
//
// TODO: Extract from runs: if neither pipeline is found
func parseRepo(pkg *melange.Packages) string {
for i := range pkg.Config.Pipeline {
step := &pkg.Config.Pipeline[i]
switch step.Uses {
case "fetch":
return step.With["uri"]
case "git-checkout":
return step.With["repository"]
}
}
return ""
}
// parseRef tries to extract the correct tag/release version string from either
// the fetch or git-checkout pipelines.
func parseRef(pkg *melange.Packages) string {
ref := ""
for i := range pkg.Config.Pipeline {
step := &pkg.Config.Pipeline[i]
switch step.Uses {
case "fetch":
uri := step.With["uri"]
pattern := `.*\/(v?\$\{{2}package.version\}{2})`
re := regexp.MustCompile(pattern)
matches := re.FindStringSubmatch(uri)
if len(matches) > 1 {
ref = matches[1]
break
}
case "git-checkout":
if val, ok := step.With["tag"]; ok {
ref = val
break
}
if val, ok := step.With["branch"]; ok {
ref = val
break
}
}
}
return strings.ReplaceAll(ref, "${{package.version}}", pkg.Config.Package.Version)
}