Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prme-github-source (take 1) #107

Merged
merged 8 commits into from
Aug 12, 2023
Merged
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
File renamed without changes.
2 changes: 1 addition & 1 deletion bin/golangci-lint
1 change: 1 addition & 0 deletions frontend/components/Review/PageChrome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const { pending, data, error } = await useFetch<Review>("/api/review", {
lazy: true,
params: Object.assign({}, route.params, {
refresh: route.query.refresh,
kind: "review",
}),
server: false,
});
Expand Down
16 changes: 14 additions & 2 deletions server/cmd/server/api.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package main

import (
"fmt"

"github.com/pkg/errors"

"github.com/stanistan/present-me/internal/api"
"github.com/stanistan/present-me/internal/github"
"github.com/stanistan/present-me/internal/http"
)
Expand Down Expand Up @@ -47,8 +50,17 @@ var apiRoutes = http.Routes(

// GET /review hydrates the the full review from github.
http.GET("/review", func(r *http.Request) (*http.JSONResponse, error) {
source := github.ReviewAPISource{
ReviewParamsMap: github.NewReviewParamsMap(r.URL.Query()),
params := github.NewReviewParamsMap(r.URL.Query())
var source api.Source
switch params.Kind {
case "review":
source = &github.ReviewAPISource{ReviewParamsMap: params}
case "prme":
source = &github.CommentsAPISource{ReviewParamsMap: params}
case "":
source = &api.ErrSource{Err: fmt.Errorf("missing kind")}
default:
source = &api.ErrSource{Err: fmt.Errorf("invalid kind: %s", params.Kind)}
}

review, err := source.GetReview(r.Context())
Expand Down
31 changes: 14 additions & 17 deletions server/cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"fmt"
"net/http"
"time"

Expand All @@ -15,27 +14,24 @@ import (
"github.com/stanistan/present-me/internal/github"
)

var (
version = "development" // dynamically linked
)
const name = "present-me"

var version = "development" // dynamically linked

func main() {
var config pm.Config
_ = kong.Parse(
&config,
kong.Name("present-me"),
kong.UsageOnError(),
kong.Description(fmt.Sprintf("build version: %s", version)),
)
_ = kong.Parse(&config,
kong.Name(name),
kong.Vars{"version": version},
kong.UsageOnError())

// 0. Standard Deps
// - logger,
// - ctx withLogger
// - disk cache
// - github client
log := config.Logger()
ctx := log.WithContext(context.Background())
// set up our logger
ctx, log := config.Logger(context.Background())

// get our cache setup for the server
diskCache := config.Cache(ctx)

// configure our github client
gh, err := config.GithubClient(ctx)
if err != nil {
log.Fatal().Err(err).Msg("could not configure GH client")
Expand All @@ -47,6 +43,7 @@ func main() {
api := r.PathPrefix("/api").Subrouter()
api.Use(
hlog.NewHandler(log),
hlog.URLHandler("url"),
github.Middleware(gh),
cache.Middleware(diskCache, func(r *http.Request) *cache.Options {
return &cache.Options{
Expand Down
10 changes: 8 additions & 2 deletions server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import (
"github.com/stanistan/present-me/internal/log"
)

// Config is the main configuration wrapper struct for
// the present-me application.
//
// It is basically the DI provider for all of the runtime
// dependencies and how to configure them.
type Config struct {
ServeConfig
Log log.Config `embed:"" prefix:"log-"`
Expand All @@ -23,8 +28,9 @@ func (c *Config) GithubClient(ctx context.Context) (*github.Client, error) {
return g, errors.WithStack(err)
}

func (c *Config) Logger() zerolog.Logger {
return log.NewLogger(c.Log)
func (c *Config) Logger(ctx context.Context) (context.Context, zerolog.Logger) {
l := log.NewLogger(c.Log)
return l.WithContext(ctx), l
}

func (c *Config) Cache(ctx context.Context) *cache.Cache {
Expand Down
2 changes: 1 addition & 1 deletion server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/stanistan/present-me
go 1.20

require (
github.com/alecthomas/kong v0.7.2-0.20230225013903-a9be85c4d3d6
github.com/alecthomas/kong v0.8.0
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0
github.com/cespare/reflex v0.3.1
github.com/google/go-github/v52 v52.0.0
Expand Down
4 changes: 2 additions & 2 deletions server/go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
github.com/alecthomas/kong v0.7.2-0.20230225013903-a9be85c4d3d6 h1:yZxc3zrUYRv+1w6sqPX+0s7lfBasfojCN/SeZ2wueXk=
github.com/alecthomas/kong v0.7.2-0.20230225013903-a9be85c4d3d6/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s=
github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0 h1:5+NghM1Zred9Z078QEZtm28G/kfDfZN/92gkDlLwGVA=
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0/go.mod h1:Xg3xPRN5Mcq6GDqeUVhFbjEWMb4JHCyWEeeBGEYQoTU=
Expand Down
2 changes: 2 additions & 0 deletions server/internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ func (r *Review) GetReview(_ context.Context) (Review, error) {
return *r, nil
}

// Comment (basically a standard card), is a named and annotated code block.
type Comment struct {
Number int `json:"number"`
Title MaybeLinked `json:"title"`
Description string `json:"description"`
CodeBlock CodeBlock `json:"code"`
}

// CodeBlock is the code block and its diff.
type CodeBlock struct {
Content string `json:"content"`
Language string `json:"lang"`
Expand Down
15 changes: 15 additions & 0 deletions server/internal/api/default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package api

import (
"context"
)

type ErrSource struct {
Err error
}

var _ Source = &ErrSource{}

func (s *ErrSource) GetReview(_ context.Context) (Review, error) {
return Review{}, s.Err
}
4 changes: 4 additions & 0 deletions server/internal/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ func WrapErr(err error) *Error {
HttpCode: 500,
}
}

func New(msg string) error {
return errors.New(msg)
}
68 changes: 68 additions & 0 deletions server/internal/github/api_source_prme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package github

import (
"context"
"fmt"
"strings"

"github.com/stanistan/present-me/internal/api"
"github.com/stanistan/present-me/internal/errors"
)

// CommentsAPISource can construct a api.Review from a tag
// on a pull requests' comments.
type CommentsAPISource struct {
ReviewParamsMap ReviewParamsMap
}

var _ api.Source = &CommentsAPISource{}

func (s *CommentsAPISource) GetReview(ctx context.Context) (api.Review, error) {
params, err := ReviewParamsFromMap(s.ReviewParamsMap)
if err != nil {
return api.Review{}, errors.WithStack(err)
}

model, err := FetchReviewModel(ctx, params, CommentMatchesTag(s.ReviewParamsMap.Tag))
if err != nil {
return api.Review{}, errors.WithStack(err)
}

var body []string
if model.PR.Body != nil && *model.PR.Body != "" {
body = append(body, *model.PR.Body)
}

return api.Review{
Title: api.MaybeLinked{
Text: fmt.Sprintf("%s (#%d)", *model.PR.Title, *model.PR.Number),
HRef: *model.PR.Links.HTML.HRef,
},
Links: []api.LabelledLink{
{
Label: "Author",
MaybeLinked: api.MaybeLinked{
Text: *model.PR.User.Login,
HRef: *model.PR.User.HTMLURL,
},
},
{
Label: "Pull Request",
MaybeLinked: api.MaybeLinked{
Text: fmt.Sprintf(
"%s/%s/pull/%d",
params.Owner,
params.Repo,
params.Pull,
),
HRef: *model.PR.HTMLURL,
},
},
},
MetaData: map[string]any{
"params": s.ReviewParamsMap,
},
Body: strings.Join(body, "\n\n---\n\n"),
Comments: transformComments(model.Comments),
}, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package github
import (
"context"
"fmt"
"path"
"strings"

"github.com/stanistan/present-me/internal/api"
Expand All @@ -22,12 +21,11 @@ func (s *ReviewAPISource) GetReview(ctx context.Context) (api.Review, error) {
return api.Review{}, errors.WithStack(err)
}

gh, ok := Ctx(ctx)
if !ok || gh == nil {
return api.Review{}, fmt.Errorf("need gh context")
if params.ReviewID == 0 {
return api.Review{}, errors.New("review must have review id")
}

model, err := params.Model(ctx, gh)
model, err := FetchReviewModel(ctx, params, CommentMatchesReview(params.ReviewID))
if err != nil {
return api.Review{}, errors.WithStack(err)
}
Expand Down Expand Up @@ -81,51 +79,3 @@ func (s *ReviewAPISource) GetReview(ctx context.Context) (api.Review, error) {
Comments: transformComments(model.Comments),
}, nil
}

func transformComments(cs []*PullRequestComment) []api.Comment {
out := make([]api.Comment, len(cs))
for idx, c := range cs {
c := c
out[idx] = api.Comment{
Number: idx + 1,
Title: api.MaybeLinked{
Text: *c.Path,
HRef: *c.HTMLURL,
},
Description: commentBody(*c.Body),
CodeBlock: api.CodeBlock{
IsDiff: true,
Content: *c.DiffHunk,
Language: detectLanguage(*c.Path),
},
}
}
return out
}

func commentBody(s string) string {
return trimStartsWithNumber(s)
}

func detectLanguage(p string) string {
var (
base = path.Base(p)
ext = path.Ext(p)
)

switch ext {
case "":
if base == "Dockerfile" {
return "docker"
}
return "bash"
case ".rs":
return "rust"
case ".vue":
return "html"
case ".Dockerfile":
return "docker"
}

return ext[1:]
}
29 changes: 29 additions & 0 deletions server/internal/github/comment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package github

import "github.com/stanistan/present-me/internal/api"

func transformComments(cs []*PullRequestComment) []api.Comment {
out := make([]api.Comment, len(cs))
for idx, c := range cs {
c := c
out[idx] = api.Comment{
Number: idx + 1,
Title: api.MaybeLinked{
Text: *c.Path,
HRef: *c.HTMLURL,
},
Description: commentBody(*c.Body),
CodeBlock: api.CodeBlock{
IsDiff: true,
Content: *c.DiffHunk,
Language: detectLanguage(*c.Path),
},
}
}
return out
}

func commentBody(s string) string {
out := startsWithNumberRegexp.ReplaceAllString(s, "")
return prmeTagRegexp.ReplaceAllString(out, "")
}
1 change: 0 additions & 1 deletion server/internal/github/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ func (p *diffScanner) filter(lines []string, auto bool) []string {
}

func diffRange(c *PullRequestComment) (int, int, bool, error) {

// - endLine is the line that the comment is on or after,
// - startLine is the beginning line that we'll include in our diff,
// and it looks like github defaults to 4 lines included if there is
Expand Down
Loading