Files
grafana/pkg/registry/apis/provisioning/webhooks/pullrequest/comment.go
T
Roberto Jiménez Sánchez 1cc21a0705 Provisioning: Make image renderer note optional in PR comments (#113837)
* Provisioning: Remove image renderer note from PR comment template

Removes the 'NOTE: The image renderer is not configured' message from
the pull request comment template when image renderer is unavailable.
This addresses issue #656 in git-ui-sync-project.

- Updated commentTemplateMissingImageRenderer to be empty
- Updated testdata to reflect the change
- All unit tests pass

* Provisioning: Make image renderer note optional in PR comments

Make the image renderer note in pull request comments optional based on
the allowImageRendering configuration flag. When enabled, the note now
includes a link to the setup documentation.

- Add showImageRendererNote boolean field to commenter struct
- Update NewCommenter to accept showImageRendererNote parameter
- Update template to conditionally show note with documentation link
- Pass allowImageRendering from APIBuilder to commenter in register.go
- Update ProvidePullRequestWorker to use cfg.ProvisioningAllowImageRendering
- Add tests to verify note appears/disappears based on flag

Fixes https://github.com/grafana/git-ui-sync-project/issues/656

* Format code with go fmt

* Remove redundant text from image renderer note

Remove 'The image renderer is not configured.' from the note message.
The note now focuses on actionable guidance with the documentation link.

* Fix compilation error: use cfg.ProvisioningAllowImageRendering directly

Cannot access unexported field allowImageRendering from webhooks package.
Use cfg.ProvisioningAllowImageRendering directly since we have access to cfg.
2025-11-14 10:33:28 +01:00

129 lines
3.9 KiB
Go

package pullrequest
import (
"bytes"
"context"
"fmt"
"html/template"
"path/filepath"
"strings"
)
type commenter struct {
templateDashboard *template.Template
templateTable *template.Template
templateRenderInfo *template.Template
showImageRendererNote bool
}
func NewCommenter(showImageRendererNote bool) Commenter {
return &commenter{
templateDashboard: template.Must(template.New("dashboard").Parse(commentTemplateSingleDashboard)),
templateTable: template.Must(template.New("table").Parse(commentTemplateTable)),
templateRenderInfo: template.Must(template.New("setup").Parse(commentTemplateMissingImageRenderer)),
showImageRendererNote: showImageRendererNote,
}
}
func (c *commenter) Comment(ctx context.Context, prRepo PullRequestRepo, pr int, info changeInfo) error {
comment, err := c.generateComment(ctx, info)
if err != nil {
return fmt.Errorf("unable to generate comment text: %w", err)
}
if err := prRepo.CommentPullRequest(ctx, pr, comment); err != nil {
return fmt.Errorf("comment pull request: %w", err)
}
return nil
}
func (c *commenter) generateComment(_ context.Context, info changeInfo) (string, error) {
// TODO: should we comment even if there are no changes?
if len(info.Changes) == 0 {
return "Grafana didn't find any changes in this pull request.", nil
}
var buf bytes.Buffer
if len(info.Changes) == 1 && info.Changes[0].Parsed.GVK.Kind == dashboardKind {
if err := c.templateDashboard.Execute(&buf, info.Changes[0]); err != nil {
return "", fmt.Errorf("unable to execute template: %w", err)
}
} else {
if err := c.templateTable.Execute(&buf, info); err != nil {
return "", fmt.Errorf("unable to execute template: %w", err)
}
}
if info.MissingImageRenderer && c.showImageRendererNote {
if err := c.templateRenderInfo.Execute(&buf, info); err != nil {
return "", fmt.Errorf("unable to execute template: %w", err)
}
}
return strings.TrimSpace(buf.String()), nil
}
const commentTemplateSingleDashboard = `Hey there! 🎉
Grafana spotted some changes to your dashboard.
{{- if and .GrafanaScreenshotURL .PreviewScreenshotURL}}
### Side by Side Comparison of {{.Parsed.Info.Path}}
| Before | After |
|----------|---------|
| ![Before]({{.GrafanaScreenshotURL}}) | ![Preview]({{.PreviewScreenshotURL}}) |
{{- else if .GrafanaScreenshotURL}}
### Original of {{.Title}}
![Original]({{.GrafanaScreenshotURL}})
{{- else if .PreviewScreenshotURL}}
### Preview of {{.Parsed.Info.Path}}
![Preview]({{.PreviewScreenshotURL}})
{{ end}}
{{ if and .GrafanaURL .PreviewURL}}
See the [original]({{.GrafanaURL}}) and [preview]({{.PreviewURL}}) of {{.Parsed.Info.Path}}.
{{- else if .GrafanaURL}}
See the [original]({{.GrafanaURL}}) of {{.Title}}.
{{- else if .PreviewURL}}
See the [preview]({{.PreviewURL}}) of {{.Parsed.Info.Path}}.
{{- end}}
`
const commentTemplateTable = `Hey there! 🎉
Grafana spotted some changes.
| Action | Kind | Resource | Preview |
|--------|------|----------|---------|
{{- range .Changes}}
| {{.Parsed.Action}} | {{.Kind}} | {{.ExistingLink}} | {{ if .PreviewURL}}[preview]({{.PreviewURL}}){{ end }} |
{{- end}}
{{ if .SkippedFiles }}
and {{ .SkippedFiles }} more files.
{{ end}}
`
const commentTemplateMissingImageRenderer = `
NOTE: To enable dashboard previews in pull requests, refer to the [image rendering setup documentation](https://grafana.com/docs/grafana/latest/observability-as-code/provision-resources/git-sync-setup/#configure-webhooks-and-image-rendering).
`
// TODO: does this have some value?
func (f *fileChangeInfo) Kind() string {
if f.Parsed == nil {
return filepath.Ext(f.Change.Path)
}
v := f.Parsed.GVK.Kind
if v == "" {
return filepath.Ext(f.Parsed.Info.Path)
}
return f.Parsed.GVK.Kind
}
// TODO: does this have some value?
func (f *fileChangeInfo) ExistingLink() string {
if f.GrafanaURL != "" {
return fmt.Sprintf("[%s](%s)", f.Title, f.GrafanaURL)
}
return f.Title
}