POC/Provisioning/Jobs: Move PR options to their own object and add resource summary (#99489)

This commit is contained in:
Ryan McKinley authored and GitHub committed 2025-01-24 14:55:45 +03:00
1 parent bd201abc63
commit 5cdaf77bc9
12 files changed
+402 -90

No files matched your search

+27 -3
View File
@@ -63,6 +63,14 @@ type JobSpec struct {
// The the repository reference (for now also in labels)
Repository string `json:"repository"`
// Pull request options
PullRequest *PullRequestOptions `json:"pr,omitempty"`
// Required when the action is `export`
Export *ExportOptions `json:"export,omitempty"`
}
type PullRequestOptions struct {
// The branch of commit hash
Ref string `json:"ref,omitempty"`
@@ -72,9 +80,6 @@ type JobSpec struct {
// URL to the originator (eg, PR URL)
URL string `json:"url,omitempty"`
// Required when the action is `export`
Export *ExportOptions `json:"export,omitempty"`
}
type ExportOptions struct {
@@ -101,6 +106,25 @@ type JobStatus struct {
// Optional value 0-100 that can be set while running
Progress float64 `json:"progress,omitempty"`
// Summary of processed actions
Summary []JobResourceSummary `json:"summary,omitempty"`
}
type JobResourceSummary struct {
Group string `json:"group,omitempty"`
Resource string `json:"resource,omitempty"`
Create int64 `json:"create,omitempty"`
Update int64 `json:"update,omitempty"`
Delete int64 `json:"delete,omitempty"`
// No action required (useful for sync)
Noop int64 `json:"noop,omitempty"`
// Report errors for this resource type
// This may not be an exhaustive list and recommend looking at the logs for more info
Errors []string `json:"errors,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -283,9 +283,35 @@ func (in *JobList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JobResourceSummary) DeepCopyInto(out *JobResourceSummary) {
*out = *in
if in.Errors != nil {
in, out := &in.Errors, &out.Errors
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JobResourceSummary.
func (in *JobResourceSummary) DeepCopy() *JobResourceSummary {
if in == nil {
return nil
}
out := new(JobResourceSummary)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JobSpec) DeepCopyInto(out *JobSpec) {
*out = *in
if in.PullRequest != nil {
in, out := &in.PullRequest, &out.PullRequest
*out = new(PullRequestOptions)
**out = **in
}
if in.Export != nil {
in, out := &in.Export, &out.Export
*out = new(ExportOptions)
@@ -312,6 +338,13 @@ func (in *JobStatus) DeepCopyInto(out *JobStatus) {
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Summary != nil {
in, out := &in.Summary, &out.Summary
*out = make([]JobResourceSummary, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
@@ -357,6 +390,22 @@ func (in *LocalRepositoryConfig) DeepCopy() *LocalRepositoryConfig {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PullRequestOptions) DeepCopyInto(out *PullRequestOptions) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PullRequestOptions.
func (in *PullRequestOptions) DeepCopy() *PullRequestOptions {
if in == nil {
return nil
}
out := new(PullRequestOptions)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Repository) DeepCopyInto(out *Repository) {
*out = *in
@@ -26,10 +26,12 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HistoryList": schema_pkg_apis_provisioning_v0alpha1_HistoryList(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Job": schema_pkg_apis_provisioning_v0alpha1_Job(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobList": schema_pkg_apis_provisioning_v0alpha1_JobList(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobResourceSummary": schema_pkg_apis_provisioning_v0alpha1_JobResourceSummary(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobSpec": schema_pkg_apis_provisioning_v0alpha1_JobSpec(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobStatus": schema_pkg_apis_provisioning_v0alpha1_JobStatus(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.LintIssue": schema_pkg_apis_provisioning_v0alpha1_LintIssue(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.LocalRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_LocalRepositoryConfig(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.PullRequestOptions": schema_pkg_apis_provisioning_v0alpha1_PullRequestOptions(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Repository": schema_pkg_apis_provisioning_v0alpha1_Repository(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryList": schema_pkg_apis_provisioning_v0alpha1_RepositoryList(ref),
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositorySpec": schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref),
@@ -579,6 +581,70 @@ func schema_pkg_apis_provisioning_v0alpha1_JobList(ref common.ReferenceCallback)
}
}
func schema_pkg_apis_provisioning_v0alpha1_JobResourceSummary(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"group": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"resource": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"create": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
Format: "int64",
},
},
"update": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
Format: "int64",
},
},
"delete": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
Format: "int64",
},
},
"noop": {
SchemaProps: spec.SchemaProps{
Description: "No action required (useful for sync)",
Type: []string{"integer"},
Format: "int64",
},
},
"errors": {
SchemaProps: spec.SchemaProps{
Description: "Report errors for this resource type This may not be an exhaustive list and recommend looking at the logs for more info",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
},
},
},
}
}
func schema_pkg_apis_provisioning_v0alpha1_JobSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -602,31 +668,10 @@ func schema_pkg_apis_provisioning_v0alpha1_JobSpec(ref common.ReferenceCallback)
Format: "",
},
},
"ref": {
SchemaProps: spec.SchemaProps{
Description: "The branch of commit hash",
Type: []string{"string"},
Format: "",
},
},
"pr": {
SchemaProps: spec.SchemaProps{
Description: "Pull request number (when appropriate)",
Type: []string{"integer"},
Format: "int32",
},
},
"hash": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"url": {
SchemaProps: spec.SchemaProps{
Description: "URL to the originator (eg, PR URL)",
Type: []string{"string"},
Format: "",
Description: "Pull request options",
Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.PullRequestOptions"),
},
},
"export": {
@@ -640,7 +685,7 @@ func schema_pkg_apis_provisioning_v0alpha1_JobSpec(ref common.ReferenceCallback)
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ExportOptions"},
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ExportOptions", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.PullRequestOptions"},
}
}
@@ -698,9 +743,25 @@ func schema_pkg_apis_provisioning_v0alpha1_JobStatus(ref common.ReferenceCallbac
Format: "double",
},
},
"summary": {
SchemaProps: spec.SchemaProps{
Description: "Summary of processed actions",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobResourceSummary"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobResourceSummary"},
}
}
@@ -758,6 +819,45 @@ func schema_pkg_apis_provisioning_v0alpha1_LocalRepositoryConfig(ref common.Refe
}
}
func schema_pkg_apis_provisioning_v0alpha1_PullRequestOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"ref": {
SchemaProps: spec.SchemaProps{
Description: "The branch of commit hash",
Type: []string{"string"},
Format: "",
},
},
"pr": {
SchemaProps: spec.SchemaProps{
Description: "Pull request number (when appropriate)",
Type: []string{"integer"},
Format: "int32",
},
},
"hash": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"url": {
SchemaProps: spec.SchemaProps{
Description: "URL to the originator (eg, PR URL)",
Type: []string{"string"},
Format: "",
},
},
},
},
},
}
}
func schema_pkg_apis_provisioning_v0alpha1_Repository(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -1,12 +1,15 @@
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,HealthStatus,Message
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,HistoryItem,Authors
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobResourceSummary,Errors
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobStatus,Errors
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobStatus,Summary
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositoryStatus,Stats
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,ResourceWrapper,Errors
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,ResourceWrapper,Lint
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,SyncStatus,Message
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,TestResults,Errors
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,WebhookStatus,SubscribedEvents
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobSpec,PullRequest
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitHub
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,SyncStatus,JobID
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,WebhookResponse,Message
@@ -23,6 +23,11 @@ func (s *dummyExporter) Export(ctx context.Context,
logger.Info("start export", "folder", options.Folder)
size := 5 + rand.IntN(15)
dashboards := provisioning.JobResourceSummary{
Group: "dashboard.grafana.app",
Resource: "dashboards",
}
status := provisioning.JobStatus{
State: provisioning.JobStateWorking,
Message: "exporting..." + repo.Config().Spec.Title,
@@ -39,6 +44,23 @@ func (s *dummyExporter) Export(ctx context.Context,
sleep := time.Duration(400+rand.IntN(800)) * time.Millisecond
status.Message, _ = util.GetRandomString(rand.IntN(10 + 15))
time.Sleep(sleep)
for j := 0; j < (4 + rand.IntN(10)); j++ {
switch rand.IntN(9) {
case 0, 1, 2:
dashboards.Create++
case 3, 4:
dashboards.Update++
case 5:
dashboards.Delete++
case 6, 7, 8:
dashboards.Noop++
}
}
status.Summary = []provisioning.JobResourceSummary{
dashboards,
}
err = progress(status)
if err != nil {
return nil, err
@@ -15,6 +15,14 @@ import (
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"
)
type PullRequestWorker interface {
ProcessPullRequest(ctx context.Context,
repo repository.Repository,
options provisioning.PullRequestOptions,
progress func(provisioning.JobStatus) error,
) (*provisioning.JobStatus, error)
}
// resourcePreview represents a resource that has changed in a pull request.
type resourcePreview struct {
Filename string
@@ -65,7 +73,7 @@ type PreviewRenderer interface {
RenderDashboardPreview(ctx context.Context, path string, ref string) (string, error)
}
type PullRequestCommenter struct {
type pullRequestCommenter struct {
repo PullRequestRepo
parser *resources.Parser
lintTemplate *template.Template
@@ -79,7 +87,7 @@ func NewPullRequestCommenter(
parser *resources.Parser,
renderer PreviewRenderer,
baseURL *url.URL,
) (*PullRequestCommenter, error) {
) (PullRequestWorker, error) {
lintTemplate, err := template.New("comment").Parse(lintDashboardIssuesTemplate)
if err != nil {
return nil, fmt.Errorf("parse lint comment template: %w", err)
@@ -89,7 +97,7 @@ func NewPullRequestCommenter(
return nil, fmt.Errorf("parse previews comment template: %w", err)
}
return &PullRequestCommenter{
return &pullRequestCommenter{
repo: repo,
parser: parser,
lintTemplate: lintTemplate,
@@ -99,40 +107,51 @@ func NewPullRequestCommenter(
}, nil
}
func (c *PullRequestCommenter) Process(ctx context.Context, job provisioning.Job) error {
if job.Spec.Action != provisioning.JobActionPullRequest {
return errors.New("job is not a pull request")
}
func (c *pullRequestCommenter) ProcessPullRequest(ctx context.Context,
repo repository.Repository,
options provisioning.PullRequestOptions,
progress func(provisioning.JobStatus) error,
) (*provisioning.JobStatus, error) {
cfg := c.repo.Config().Spec
// TODO: clean specification to have better options
if !(cfg.Linting && cfg.GitHub.PullRequestLinter) &&
!cfg.GitHub.GenerateDashboardPreviews {
return nil
return &provisioning.JobStatus{
State: provisioning.JobStateSuccess,
Message: "linting and previews are not required",
}, nil
}
logger := logging.FromContext(ctx).With("pr", job.Spec.PR)
logger := logging.FromContext(ctx).With("pr", options.PR)
logger.Info("process pull request")
defer logger.Info("pull request processed")
spec := job.Spec
base := cfg.GitHub.Branch
ref := spec.Hash
ref := options.Hash
// list pull requests changes files
files, err := c.repo.CompareFiles(ctx, base, ref)
if err != nil {
return fmt.Errorf("failed to list pull request files: %w", err)
return &provisioning.JobStatus{
State: provisioning.JobStateError,
Message: fmt.Sprintf("failed to list pull request files: %s", err.Error()),
}, nil
}
// clear all previous comments
if err := c.repo.ClearAllPullRequestFileComments(ctx, spec.PR); err != nil {
return fmt.Errorf("failed to clear pull request comments: %w", err)
if err := c.repo.ClearAllPullRequestFileComments(ctx, options.PR); err != nil {
return &provisioning.JobStatus{
State: provisioning.JobStateError,
Message: fmt.Sprintf("failed to clear pull request comments: %+v", err),
}, nil
}
if len(files) == 0 {
logger.Info("no files to process")
return nil
return &provisioning.JobStatus{
State: provisioning.JobStateSuccess,
Message: "no files to process",
}, nil
}
previews := make([]resourcePreview, 0, len(files))
@@ -145,7 +164,10 @@ func (c *PullRequestCommenter) Process(ctx context.Context, job provisioning.Job
logger := logger.With("file", f.Path)
fileInfo, err := c.repo.Read(ctx, f.Path, ref)
if err != nil {
return fmt.Errorf("failed to read file %s: %w", f.Path, err)
return &provisioning.JobStatus{
State: provisioning.JobStateError,
Message: fmt.Sprintf("failed to read file %s: %+v", f.Path, err),
}, nil
}
parsed, err := c.parser.Parse(ctx, fileInfo, true)
@@ -161,11 +183,11 @@ func (c *PullRequestCommenter) Process(ctx context.Context, job provisioning.Job
if cfg.Linting && cfg.GitHub.PullRequestLinter && len(parsed.Lint) > 0 && f.Action != repository.FileActionDeleted {
var buf bytes.Buffer
if err := c.lintTemplate.Execute(&buf, parsed.Lint); err != nil {
return fmt.Errorf("execute lint comment template: %w", err)
return nil, fmt.Errorf("execute lint comment template: %w", err)
}
if err := c.repo.CommentPullRequestFile(ctx, spec.PR, f.Path, ref, buf.String()); err != nil {
return fmt.Errorf("comment pull request file %s: %w", f.Path, err)
if err := c.repo.CommentPullRequestFile(ctx, options.PR, f.Path, ref, buf.String()); err != nil {
return nil, fmt.Errorf("comment pull request file %s: %w", f.Path, err)
}
logger.Info("lint comment added")
@@ -180,23 +202,23 @@ func (c *PullRequestCommenter) Process(ctx context.Context, job provisioning.Job
switch f.Action {
case repository.FileActionCreated:
preview.PreviewURL = c.previewURL(ref, f.Path, spec.URL)
preview.PreviewURL = c.previewURL(ref, f.Path, options.URL)
case repository.FileActionUpdated:
preview.OriginalURL = c.previewURL(base, f.Path, spec.URL)
preview.PreviewURL = c.previewURL(ref, f.Path, spec.URL)
preview.OriginalURL = c.previewURL(base, f.Path, options.URL)
preview.PreviewURL = c.previewURL(ref, f.Path, options.URL)
case repository.FileActionRenamed:
preview.OriginalURL = c.previewURL(base, f.PreviousPath, spec.URL)
preview.PreviewURL = c.previewURL(ref, f.Path, spec.URL)
preview.OriginalURL = c.previewURL(base, f.PreviousPath, options.URL)
preview.PreviewURL = c.previewURL(ref, f.Path, options.URL)
case repository.FileActionDeleted:
preview.OriginalURL = c.previewURL(base, f.Path, spec.URL)
preview.OriginalURL = c.previewURL(base, f.Path, options.URL)
default:
return fmt.Errorf("unknown file action: %s", f.Action)
return nil, fmt.Errorf("unknown file action: %s", f.Action)
}
if cfg.GitHub.GenerateDashboardPreviews && f.Action != repository.FileActionDeleted {
screenshotURL, err := c.renderer.RenderDashboardPreview(ctx, f.Path, ref)
if err != nil {
return fmt.Errorf("render dashboard preview: %w", err)
return nil, fmt.Errorf("render dashboard preview: %w", err)
}
preview.PreviewScreenshotURL = screenshotURL
@@ -209,21 +231,24 @@ func (c *PullRequestCommenter) Process(ctx context.Context, job provisioning.Job
if len(previews) > 0 && cfg.GitHub.GenerateDashboardPreviews {
var buf bytes.Buffer
if err := c.prevTemplate.Execute(&buf, previews); err != nil {
return fmt.Errorf("execute previews comment template: %w", err)
return nil, fmt.Errorf("execute previews comment template: %w", err)
}
if err := c.repo.CommentPullRequest(ctx, spec.PR, buf.String()); err != nil {
return fmt.Errorf("comment pull request: %w", err)
if err := c.repo.CommentPullRequest(ctx, options.PR, buf.String()); err != nil {
return nil, fmt.Errorf("comment pull request: %w", err)
}
logger.Info("previews comment added", "number", len(previews))
}
return nil
return &provisioning.JobStatus{
State: provisioning.JobStateSuccess,
Message: "finished", // can update with useful feedback
}, nil
}
// previewURL returns the URL to preview the file in Grafana
func (c *PullRequestCommenter) previewURL(ref, filePath, pullRequestURL string) string {
func (c *pullRequestCommenter) previewURL(ref, filePath, pullRequestURL string) string {
// Copy the baseURL to modify path and query
baseURL := *c.baseURL
baseURL = *baseURL.JoinPath("/admin/provisioning", c.repo.Config().GetName(), "dashboard/preview", filePath)
@@ -6,6 +6,7 @@ import (
"net/url"
"time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/endpoints/request"
@@ -159,14 +160,17 @@ func (g *JobWorker) Process(ctx context.Context, job provisioning.Job, progress
id: id,
}
options := job.Spec.PullRequest
if options == nil {
return nil, apierrors.NewBadRequest("missing spec.pr")
}
commenter, err := NewPullRequestCommenter(prRepo, parser, renderer, baseURL)
if err != nil {
return nil, fmt.Errorf("error creating pull request commenter: %w", err)
}
return commenter.ProcessPullRequest(ctx, repo, *options, progress)
if err := commenter.Process(ctx, job); err != nil {
return nil, fmt.Errorf("error processing pull request: %w", err)
}
case provisioning.JobActionExport:
if job.Spec.Export == nil {
return &provisioning.JobStatus{
@@ -522,10 +522,12 @@ func (r *githubRepository) parsePullRequestEvent(event *github.PullRequestEvent)
Job: &provisioning.JobSpec{
Repository: r.Config().GetName(),
Action: provisioning.JobActionPullRequest,
URL: pr.GetHTMLURL(),
PR: pr.GetNumber(),
Ref: pr.GetHead().GetRef(),
Hash: pr.GetHead().GetSHA(),
PullRequest: &provisioning.PullRequestOptions{
URL: pr.GetHTMLURL(),
PR: pr.GetNumber(),
Ref: pr.GetHead().GetRef(),
Hash: pr.GetHead().GetSHA(),
},
},
}, nil
}
@@ -68,10 +68,12 @@ func TestParseWebhooks(t *testing.T) {
Job: &provisioning.JobSpec{
Repository: "unit-test-repo",
Action: provisioning.JobActionPullRequest,
Ref: "dashboard/1733653266690",
Hash: "ab5446a53df9e5f8bdeed52250f51fad08e822bc",
PR: 12,
URL: "https://github.com/grafana/git-ui-sync-demo/pull/12",
PullRequest: &provisioning.PullRequestOptions{
Ref: "dashboard/1733653266690",
Hash: "ab5446a53df9e5f8bdeed52250f51fad08e822bc",
PR: 12,
URL: "https://github.com/grafana/git-ui-sync-demo/pull/12",
},
},
}},
{"push", "different_branch", provisioning.WebhookResponse{
@@ -43,7 +43,7 @@ func TestIntegrationProvisioning(t *testing.T) {
AppModeProduction: false, // required for experimental APIs
EnableFeatureToggles: []string{
featuremgmt.FlagProvisioning,
featuremgmt.FlagKubernetesFolders, // Required for tests that deal with folders.
featuremgmt.FlagKubernetesFoldersServiceV2, // Required for tests that deal with folders.
featuremgmt.FlagUnifiedStorageSearch,
},
PermittedProvisioningPaths: ".|" + provisioningPath,
+82 -15
View File
@@ -3782,10 +3782,47 @@
}
]
},
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobResourceSummary": {
"type": "object",
"properties": {
"create": {
"type": "integer",
"format": "int64"
},
"delete": {
"type": "integer",
"format": "int64"
},
"errors": {
"description": "Report errors for this resource type This may not be an exhaustive list and recommend looking at the logs for more info",
"type": "array",
"items": {
"type": "string",
"default": ""
}
},
"group": {
"type": "string"
},
"noop": {
"description": "No action required (useful for sync)",
"type": "integer",
"format": "int64"
},
"resource": {
"type": "string"
},
"update": {
"type": "integer",
"format": "int64"
}
}
},
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobSpec": {
"type": "object",
"required": [
"action"
"action",
"repository"
],
"properties": {
"action": {
@@ -3806,21 +3843,18 @@
}
]
},
"hash": {
"type": "string"
},
"pr": {
"description": "Pull request number (when appropriate)",
"type": "integer",
"format": "int32"
"description": "Pull request options",
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.PullRequestOptions"
}
]
},
"ref": {
"description": "The branch of commit hash",
"type": "string"
},
"url": {
"description": "URL to the originator (eg, PR URL)",
"type": "string"
"repository": {
"description": "The the repository reference (for now also in labels)",
"type": "string",
"default": ""
}
}
},
@@ -3843,7 +3877,7 @@
"type": "string"
},
"progress": {
"description": "Optional value 0-1 that can be set while running",
"description": "Optional value 0-100 that can be set while running",
"type": "number",
"format": "double"
},
@@ -3860,6 +3894,18 @@
"success",
"working"
]
},
"summary": {
"description": "Summary of processed actions",
"type": "array",
"items": {
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobResourceSummary"
}
]
}
}
}
},
@@ -3901,6 +3947,27 @@
}
}
},
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.PullRequestOptions": {
"type": "object",
"properties": {
"hash": {
"type": "string"
},
"pr": {
"description": "Pull request number (when appropriate)",
"type": "integer",
"format": "int32"
},
"ref": {
"description": "The branch of commit hash",
"type": "string"
},
"url": {
"description": "URL to the originator (eg, PR URL)",
"type": "string"
}
}
},
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository": {
"description": "When this code is changed, make sure to update the code generation. As of writing, this can be done via the hack dir in the root of the repo: ./hack/update-codegen.sh provisioning If you've opened the generated files in this dir at some point in VSCode, you may also have to re-open them to clear errors.",
"type": "object",
@@ -435,14 +435,27 @@ export type ExportOptions = {
history?: boolean;
prefix?: string;
};
export type JobSpec = {
action: 'export' | 'pr' | 'sync';
export?: ExportOptions;
export type PullRequestOptions = {
hash?: string;
pr?: number;
ref?: string;
url?: string;
};
export type JobSpec = {
action: 'export' | 'pr' | 'sync';
export?: ExportOptions;
pr?: PullRequestOptions;
repository: string;
};
export type JobResourceSummary = {
create?: number;
delete?: number;
errors?: string[];
group?: string;
noop?: number;
resource?: string;
update?: number;
};
export type JobStatus = {
errors?: string[];
finished?: number;
@@ -450,6 +463,7 @@ export type JobStatus = {
progress?: number;
started?: number;
state?: 'error' | 'pending' | 'success' | 'working';
summary?: JobResourceSummary[];
};
export type Job = {
apiVersion?: string;