Skip to content

Commit 62ec08b

Browse files
committed
feat(server): implement tags/list endpoint
When a git source is used branch names are exposed in the tags list. For other source types, only "latest" is exposed. Fixes: #85
1 parent 9292851 commit 62ec08b

File tree

3 files changed

+194
-36
lines changed

3 files changed

+194
-36
lines changed

config/pkgsource.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"strings"
2323

2424
log "github.com/sirupsen/logrus"
25+
"gopkg.in/src-d/go-git.v4"
26+
"gopkg.in/src-d/go-git.v4/plumbing"
2527
)
2628

2729
// PkgSource represents the source from which the Nix package set used
@@ -32,13 +34,16 @@ type PkgSource interface {
3234
// for calling Nix.
3335
Render(tag string) (string, string)
3436

35-
// Create a key by which builds for this source and iamge
37+
// Create a key by which builds for this source and image
3638
// combination can be cached.
3739
//
3840
// The empty string means that this value is not cacheable due
3941
// to the package source being a moving target (such as a
4042
// channel).
4143
CacheKey(pkgs []string, tag string) string
44+
45+
// Return available docker tags for the current PkgSource
46+
Tags() ([]string, error)
4247
}
4348

4449
type GitSource struct {
@@ -91,6 +96,30 @@ func (g *GitSource) CacheKey(pkgs []string, tag string) string {
9196
return hashed
9297
}
9398

99+
// Regex to determine valid docker tags
100+
var tagRegex = regexp.MustCompile(`^[\w][\w.-]{0,127}$`)
101+
102+
func (g *GitSource) Tags() ([]string, error) {
103+
tags := []string{"latest"}
104+
r, err := git.PlainOpen(g.repository)
105+
if err != nil {
106+
return tags, err
107+
}
108+
branchesRefs, err := r.Branches()
109+
if err != nil {
110+
return tags, err
111+
}
112+
err = branchesRefs.ForEach(func(r *plumbing.Reference) error {
113+
tag := strings.TrimPrefix(string(r.Name()), "refs/heads/")
114+
// latest tag is always present and represent the master branch
115+
if tagRegex.MatchString(tag) && tag != "master" {
116+
tags = append(tags, tag)
117+
}
118+
return nil
119+
})
120+
return tags, err
121+
}
122+
94123
type NixChannel struct {
95124
channel string
96125
}
@@ -113,6 +142,10 @@ func (n *NixChannel) CacheKey(pkgs []string, tag string) string {
113142
return hashed
114143
}
115144

145+
func (n *NixChannel) Tags() ([]string, error) {
146+
return []string{"latest"}, nil
147+
}
148+
116149
type PkgsPath struct {
117150
path string
118151
}
@@ -128,6 +161,10 @@ func (p *PkgsPath) CacheKey(pkgs []string, tag string) string {
128161
return ""
129162
}
130163

164+
func (n *PkgsPath) Tags() ([]string, error) {
165+
return []string{"latest"}, nil
166+
}
167+
131168
// Retrieve a package source from the environment. If no source is
132169
// specified, the Nix code will default to a recent NixOS channel.
133170
func pkgSourceFromEnv() (PkgSource, error) {
@@ -140,7 +177,7 @@ func pkgSourceFromEnv() (PkgSource, error) {
140177
}
141178

142179
if git := os.Getenv("NIXERY_PKGS_REPO"); git != "" {
143-
log.WithField("repo", git).Info("using NIx package set from git repository")
180+
log.WithField("repo", git).Info("using Nix package set from git repository")
144181

145182
return &GitSource{
146183
repository: git,

go-deps.nix

Lines changed: 133 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,125 +5,224 @@
55
fetch = {
66
type = "git";
77
url = "https://code.googlesource.com/gocloud";
8-
rev = "77f6a3a292a7dbf66a5329de0d06326f1906b450";
9-
sha256 = "1c9pkx782nbcp8jnl5lprcbzf97van789ky5qsncjgywjyymhigi";
8+
rev = "dccc6b4b7113c54191c37cc0c75a1ad3d632b9c8";
9+
sha256 = "0b268pf83p20waxl82jfwnqkihp992xxxmjpyc9xd8wliq110cc5";
10+
};
11+
}
12+
{
13+
goPackagePath = "github.com/emirpasic/gods";
14+
fetch = {
15+
type = "git";
16+
url = "https://github.com/emirpasic/gods";
17+
rev = "4e23915b9a82f35f320a68a395a7a5045c826932";
18+
sha256 = "00f8ch1rccakc62f9nj97hapvnx84z7wbcdmbmz7p802b9mxk5nl";
19+
};
20+
}
21+
{
22+
goPackagePath = "github.com/golang/groupcache";
23+
fetch = {
24+
type = "git";
25+
url = "https://github.com/golang/groupcache";
26+
rev = "8c9f03a8e57eb486e42badaed3fb287da51807ba";
27+
sha256 = "0vjjr79r32icjzlb05wn02k59av7jx0rn1jijml8r4whlg7dnkfh";
1028
};
1129
}
1230
{
1331
goPackagePath = "github.com/golang/protobuf";
1432
fetch = {
1533
type = "git";
1634
url = "https://github.com/golang/protobuf";
17-
rev = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7";
18-
sha256 = "1k1wb4zr0qbwgpvz9q5ws9zhlal8hq7dmq62pwxxriksayl6hzym";
35+
rev = "d23c5127dc24889085f8ccea5c9d560a57a879d8";
36+
sha256 = "1cyyr52yhj3fzrily3rmsbqyj8va4ld75lmry0857m39rgpv8sy1";
1937
};
2038
}
2139
{
2240
goPackagePath = "github.com/googleapis/gax-go";
2341
fetch = {
2442
type = "git";
2543
url = "https://github.com/googleapis/gax-go";
26-
rev = "bd5b16380fd03dc758d11cef74ba2e3bc8b0e8c2";
27-
sha256 = "1lxawwngv6miaqd25s3ba0didfzylbwisd2nz7r4gmbmin6jsjrx";
44+
rev = "b443e5a67ec8eeac76f5f384004931878cab24b3";
45+
sha256 = "075s8b76l14c9vlchly38hsf28bnr7vzq9q57g2kg1025h004lzw";
46+
};
47+
}
48+
{
49+
goPackagePath = "github.com/jbenet/go-context";
50+
fetch = {
51+
type = "git";
52+
url = "https://github.com/jbenet/go-context";
53+
rev = "d14ea06fba99483203c19d92cfcd13ebe73135f4";
54+
sha256 = "0q91f5549n81w3z5927n4a1mdh220bdmgl42zi3h992dcc4ls0sl";
55+
};
56+
}
57+
{
58+
goPackagePath = "github.com/kevinburke/ssh_config";
59+
fetch = {
60+
type = "git";
61+
url = "https://github.com/kevinburke/ssh_config";
62+
rev = "01f96b0aa0cdcaa93f9495f89bbc6cb5a992ce6e";
63+
sha256 = "1bxfjkjl3ibzdkwyvgdwawmd0skz30ah1ha10rg6fkxvj7lgg4jz";
64+
};
65+
}
66+
{
67+
goPackagePath = "github.com/mitchellh/go-homedir";
68+
fetch = {
69+
type = "git";
70+
url = "https://github.com/mitchellh/go-homedir";
71+
rev = "af06845cf3004701891bf4fdb884bfe4920b3727";
72+
sha256 = "0ydzkipf28hwj2bfxqmwlww47khyk6d152xax4bnyh60f4lq3nx1";
73+
};
74+
}
75+
{
76+
goPackagePath = "github.com/sergi/go-diff";
77+
fetch = {
78+
type = "git";
79+
url = "https://github.com/sergi/go-diff";
80+
rev = "58c5cb1602ee9676b5d3590d782bedde80706fcc";
81+
sha256 = "0ir8ali2vx0j7pipmlfd6k8c973akyy2nmbjrf008fm800zcp7z2";
2882
};
2983
}
3084
{
31-
goPackagePath = "github.com/hashicorp/golang-lru";
85+
goPackagePath = "github.com/sirupsen/logrus";
3286
fetch = {
3387
type = "git";
34-
url = "https://github.com/hashicorp/golang-lru";
35-
rev = "59383c442f7d7b190497e9bb8fc17a48d06cd03f";
36-
sha256 = "0yzwl592aa32vfy73pl7wdc21855w17zssrp85ckw2nisky8rg9c";
88+
url = "https://github.com/sirupsen/logrus";
89+
rev = "947831125f318c2fb34bfc6205ee5d74994deb88";
90+
sha256 = "17y3v3zfzjaw6sl2w9p1f2ai78ma3d5ifbr8wq4hrbjmyy2clrac";
91+
};
92+
}
93+
{
94+
goPackagePath = "github.com/src-d/gcfg";
95+
fetch = {
96+
type = "git";
97+
url = "https://github.com/src-d/gcfg";
98+
rev = "1ac3a1ac202429a54835fe8408a92880156b489d";
99+
sha256 = "044j95skmyrwjw5fwjk6ka32rjgsg0ar0mfp9np19sh1acwv4x4r";
100+
};
101+
}
102+
{
103+
goPackagePath = "github.com/xanzy/ssh-agent";
104+
fetch = {
105+
type = "git";
106+
url = "https://github.com/xanzy/ssh-agent";
107+
rev = "6a3e2ff9e7c564f36873c2e36413f634534f1c44";
108+
sha256 = "1chjlnv5d6svpymxgsr62d992m2xi6jb5lybjc5zn1h3hv1m01av";
37109
};
38110
}
39111
{
40112
goPackagePath = "go.opencensus.io";
41113
fetch = {
42114
type = "git";
43115
url = "https://github.com/census-instrumentation/opencensus-go";
44-
rev = "b4a14686f0a98096416fe1b4cb848e384fb2b22b";
45-
sha256 = "1aidyp301v5ngwsnnc8v1s09vvbsnch1jc4vd615f7qv77r9s7dn";
116+
rev = "84d38db2b42a4fc1eebad7b32616e8f4bd48bd76";
117+
sha256 = "0fladfb5n46v4dqsdr7md75v9hwqgbj6r1vjjrazshnmyq4ks7d5";
118+
};
119+
}
120+
{
121+
goPackagePath = "golang.org/x/crypto";
122+
fetch = {
123+
type = "git";
124+
url = "https://go.googlesource.com/crypto";
125+
rev = "2aa609cf4a9d7d1126360de73b55b6002f9e052a";
126+
sha256 = "1yvis6fqbsd7f356aqyi18f76vnwj3bry6mxqnkvshq4cwrf92il";
46127
};
47128
}
48129
{
49130
goPackagePath = "golang.org/x/net";
50131
fetch = {
51132
type = "git";
52133
url = "https://go.googlesource.com/net";
53-
rev = "da137c7871d730100384dbcf36e6f8fa493aef5b";
54-
sha256 = "1qsiyr3irmb6ii06hivm9p2c7wqyxczms1a9v1ss5698yjr3fg47";
134+
rev = "6afb5195e5aab057fda82e27171243402346b0ad";
135+
sha256 = "1aiz41q2yxgg3dxfkn33ff54vhaxbiwcps9j3ia1xx4cqxim38zw";
55136
};
56137
}
57138
{
58139
goPackagePath = "golang.org/x/oauth2";
59140
fetch = {
60141
type = "git";
61142
url = "https://go.googlesource.com/oauth2";
62-
rev = "0f29369cfe4552d0e4bcddc57cc75f4d7e672a33";
63-
sha256 = "06jwpvx0x2gjn2y959drbcir5kd7vg87k0r1216abk6rrdzzrzi2";
143+
rev = "bf48bf16ab8d622ce64ec6ce98d2c98f916b6303";
144+
sha256 = "1sirdib60zwmh93kf9qrx51r8544k1p9rs5mk0797wibz3m4mrdg";
64145
};
65146
}
66147
{
67148
goPackagePath = "golang.org/x/sys";
68149
fetch = {
69150
type = "git";
70151
url = "https://go.googlesource.com/sys";
71-
rev = "51ab0e2deafac1f46c46ad59cf0921be2f180c3d";
72-
sha256 = "0xdhpckbql3bsqkpc2k5b1cpnq3q1qjqjjq2j3p707rfwb8nm91a";
152+
rev = "d5e6a3e2c0ae16fc7480523ebcb7fd4dd3215489";
153+
sha256 = "0lz7vm5dz2p14fzq2j4m1l9p392cl0fa73aaf45gln07ylfajk4n";
73154
};
74155
}
75156
{
76157
goPackagePath = "golang.org/x/text";
77158
fetch = {
78159
type = "git";
79160
url = "https://go.googlesource.com/text";
80-
rev = "342b2e1fbaa52c93f31447ad2c6abc048c63e475";
81-
sha256 = "0flv9idw0jm5nm8lx25xqanbkqgfiym6619w575p7nrdh0riqwqh";
161+
rev = "929e72ca90deac4784bbe451caf10faa5b256ebe";
162+
sha256 = "0kwyw87bx0rsc5bbqrrg36yv2b7rs4ijs4p4444s8zwzq6sw24y8";
163+
};
164+
}
165+
{
166+
goPackagePath = "gonum.org/v1/gonum";
167+
fetch = {
168+
type = "git";
169+
url = "https://github.com/gonum/gonum";
170+
rev = "833936c7d4c5e9aaf542b3449692efd5ba673699";
171+
sha256 = "110f75q6x30vmk4jsp8cb4s3rhrply14fvc96ivdrw7gp0v9nc24";
82172
};
83173
}
84174
{
85175
goPackagePath = "google.golang.org/api";
86176
fetch = {
87177
type = "git";
88178
url = "https://code.googlesource.com/google-api-go-client";
89-
rev = "069bea57b1be6ad0671a49ea7a1128025a22b73f";
90-
sha256 = "19q2b610lkf3z3y9hn6rf11dd78xr9q4340mdyri7kbijlj2r44q";
179+
rev = "96b6e7d6790a07e2d171e9dfc649c8ff6306a367";
180+
sha256 = "1460kmfqq6n6n481x38lvxs5f39hp4sfcpm7kfqp43vlbgqswps7";
91181
};
92182
}
93183
{
94184
goPackagePath = "google.golang.org/genproto";
95185
fetch = {
96186
type = "git";
97187
url = "https://github.com/google/go-genproto";
98-
rev = "c506a9f9061087022822e8da603a52fc387115a8";
99-
sha256 = "03hh80aqi58dqi5ykj4shk3chwkzrgq2f3k6qs5qhgvmcy79y2py";
188+
rev = "e50cd9704f63023d62cd06a1994b98227fc4d21a";
189+
sha256 = "1392q1dfg4kkfg86w05gsszdlkd0hf424rvich1xzjqbm3ad3lin";
100190
};
101191
}
102192
{
103193
goPackagePath = "google.golang.org/grpc";
104194
fetch = {
105195
type = "git";
106196
url = "https://github.com/grpc/grpc-go";
107-
rev = "977142214c45640483838b8672a43c46f89f90cb";
108-
sha256 = "05wig23l2sil3bfdv19gq62sya7hsabqj9l8pzr1sm57qsvj218d";
197+
rev = "a43f3ee96cf10d74132799c5faaa7182f501d6f8";
198+
sha256 = "1zc4l942hmlvq1ks6g3fz0iaa19dngpsmm6f0iy7z500g16x20m4";
109199
};
110200
}
111201
{
112-
goPackagePath = "gonum.org/v1/gonum";
202+
goPackagePath = "gopkg.in/src-d/go-billy.v4";
113203
fetch = {
114204
type = "git";
115-
url = "https://github.com/gonum/gonum";
116-
rev = "ced62fe5104b907b6c16cb7e575c17b2e62ceddd";
117-
sha256 = "1b7q6haabnp53igpmvr6a2414yralhbrldixx4kbxxg1apy8jdjg";
205+
url = "https://gopkg.in/src-d/go-billy.v4";
206+
rev = "780403cfc1bc95ff4d07e7b26db40a6186c5326e";
207+
sha256 = "0jcyi4ink2njgflp3f2mbl5b86p2w0rh945k5xplcl158i5wkrc6";
118208
};
119209
}
120210
{
121-
goPackagePath = "github.com/sirupsen/logrus";
211+
goPackagePath = "gopkg.in/src-d/go-git.v4";
122212
fetch = {
123213
type = "git";
124-
url = "https://github.com/sirupsen/logrus";
125-
rev = "de736cf91b921d56253b4010270681d33fdf7cb5";
126-
sha256 = "1qixss8m5xy7pzbf0qz2k3shjw0asklm9sj6zyczp7mryrari0aj";
214+
url = "https://gopkg.in/src-d/go-git.v4";
215+
rev = "0d1a009cbb604db18be960db5f1525b99a55d727";
216+
sha256 = "0n4x7r69qrmpss51b3wd3vj4b9jmip4archz3fbqk6q1yyd1pxjb";
217+
};
218+
}
219+
{
220+
goPackagePath = "gopkg.in/warnings.v0";
221+
fetch = {
222+
type = "git";
223+
url = "https://gopkg.in/warnings.v0";
224+
rev = "ec4a0fea49c7b46c2aeb0b51aac55779c607e52b";
225+
sha256 = "1kzj50jn708cingn7a13c2wdlzs6qv89dr2h4zj8d09647vlnd81";
127226
};
128227
}
129228
]

main.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ var version string = "devel"
5555
var (
5656
manifestRegex = regexp.MustCompile(`^/v2/([\w|\-|\.|\_|\/]+)/manifests/([\w|\-|\.|\_]+)$`)
5757
layerRegex = regexp.MustCompile(`^/v2/([\w|\-|\.|\_|\/]+)/blobs/sha256:(\w+)$`)
58+
tagsRegex = regexp.MustCompile(`^/v2/([\w|\-|\.|\_|\/]+)/tags/list$`)
5859
)
5960

6061
// Downloads the popularity information for the package set from the
@@ -184,6 +185,27 @@ func (h *registryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
184185
return
185186
}
186187

188+
tagsMatches := tagsRegex.FindStringSubmatch(r.RequestURI)
189+
if len(tagsMatches) == 2 {
190+
tags, err := h.state.Cfg.Pkgs.Tags()
191+
if err != nil {
192+
writeError(w, 500, "UNKNOWN", "failed to list tags")
193+
194+
log.WithError(err).WithFields(log.Fields{
195+
"image": tagsMatches[1],
196+
}).Error(err)
197+
198+
return
199+
}
200+
manifest, _ := json.Marshal(map[string]interface{}{
201+
"name": tagsMatches[1],
202+
"tags": tags,
203+
})
204+
w.Header().Add("Content-Type", manifestMediaType)
205+
w.Write(manifest)
206+
return
207+
}
208+
187209
log.WithField("uri", r.RequestURI).Info("unsupported registry route")
188210

189211
w.WriteHeader(404)

0 commit comments

Comments
 (0)