Initial commit

This commit is contained in:
Alexis Vanier
2020-01-09 17:06:03 -05:00
committed by Alexis Vanier
commit ebbf79ce68
23 changed files with 1443 additions and 0 deletions

305
pr/pr.go Normal file
View File

@@ -0,0 +1,305 @@
package pr
import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path"
"sort"
"strconv"
"strings"
"text/tabwriter"
"github.com/avanier/gitea-resource/util"
)
// List returns a slice of PRs
func List(stdinPayload util.STDINPayload) {
var (
err error
stdoutVersions []stdoutVersion
)
if stdinPayload.Source.SkipSSLVerification {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
client := &http.Client{}
req, err := http.NewRequest("GET", composeAllPrURL(stdinPayload.Source), nil)
if !stdinPayload.Source.Insecure && len(stdinPayload.Source.AccessToken) > 0 {
req.Header.Add("Authorization", stdinPayload.Source.AccessToken)
}
response, err := client.Do(req)
util.CheckResponse(response)
/*
CAVEAT EMPTOR
This does not page. So, for some reason if you have more than 50 PRs addeed
since you last checked, or you run this for the first time, and you set version
to `every`, this will only show the 50 first. You can either change Gitea's
number of API items returned, or create a PR a pager here.
https://docs.gitea.io/en-us/api-usage/
*/
if err != nil {
util.HandleError(err)
}
data, _ := ioutil.ReadAll(response.Body)
prs := []pr{} // Slice of PRs
err = json.Unmarshal(data, &prs)
if err != nil {
util.HandleError(err)
}
fmt.Fprintf(os.Stderr, "prs returned: %d\n", len(prs))
fmt.Fprintf(os.Stderr, "minimum version: %s\n", stdinPayload.Version.Number)
prs = filterPRs(prs, stdinPayload.Version.Number)
prs = sortPRs(prs)
table := tabwriter.NewWriter(os.Stderr, 0, 0, 1, ' ', tabwriter.TabIndent)
header := []string{
"Number",
"Url",
"Title",
"Creator",
"Date Created",
"Base Ref",
"Head Ref",
}
if len(prs) > 0 {
fmt.Fprintln(table, strings.Join(header, "\t"))
} else {
fmt.Fprintln(os.Stderr, "no prs detected beyond the last known version")
}
for ind, onePr := range prs {
stdoutVersions = append(stdoutVersions, stdoutVersion{Ref: strconv.Itoa(int(onePr.Number))})
if ind == 0 {
fmt.Printf("\n")
}
lineElems := []string{
fmt.Sprint(onePr.Number),
onePr.URL,
onePr.Title,
extractUser(onePr),
onePr.Created,
onePr.Base.Ref,
onePr.Head.Ref,
}
fmt.Fprintln(table, strings.Join(lineElems, "\t"))
}
err = table.Flush()
if err != nil {
util.HandleError(err)
}
stdoutData, err := json.MarshalIndent(stdoutVersions, "", " ")
if err != nil {
util.HandleError(err)
}
fmt.Fprintln(os.Stdout, string(stdoutData))
}
func composeAllPrURL(sourceConfig util.SourceConfig) string {
urlString := &url.URL{}
if sourceConfig.Insecure {
urlString.Scheme = "http"
} else {
urlString.Scheme = "https"
}
urlString.Host = strings.Join([]string{
sourceConfig.Hostname,
sourceConfig.Port},
":",
)
urlPath := path.Join(
"api",
"v1",
"repos",
sourceConfig.Owner,
sourceConfig.Repo,
"pulls",
)
urlString.Path = urlPath
queryString := url.Values{}
queryString.Set("state", "open")
queryString.Set("sort", "oldest")
urlString.RawQuery = queryString.Encode()
return urlString.String()
}
func composeSinglePrURL(source util.STDINPayload) string {
urlString := &url.URL{}
if source.Source.Insecure {
urlString.Scheme = "http"
} else {
urlString.Scheme = "https"
}
urlString.Host = strings.Join([]string{
source.Source.Hostname,
source.Source.Port},
":",
)
urlPath := path.Join(
"api",
"v1",
"repos",
source.Source.Owner,
source.Source.Repo,
"pulls",
source.Version.Number,
)
urlString.Path = urlPath
return urlString.String()
}
func extractUser(onePr pr) string {
var user string
if onePr.User.FullName != "" {
user = onePr.User.FullName
} else {
user = onePr.User.Username
}
return user
}
func sortPRs(prs []pr) []pr {
sort.SliceStable(prs, func(leftInd, rightInd int) bool {
return prs[leftInd].Number < prs[rightInd].Number
})
return prs
}
func filterPRs(prs []pr, minVersStr string) []pr {
filteredPRs := []pr{}
minVer, err := strconv.ParseInt(minVersStr, 10, 64)
if err != nil {
util.HandleError(err)
}
for _, onePR := range prs {
if int64(onePR.Number) > minVer {
filteredPRs = append(filteredPRs, onePR)
}
}
return filteredPRs
}
// Get fetches the raw json of the PR object from the API and outputs it to a file
func Get(stdinPayload util.STDINPayload, dest string) {
var (
err error
thisPR pr
)
if stdinPayload.Source.SkipSSLVerification {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
client := &http.Client{}
req, err := http.NewRequest("GET", composeSinglePrURL(stdinPayload), nil)
if err != nil {
util.HandleError(err)
}
if !stdinPayload.Source.Insecure && len(stdinPayload.Source.AccessToken) > 0 {
req.Header.Add("Authorization", stdinPayload.Source.AccessToken)
}
response, err := client.Do(req)
util.CheckResponse(response)
data, _ := ioutil.ReadAll(response.Body)
err = json.Unmarshal(data, &thisPR)
if err != nil {
util.HandleError(err)
}
metadataPayload := metadata{
Number: strconv.Itoa(int(thisPR.Number)),
Title: thisPR.Title,
Base: thisPR.Base.Ref,
Head: thisPR.Head.Ref,
CreatedAt: thisPR.Created,
CreatedBy: extractUser(thisPR),
}
stdoutPayload := getStdout{
Version: stdoutVersion{
Ref: strconv.Itoa(int(thisPR.Number)),
},
Metadata: metadataPayload,
}
stdoutData, err := json.MarshalIndent(stdoutPayload, "", " ")
fmt.Fprintln(os.Stdout, string(stdoutData))
rawDestFile := path.Join(
dest,
"pr.json",
)
metaDestFile := path.Join(
dest,
"metadata.json",
)
err = ioutil.WriteFile(rawDestFile, data, 0644)
if err != nil {
util.HandleError(err)
}
fmt.Fprintf(os.Stderr, "raw data written to %s\n", rawDestFile)
err = ioutil.WriteFile(metaDestFile, stdoutData, 0644)
if err != nil {
util.HandleError(err)
}
fmt.Fprintf(os.Stderr, "resource metadata written to %s\n", metaDestFile)
}

37
pr/types.go Normal file
View File

@@ -0,0 +1,37 @@
package pr
type pr struct {
ID int16 `json:"id"`
URL string `json:"url"`
Number int16 `json:"number"`
Title string `json:"title"`
Base struct {
Ref string `json:"ref"`
}
Head struct {
Ref string `json:"ref"`
}
Created string `json:"created_at"`
User struct {
Username string `json:"username,omitempty"`
FullName string `json:"full_name,omitempty"`
}
}
type metadata struct {
Number string `json:"number"`
Title string `json:"title"`
Base string `json:"base"`
Head string `json:"head"`
CreatedAt string `json:"createdAt"`
CreatedBy string `json:"createdBy"`
}
type getStdout struct {
Version stdoutVersion
Metadata metadata
}
type stdoutVersion struct {
Ref string `json:"ref"`
}