mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 15:42:21 +08:00

* Spike: Extras * Attempt to wire it up * Hack * Fix issue with jobs * Wire more things up * Fix more wiring stuff * Remove webhook secret key from main registration * Move secret encryption also outside register * Add TODOs in code * Add more explanations * Move connectors to different package * Move pull request job into webhooks * Separate registration * Remove duplicate files * Fix missing function * Extract webhook repository logic out of the core github repository * Use status patcher in webhook connector * Fix change in go mod * Change hooks signature * Remove TODOs * Remove Webhook methos from go-git * Remove leftover * Fix mistake in OpenAPI spec * Fix some tests * Fix some issues * Fix linting
123 lines
3.8 KiB
Go
123 lines
3.8 KiB
Go
package pullrequest
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
|
|
"github.com/grafana/grafana-app-sdk/logging"
|
|
provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
|
|
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs"
|
|
"github.com/grafana/grafana/pkg/registry/apis/provisioning/repository"
|
|
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"
|
|
)
|
|
|
|
//go:generate mockery --name=PullRequestRepo --structname=MockPullRequestRepo --inpackage --filename=mock_pullrequest_repo.go --with-expecter
|
|
type PullRequestRepo interface {
|
|
Config() *provisioning.Repository
|
|
Read(ctx context.Context, path, ref string) (*repository.FileInfo, error)
|
|
CompareFiles(ctx context.Context, base, ref string) ([]repository.VersionedFileChange, error)
|
|
CommentPullRequest(ctx context.Context, pr int, comment string) error
|
|
}
|
|
|
|
//go:generate mockery --name=Evaluator --structname=MockEvaluator --inpackage --filename=mock_evaluator.go --with-expecter
|
|
type Evaluator interface {
|
|
Evaluate(ctx context.Context, repo repository.Reader, opts provisioning.PullRequestJobOptions, changes []repository.VersionedFileChange, progress jobs.JobProgressRecorder) (changeInfo, error)
|
|
}
|
|
|
|
//go:generate mockery --name=Commenter --structname=MockCommenter --inpackage --filename=mock_commenter.go --with-expecter
|
|
type Commenter interface {
|
|
Comment(ctx context.Context, repo PullRequestRepo, pr int, changeInfo changeInfo) error
|
|
}
|
|
|
|
type PullRequestWorker struct {
|
|
evaluator Evaluator
|
|
commenter Commenter
|
|
}
|
|
|
|
func NewPullRequestWorker(evaluator Evaluator, commenter Commenter) *PullRequestWorker {
|
|
return &PullRequestWorker{
|
|
evaluator: evaluator,
|
|
commenter: commenter,
|
|
}
|
|
}
|
|
|
|
func (c *PullRequestWorker) IsSupported(ctx context.Context, job provisioning.Job) bool {
|
|
return job.Spec.Action == provisioning.JobActionPullRequest
|
|
}
|
|
|
|
func (c *PullRequestWorker) Process(ctx context.Context,
|
|
repo repository.Repository,
|
|
job provisioning.Job,
|
|
progress jobs.JobProgressRecorder,
|
|
) error {
|
|
cfg := repo.Config().Spec
|
|
opts := job.Spec.PullRequest
|
|
if opts == nil {
|
|
return apierrors.NewBadRequest("missing spec.pr")
|
|
}
|
|
|
|
if opts.Ref == "" {
|
|
return apierrors.NewBadRequest("missing spec.ref")
|
|
}
|
|
|
|
// FIXME: this is leaky because it's supposed to be already a PullRequestRepo
|
|
if cfg.GitHub == nil {
|
|
return apierrors.NewBadRequest("expecting github configuration")
|
|
}
|
|
|
|
reader, ok := repo.(repository.Reader)
|
|
if !ok {
|
|
return errors.New("pull request job submitted targeting repository that is not a Reader")
|
|
}
|
|
|
|
prRepo, ok := repo.(PullRequestRepo)
|
|
if !ok {
|
|
return fmt.Errorf("repository is not a pull request repository")
|
|
}
|
|
|
|
logger := logging.FromContext(ctx).With("pr", opts.PR)
|
|
logger.Info("process pull request")
|
|
defer logger.Info("pull request processed")
|
|
|
|
progress.SetMessage(ctx, "listing pull request files")
|
|
// FIXME: this is leaky because it's supposed to be already a PullRequestRepo
|
|
base := cfg.GitHub.Branch
|
|
files, err := prRepo.CompareFiles(ctx, base, opts.Ref)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list pull request files: %w", err)
|
|
}
|
|
|
|
files = onlySupportedFiles(files)
|
|
if len(files) == 0 {
|
|
progress.SetFinalMessage(ctx, "no files to process")
|
|
return nil
|
|
}
|
|
|
|
changeInfo, err := c.evaluator.Evaluate(ctx, reader, *opts, files, progress)
|
|
if err != nil {
|
|
return fmt.Errorf("calculate changes: %w", err)
|
|
}
|
|
|
|
if err := c.commenter.Comment(ctx, prRepo, opts.PR, changeInfo); err != nil {
|
|
return fmt.Errorf("comment pull request: %w", err)
|
|
}
|
|
logger.Info("preview comment added")
|
|
|
|
return nil
|
|
}
|
|
|
|
// Remove files we should not try to process
|
|
func onlySupportedFiles(files []repository.VersionedFileChange) (ret []repository.VersionedFileChange) {
|
|
for _, file := range files {
|
|
if file.Action == repository.FileActionIgnored || resources.IsPathSupported(file.Path) != nil {
|
|
continue
|
|
}
|
|
ret = append(ret, file)
|
|
}
|
|
|
|
return
|
|
}
|