summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Anderson <[email protected]>2017-01-31 14:36:35 -0800
committerDavid Anderson <[email protected]>2017-01-31 14:36:35 -0800
commitaded79682ca01ac8c7fb17449d79f5274e727f2d (patch)
treeae754122bac09493cb5ef046c3bd10d65bde85f8
parent3e6354c147b050cb9b008ae44d68fd1d3d385723 (diff)
Add a deploy step to garbage-collect old packagecloud files.
-rw-r--r--.travis.yml14
-rw-r--r--scripts/prune_old_versions.go128
2 files changed, 139 insertions, 3 deletions
diff --git a/.travis.yml b/.travis.yml
index 9dad151..888f051 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,9 +20,12 @@ script:
--description "TLS SNI router" --url "https://github.com/google/tlsrouter" ./tlsrouter=/usr/bin/tlsrouter
./systemd/tlsrouter.service=/lib/systemd/system/tlsrouter.service
-# Random edit to force travis rebuild
+env:
+ # Packagecloud API key, for prune_old_versions.go
+ - secure: "SRcNwt+45QyPS1w9aGxMg9905Y6d9w4mBM29G6iTTnUB5nD7cAk4m+tf834knGSobVXlWcRnTDW8zrHdQ9yX22dPqCpH5qE+qzTmIvxRHrVJRMmPeYvligJ/9jYfHgQbvuRT8cUpIcpCQAla6rw8nXfKTOE3h8XqMP2hdc3DTVOu2HCfKCNco1tJ7is+AIAnFV2Wpsbb3ZsdKFvHvi2RKUfFaX61J1GNt2/XJIlZs8jC6Y1IAC+ftjql9UsAE/WjZ9fL0Ww1b9/LBIIGHXWI3HpVv9WvlhhIxIlJgOVjmU2lbSuj2w/EBDJ9cd1Qe+wJkT3yKzE1NRsNScVjGg+Ku5igJu/XXuaHkIX01+15BqgPduBYRL0atiNQDhqgBiSyVhXZBX9vsgsp0bgpKaBSF++CV18Q9dara8aljqqS33M3imO3I8JmXU10944QA9Wvu7pCYuIzXxhINcDXRvqxBqz5LnFJGwnGqngTrOCSVS2xn7Y+sjmhe1n5cPCEISlozfa9mPYPvMPp8zg3TbATOOM8CVfcpaNscLqa/+SExN3zMwSanjNKrBgoaQcBzGW5mIgSPxhXkWikBgapiEN7+2Y032Lhqdb9dYjH+EuwcnofspDjjMabWxnuJaln+E3/9vZi2ooQrBEtvymUTy4VMSnqwIX5bU7nPdIuQycdWhk="
+
deploy:
- provider: packagecloud
+- provider: packagecloud
repository: tlsrouter
username: danderson
dist: debian/stretch
@@ -30,5 +33,10 @@ deploy:
token:
secure: gNU3o70EU4oYeIS6pr0K5oLMGqqxrcf41EOv6c/YoHPVdV6Cx4j9NW0/ISgu6a1/Xf2NgWKT5BWwLpAuhmGdALuOz1Ah//YBWd9N8mGHGaC6RpOPDU8/9NkQdBEmjEH9sgX4PNOh1KQ7d7O0OH0g8RqJlJa0MkUYbTtN6KJ29oiUXxKmZM4D/iWB8VonKOnrtx1NwQL8jL8imZyEV/1fknhDwumz2iKeU1le4Neq9zkxwICMLUonmgphlrp+SDb1EOoHxT6cn51bqBQtQUplfC4dN4OQU/CPqE9E1N1noibvN29YA93qfcrjD3I95KT9wzq+3B6he33+kb0Gz+Cj5ypGy4P85l7TuX4CtQg0U3NAlJCk32IfsdjK+o47pdmADij9IIb9yKt+g99FMERkJJY5EInqEsxHlW/vNF5OqQCmpiHstZL4R2XaHEsWh6j77npnjjC1Aea8xZTWr8PTsbSzVkbG7bTmFpZoPH8eEmr4GNuw5gnbi6D1AJDjcA+UdY9s5qZNpzuWOqfhOFxL+zUW+8sHBvcoFw3R+pwHECs2LCL1c0xAC1LtNUnmW/gnwHavtvKkzErjR1P8Xl7obCbeChJjp+b/BcFYlNACldZcuzBAPyPwIdlWVyUonL4bm63upfMEEShiAIDDJ21y7fjsQK7CfPA7g25bpyo+hV8=
on:
- branch: "master"
+ branch: master
+ go: "1.7"
+- provider: script
+ script: go run scripts/prune_old_versions.go -user=danderson -repo=tlsrouter -distro=debian -version=stretch -package=tlsrouter -arch=amd64 -limit=2
+ on:
+ branch: master
go: "1.7"
diff --git a/scripts/prune_old_versions.go b/scripts/prune_old_versions.go
new file mode 100644
index 0000000..43d9997
--- /dev/null
+++ b/scripts/prune_old_versions.go
@@ -0,0 +1,128 @@
+package main
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "net/http"
+ "os"
+ "sort"
+ "strings"
+ "time"
+)
+
+var (
+ user = flag.String("user", "", "username")
+ repo = flag.String("repo", "", "repository name")
+ pkgType = flag.String("pkg-type", "deb", "Package type, e.g. 'deb'")
+ distro = flag.String("distro", "", "distro name, e.g. 'debian'")
+ distroVersion = flag.String("version", "", "distro version, e.g. 'stretch'")
+ pkg = flag.String("package", "", "package name")
+ arch = flag.String("arch", "", "package architecture")
+ limit = flag.Int("limit", 2, "package versions to keep")
+)
+
+func fatalf(msg string, args ...interface{}) {
+ fmt.Printf(msg+"\n", args...)
+ os.Exit(1)
+}
+
+func main() {
+ flag.Parse()
+ if *user == "" {
+ fatalf("missing -user")
+ }
+ if *repo == "" {
+ fatalf("missing -repo")
+ }
+ if *pkgType == "" {
+ fatalf("missing -pkg-type")
+ }
+ if *distro == "" {
+ fatalf("missing -distro")
+ }
+ if *distroVersion == "" {
+ fatalf("missing -version")
+ }
+ if *pkg == "" {
+ fatalf("missing -package")
+ }
+ if *arch == "" {
+ fatalf("missing -arch")
+ }
+ if *limit < 1 {
+ fatalf("limit must be >= 1")
+ }
+
+ files, err := packageVersions(*user, *repo, *pkgType, *distro, *distroVersion, *pkg, *arch)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ if len(files) <= *limit {
+ fmt.Println("Below limit, no packages deleted")
+ return
+ }
+ delete := files[:len(files)-*limit]
+ keep := files[len(files)-*limit:]
+ if err = deletePackages(delete); err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+
+ fmt.Printf("Deleted:\n\n%s\n\nKept:\n\n%s\n", strings.Join(delete, "\n"), strings.Join(keep, "\n"))
+}
+
+type packageMeta struct {
+ Created time.Time `json:"created_at"`
+ Filename string `json:"filename"`
+}
+
+type metaSort []packageMeta
+
+func (m metaSort) Len() int { return len(m) }
+func (m metaSort) Less(i, j int) bool { return m[i].Created.Before(m[j].Created) }
+func (m metaSort) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
+
+func packageVersions(user, repo, typ, distro, version, pkgname, arch string) ([]string, error) {
+ url := fmt.Sprintf("https://%s:@packagecloud.io/api/v1/repos/%s/%s/package/%s/%s/%s/%s/%s/versions.json", os.Getenv("PACKAGECLOUD_API_KEY"), user, repo, typ, distro, version, pkgname, arch)
+ resp, err := http.Get(url)
+ if err != nil {
+ return nil, fmt.Errorf("get versions.json: %s", err)
+ }
+ defer resp.Body.Close()
+
+ var files []packageMeta
+ if err := json.NewDecoder(resp.Body).Decode(&files); err != nil {
+ return nil, fmt.Errorf("decode versions.json: %s", err)
+ }
+
+ // Newest first
+ sort.Sort(metaSort(files))
+
+ var ret []string
+ for _, meta := range files {
+ ret = append(ret, fmt.Sprintf("/api/v1/repos/%s/%s/%s/%s/%s", user, repo, distro, version, meta.Filename))
+ }
+
+ return ret, nil
+}
+
+func deletePackages(urls []string) error {
+ for _, url := range urls {
+ fullURL := fmt.Sprintf("https://%s:@packagecloud.io%s", os.Getenv("PACKAGECLOUD_API_KEY"), url)
+ req, err := http.NewRequest("DELETE", fullURL, nil)
+ if err != nil {
+ return fmt.Errorf("build delete request for %s: %s", url, err)
+ }
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return fmt.Errorf("delete %s: %s", url, err)
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != 200 {
+ return fmt.Errorf("delete %s: %s", url, resp.Status)
+ }
+ }
+ return nil
+}