Skip to content

Instantly share code, notes, and snippets.

@islishude
Created December 2, 2019 06:51
Show Gist options
  • Save islishude/a534027fb950b1ee8c8fcba7ff79935b to your computer and use it in GitHub Desktop.
Save islishude/a534027fb950b1ee8c8fcba7ff79935b to your computer and use it in GitHub Desktop.
github latest release
package github
import (
"context"
"encoding/json"
"net/http"
)
// Remote remote git server
type Remote struct {
client *http.Client
}
// New creates new client
func New(client *http.Client) *Remote {
if client == nil {
client = http.DefaultClient
}
return &Remote{client}
}
// Latest gets latest tag
func (r Remote) Latest(ctx context.Context, url string) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return "", err
}
req.Header.Set("Accept", "application/json")
resp, err := r.client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
var data struct {
Tag string `json:"tag_name"`
}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return "", err
}
return data.Tag, nil
}
package github
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
func TestRemote_Latest(t *testing.T) {
handler := http.NewServeMux()
handler.HandleFunc("/timeout", func(w http.ResponseWriter, req *http.Request) {
<-time.After(200 * time.Millisecond)
})
handler.HandleFunc("/invalidjson", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "%s", "hello,world")
})
handler.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
w.Write([]byte(`{"tag_name": "v0.18.0"}`))
})
testserver := httptest.NewServer(handler)
defer testserver.Close()
testclient := New(testserver.Client())
// test timeout
{
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
_, err := testclient.Latest(ctx, testserver.URL+"/timeout")
if !strings.Contains(err.Error(), context.DeadlineExceeded.Error()) {
t.Errorf("Want error %s but got %s", context.DeadlineExceeded, err)
}
}
// test invalid request
{
if _, err := New(nil).Latest(nil, ""); err.Error() != "net/http: nil Context" {
t.Errorf("Want error nil Context but got %s", err)
}
}
// test invaid json
{
_, err := testclient.Latest(context.Background(), testserver.URL+"/invalidjson")
if _, ok := err.(*json.SyntaxError); !ok {
t.Errorf("want json.Syntax error")
}
}
// test successful
{
tag, err := testclient.Latest(context.Background(), testserver.URL)
if err != nil {
t.Errorf("Want no errors but got %s", err)
}
if tag != "v0.18.0" {
t.Errorf("Want v0.18.0 but got %s", tag)
}
}
// e2e testing
{
if testing.Short() {
return
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
const bitcoin = "https://github.com/bitcoin/bitcoin/releases/latest"
tag, err := New(nil).Latest(ctx, bitcoin)
if err != nil {
t.Errorf("got error %s", err)
}
if tag == "" {
t.Errorf("want non empty tag")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment