-
-
Save method76/59836dbdc63f287d095ce3cee690cd3a to your computer and use it in GitHub Desktop.
Go client to github to get latest release and assets for a given repository
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "encoding/json" | |
| "flag" | |
| "fmt" | |
| "io/ioutil" | |
| "log" | |
| "net/http" | |
| "os" | |
| "regexp" | |
| ) | |
| var login, password, repo, tag, token string | |
| var assets, download bool | |
| func prepareRequest(url string) *http.Request { | |
| req, _ := http.NewRequest("GET", url, nil) | |
| if len(login)+len(password) > 0 { | |
| req.SetBasicAuth(login, password) | |
| } else if len(token) > 0 { | |
| req.Header.Add("Authorization", fmt.Sprintf("token %s", token)) | |
| } | |
| req.Header.Add("User-Agent", "metal3d-go-client") | |
| return req | |
| } | |
| // Download resource from given url, write 1 in chan when finished | |
| func downloadResource(id float64, c chan int) { | |
| defer func() { c <- 1 }() | |
| url := fmt.Sprintf("https://api.github.com/repos/%s/releases/assets/%.0f", repo, id) | |
| fmt.Printf("Start: %s\n", url) | |
| req := prepareRequest(url) | |
| req.Header.Add("Accept", "application/octet-stream") | |
| client := http.Client{} | |
| resp, _ := client.Do(req) | |
| disp := resp.Header.Get("Content-disposition") | |
| re := regexp.MustCompile(`filename=(.+)`) | |
| matches := re.FindAllStringSubmatch(disp, -1) | |
| if len(matches) == 0 || len(matches[0]) == 0 { | |
| log.Println("WTF: ", matches) | |
| log.Println(resp.Header) | |
| log.Println(req) | |
| return | |
| } | |
| disp = matches[0][1] | |
| f, err := os.OpenFile(disp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0664) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| b := make([]byte, 4096) | |
| var i int | |
| for err == nil { | |
| i, err = resp.Body.Read(b) | |
| f.Write(b[:i]) | |
| } | |
| fmt.Printf("Finished: %s -> %s\n", url, disp) | |
| f.Close() | |
| } | |
| func main() { | |
| flag.StringVar(&login, "login", "", "Github Login") | |
| flag.StringVar(&password, "password", "", "Github Password") | |
| flag.StringVar(&repo, "repo", "", "Github repository (eg. yourname/project1)") | |
| flag.BoolVar(&assets, "assets", false, "Print assets urls instead of source download link") | |
| flag.StringVar(&tag, "tag", "", "Get this release tag instead of latest") | |
| flag.StringVar(&token, "token", "", "Use OAUTH2 token") | |
| flag.BoolVar(&download, "dl", false, "Download results in current directory") | |
| flag.Parse() | |
| if len(repo) == 0 { | |
| log.Fatal("No repository provided") | |
| } | |
| // command to call | |
| command := "releases/latest" | |
| if len(tag) > 0 { | |
| command = fmt.Sprintf("releases/tags/%s", tag) | |
| } | |
| url := fmt.Sprintf("https://api.github.com/repos/%s/%s", repo, command) | |
| // create a request with basic-auth | |
| req := prepareRequest(url) | |
| // Add required headers | |
| req.Header.Add("Accept", "application/vnd.github.v3.text-match+json") | |
| req.Header.Add("Accept", "application/vnd.github.moondragon+json") | |
| // call github | |
| client := http.Client{} | |
| resp, err := client.Do(req) | |
| if err != nil { | |
| log.Fatal("Error while making request", err) | |
| } | |
| // status in <200 or >299 | |
| if resp.StatusCode < 200 || resp.StatusCode > 299 { | |
| log.Fatalf("Error: %d %s", resp.StatusCode, resp.Status) | |
| } | |
| bodyText, err := ioutil.ReadAll(resp.Body) | |
| if err != nil { | |
| log.Fatal("Error reading response", err) | |
| } | |
| // prepare result | |
| result := make(map[string]interface{}) | |
| json.Unmarshal(bodyText, &result) | |
| // print download url | |
| results := make([]interface{}, 0) | |
| if !assets { | |
| if download { | |
| results = append(results, result["id"]) | |
| } else { | |
| results = append(results, result["zipball_url"]) | |
| } | |
| } else { | |
| for _, asset := range result["assets"].([]interface{}) { | |
| if download { | |
| results = append(results, asset.(map[string]interface{})["id"]) | |
| } else { | |
| results = append(results, asset.(map[string]interface{})["browser_download_url"]) | |
| } | |
| } | |
| } | |
| if !download { | |
| // only print results | |
| for _, res := range results { | |
| fmt.Println(res) | |
| } | |
| } else { | |
| // Download results - parallel downloading, use channel to syncronize | |
| c := make(chan int) | |
| for _, res := range results { | |
| go downloadResource(res.(float64), c) | |
| } | |
| // wait for downloads end | |
| for i := 0; i < len(results); i++ { | |
| <-c | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment