Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"io"
"net/http"
"os"
"reflect"
"strings"
)

const (
Expand Down Expand Up @@ -99,15 +101,29 @@ func DoAuthRequest(method, url, bodyType, token string, headers map[string]strin
}

func GithubGet(uri string, v interface{}) error {
resp, err := http.Get(ApiURL() + uri)
vv := reflect.ValueOf(v)
if !(vv.Kind() == reflect.Ptr && vv.Elem().Kind() == reflect.Slice) {
return fmt.Errorf("v param must be a pointer to a slice")
}

return githubGet(uri, v, false)
}

func githubGet(uri string, v interface{}, isURL bool) error {
url := uri
if !isURL {
url = ApiURL() + uri
}

resp, err := http.Get(url)
if resp != nil {
defer resp.Body.Close()
}
if err != nil {
return fmt.Errorf("could not fetch releases, %v", err)
}

vprintln("GET", ApiURL()+uri, "->", resp)
vprintln("GET", url, "->", resp)

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("github did not response with 200 OK but with %v", resp.Status)
Expand All @@ -119,9 +135,21 @@ func GithubGet(uri string, v interface{}) error {
r = io.TeeReader(resp.Body, os.Stdout)
}

if err = json.NewDecoder(r).Decode(v); err != nil {
vv := reflect.ValueOf(v).Elem()
sub := reflect.New(vv.Type())
if err = json.NewDecoder(r).Decode(sub.Interface()); err != nil {
return fmt.Errorf("could not unmarshall JSON into Release struct, %v", err)
}
vv.Set(reflect.AppendSlice(vv, sub.Elem()))

linkHeader := resp.Header.Get("Link")
if linkHeader == "" {
return nil
}
links := parseHdrLink(linkHeader)
if nextURL, ok := links["next"]; ok {
return githubGet(nextURL, v, true)
}

return nil
}
Expand All @@ -133,3 +161,14 @@ func ApiURL() string {
return EnvApiEndpoint
}
}

func parseHdrLink(linkField string) map[string]string {
links := make(map[string]string)

for _, l := range strings.Split(linkField, ", ") {
e := strings.Split(l, "; rel=")
links[strings.Trim(e[1], `"`)] = strings.Trim(e[0], "<>")
}

return links
}
65 changes: 65 additions & 0 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,68 @@ func httpDelete(url, token string) (*http.Response, error) {

return resp, nil
}

func publishcmd(opt Options) error {
cmdopt := opt.Publish
user := nvls(cmdopt.User, EnvUser)
repo := nvls(cmdopt.Repo, EnvRepo)
token := nvls(cmdopt.Token, EnvToken)
tag := cmdopt.Tag

vprintln("publishing...")

if err := ValidateCredentials(user, repo, token, tag); err != nil {
return err
}

/* look up the release */
vprintf("%v/%v/%v: getting information for the release\n", user, repo, tag)
release, err := ReleaseOfTag(user, repo, tag, token)
if err != nil {
return err
}

vprintf("release %v has id %v\n", tag, release.Id)

/* the release create struct works for editing releases as well */
params := ReleaseCreate{
TagName: release.TagName,
Name: release.Name,
Body: release.Description,
Draft: false,
Prerelease: release.Prerelease,
}

/* encode the parameters as JSON, as required by the github API */
payload, err := json.Marshal(params)
if err != nil {
return fmt.Errorf("can't encode release edit params, %v", err)
}

uri := fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, release.Id)
resp, err := DoAuthRequest("PATCH", ApiURL()+uri, "application/json",
token, nil, bytes.NewReader(payload))
if err != nil {
return fmt.Errorf("while submitting %v, %v", string(payload), err)
}
defer resp.Body.Close()

vprintln("RESPONSE:", resp)
if resp.StatusCode != http.StatusOK {
if resp.StatusCode == 422 {
return fmt.Errorf("github returned %v (this is probably because the release already exists)",
resp.Status)
}
return fmt.Errorf("github returned unexpected status code %v", resp.Status)
}

if VERBOSITY != 0 {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("error while reading response, %v", err)
}
vprintln("BODY:", string(body))
}

return nil
}
7 changes: 7 additions & 0 deletions github-release.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ type Options struct {
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
Tag string `goptions:"-t, --tag, description='Git tag to query (optional)'"`
} `goptions:"info"`
Publish struct {
Token string `goptions:"-s, --security-token, description='Github token ($GITHUB_TOKEN if set). required if repo is private.'"`
User string `goptions:"-u, --user, description='Github user (required if $GITHUB_USER not set)'"`
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
Tag string `goptions:"-t, --tag, description='Git tag to query (optional)'"`
} `goptions:"publish"`
}

type Command func(Options) error
Expand All @@ -75,6 +81,7 @@ var commands = map[goptions.Verbs]Command{
"edit": editcmd,
"delete": deletecmd,
"info": infocmd,
"publish": publishcmd,
}

var (
Expand Down