Provisioning: Include Ref URLs in Job Status (#109464)
* Add URLs to Job spec * Rename them as RefURLs * Implement RefURLs for Github * Add Ref URLs to Jobs * Worker Test * Create the branch in the staged writer * Regenerate Git mock * Format code * Consolidate ResourceURLs and RefURLs into one * Fix broken tests
This commit is contained in:
@@ -204,6 +204,9 @@ type JobStatus struct {
|
||||
|
||||
// Summary of processed actions
|
||||
Summary []*JobResourceSummary `json:"summary,omitempty"`
|
||||
|
||||
// URLs contains URLs for the reference branch or commit if applicable.
|
||||
URLs *RepositoryURLs `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// Convert a JOB to a
|
||||
|
||||
@@ -316,7 +316,7 @@ type ResourceWrapper struct {
|
||||
Repository ResourceRepositoryInfo `json:"repository"`
|
||||
|
||||
// Typed links for this file (only supported by external systems, github etc)
|
||||
URLs *ResourceURLs `json:"urls,omitempty"`
|
||||
URLs *RepositoryURLs `json:"urls,omitempty"`
|
||||
|
||||
// The modified time in the remote file system
|
||||
Timestamp *metav1.Time `json:"timestamp,omitempty"`
|
||||
@@ -374,14 +374,14 @@ type ResourceRepositoryInfo struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ResourceURLs struct {
|
||||
// A URL pointing to the this file in the repository
|
||||
SourceURL string `json:"sourceURL,omitempty"`
|
||||
|
||||
type RepositoryURLs struct {
|
||||
// A URL pointing to the repository this lives in
|
||||
RepositoryURL string `json:"repositoryURL,omitempty"`
|
||||
|
||||
// A URL that will create a new pull requeset for this branch
|
||||
// A URL pointing to the file or ref in the repository
|
||||
SourceURL string `json:"sourceURL,omitempty"`
|
||||
|
||||
// A URL that will create a new pull request for this branch
|
||||
NewPullRequestURL string `json:"newPullRequestURL,omitempty"`
|
||||
|
||||
// Compare this version to the target branch
|
||||
|
||||
@@ -499,6 +499,11 @@ func (in *JobStatus) DeepCopyInto(out *JobStatus) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.URLs != nil {
|
||||
in, out := &in.URLs, &out.URLs
|
||||
*out = new(RepositoryURLs)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -790,6 +795,22 @@ func (in *RepositoryStatus) DeepCopy() *RepositoryStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RepositoryURLs) DeepCopyInto(out *RepositoryURLs) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RepositoryURLs.
|
||||
func (in *RepositoryURLs) DeepCopy() *RepositoryURLs {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RepositoryURLs)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RepositoryView) DeepCopyInto(out *RepositoryView) {
|
||||
*out = *in
|
||||
@@ -1023,22 +1044,6 @@ func (in *ResourceType) DeepCopy() *ResourceType {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceURLs) DeepCopyInto(out *ResourceURLs) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceURLs.
|
||||
func (in *ResourceURLs) DeepCopy() *ResourceURLs {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceURLs)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceWrapper) DeepCopyInto(out *ResourceWrapper) {
|
||||
*out = *in
|
||||
@@ -1046,7 +1051,7 @@ func (in *ResourceWrapper) DeepCopyInto(out *ResourceWrapper) {
|
||||
out.Repository = in.Repository
|
||||
if in.URLs != nil {
|
||||
in, out := &in.URLs, &out.URLs
|
||||
*out = new(ResourceURLs)
|
||||
*out = new(RepositoryURLs)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timestamp != nil {
|
||||
|
||||
@@ -45,6 +45,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryList": schema_pkg_apis_provisioning_v0alpha1_RepositoryList(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositorySpec": schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryStatus": schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryURLs": schema_pkg_apis_provisioning_v0alpha1_RepositoryURLs(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryView": schema_pkg_apis_provisioning_v0alpha1_RepositoryView(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryViewList": schema_pkg_apis_provisioning_v0alpha1_RepositoryViewList(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount": schema_pkg_apis_provisioning_v0alpha1_ResourceCount(ref),
|
||||
@@ -55,7 +56,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo": schema_pkg_apis_provisioning_v0alpha1_ResourceRepositoryInfo(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceStats": schema_pkg_apis_provisioning_v0alpha1_ResourceStats(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceType": schema_pkg_apis_provisioning_v0alpha1_ResourceType(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceURLs": schema_pkg_apis_provisioning_v0alpha1_ResourceURLs(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceWrapper": schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncJobOptions": schema_pkg_apis_provisioning_v0alpha1_SyncJobOptions(ref),
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncOptions": schema_pkg_apis_provisioning_v0alpha1_SyncOptions(ref),
|
||||
@@ -1116,11 +1116,17 @@ func schema_pkg_apis_provisioning_v0alpha1_JobStatus(ref common.ReferenceCallbac
|
||||
},
|
||||
},
|
||||
},
|
||||
"url": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "URLs contains URLs for the reference branch or commit if applicable.",
|
||||
Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryURLs"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobResourceSummary"},
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobResourceSummary", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryURLs"},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1651,6 +1657,46 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref common.Reference
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_provisioning_v0alpha1_RepositoryURLs(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"repositoryURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A URL pointing to the repository this lives in",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"sourceURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A URL pointing to the file or ref in the repository",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"newPullRequestURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A URL that will create a new pull request for this branch",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"compareURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Compare this version to the target branch",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_provisioning_v0alpha1_RepositoryView(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
@@ -2216,46 +2262,6 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceType(ref common.ReferenceCall
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_provisioning_v0alpha1_ResourceURLs(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"sourceURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A URL pointing to the this file in the repository",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"repositoryURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A URL pointing to the repository this lives in",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"newPullRequestURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A URL that will create a new pull requeset for this branch",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"compareURL": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Compare this version to the target branch",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
@@ -2308,7 +2314,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref common.ReferenceC
|
||||
"urls": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Typed links for this file (only supported by external systems, github etc)",
|
||||
Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceURLs"),
|
||||
Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryURLs"),
|
||||
},
|
||||
},
|
||||
"timestamp": {
|
||||
@@ -2349,7 +2355,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref common.ReferenceC
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceObjects", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceURLs", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryURLs", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceObjects", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioni
|
||||
API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,TestResults,Errors
|
||||
API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,WebhookStatus,SubscribedEvents
|
||||
API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,JobSpec,PullRequest
|
||||
API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,JobStatus,URLs
|
||||
API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,ManagerStats,Identity
|
||||
API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitHub
|
||||
API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitLab
|
||||
|
||||
@@ -18,6 +18,7 @@ type JobStatusApplyConfiguration struct {
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
Progress *float64 `json:"progress,omitempty"`
|
||||
Summary []*provisioningv0alpha1.JobResourceSummary `json:"summary,omitempty"`
|
||||
URLs *RepositoryURLsApplyConfiguration `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// JobStatusApplyConfiguration constructs a declarative configuration of the JobStatus type for use with
|
||||
@@ -88,3 +89,11 @@ func (b *JobStatusApplyConfiguration) WithSummary(values ...**provisioningv0alph
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithURLs sets the URLs field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the URLs field is set to the value of the last call.
|
||||
func (b *JobStatusApplyConfiguration) WithURLs(value *RepositoryURLsApplyConfiguration) *JobStatusApplyConfiguration {
|
||||
b.URLs = value
|
||||
return b
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// RepositoryURLsApplyConfiguration represents a declarative configuration of the RepositoryURLs type for use
|
||||
// with apply.
|
||||
type RepositoryURLsApplyConfiguration struct {
|
||||
RepositoryURL *string `json:"repositoryURL,omitempty"`
|
||||
SourceURL *string `json:"sourceURL,omitempty"`
|
||||
NewPullRequestURL *string `json:"newPullRequestURL,omitempty"`
|
||||
CompareURL *string `json:"compareURL,omitempty"`
|
||||
}
|
||||
|
||||
// RepositoryURLsApplyConfiguration constructs a declarative configuration of the RepositoryURLs type for use with
|
||||
// apply.
|
||||
func RepositoryURLs() *RepositoryURLsApplyConfiguration {
|
||||
return &RepositoryURLsApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithRepositoryURL sets the RepositoryURL field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the RepositoryURL field is set to the value of the last call.
|
||||
func (b *RepositoryURLsApplyConfiguration) WithRepositoryURL(value string) *RepositoryURLsApplyConfiguration {
|
||||
b.RepositoryURL = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithSourceURL sets the SourceURL field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the SourceURL field is set to the value of the last call.
|
||||
func (b *RepositoryURLsApplyConfiguration) WithSourceURL(value string) *RepositoryURLsApplyConfiguration {
|
||||
b.SourceURL = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithNewPullRequestURL sets the NewPullRequestURL field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the NewPullRequestURL field is set to the value of the last call.
|
||||
func (b *RepositoryURLsApplyConfiguration) WithNewPullRequestURL(value string) *RepositoryURLsApplyConfiguration {
|
||||
b.NewPullRequestURL = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithCompareURL sets the CompareURL field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the CompareURL field is set to the value of the last call.
|
||||
func (b *RepositoryURLsApplyConfiguration) WithCompareURL(value string) *RepositoryURLsApplyConfiguration {
|
||||
b.CompareURL = &value
|
||||
return b
|
||||
}
|
||||
@@ -56,6 +56,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
|
||||
return &provisioningv0alpha1.RepositorySpecApplyConfiguration{}
|
||||
case v0alpha1.SchemeGroupVersion.WithKind("RepositoryStatus"):
|
||||
return &provisioningv0alpha1.RepositoryStatusApplyConfiguration{}
|
||||
case v0alpha1.SchemeGroupVersion.WithKind("RepositoryURLs"):
|
||||
return &provisioningv0alpha1.RepositoryURLsApplyConfiguration{}
|
||||
case v0alpha1.SchemeGroupVersion.WithKind("ResourceCount"):
|
||||
return &provisioningv0alpha1.ResourceCountApplyConfiguration{}
|
||||
case v0alpha1.SchemeGroupVersion.WithKind("ResourceRef"):
|
||||
|
||||
@@ -78,6 +78,15 @@ func (w *Worker) Process(ctx context.Context, repo repository.Repository, job pr
|
||||
return fmt.Errorf("delete files from repository: %w", err)
|
||||
}
|
||||
|
||||
// Set RefURLs if the repository supports it and we have a target ref
|
||||
if opts.Ref != "" {
|
||||
if repoWithURLs, ok := repo.(repository.RepositoryWithURLs); ok {
|
||||
if refURLs, urlErr := repoWithURLs.RefURLs(ctx, opts.Ref); urlErr == nil && refURLs != nil {
|
||||
progress.SetRefURLs(ctx, refURLs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Ref == "" {
|
||||
progress.ResetResults()
|
||||
progress.SetMessage(ctx, "pull resources")
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
||||
v0alpha1 "github.com/grafana/grafana/apps/provisioning/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"
|
||||
@@ -29,41 +30,41 @@ func (m *mockReaderWriter) Delete(ctx context.Context, path, ref, message string
|
||||
// simpleRepository implements only the base Repository interface, not ReaderWriter
|
||||
type simpleRepository struct{}
|
||||
|
||||
func (s *simpleRepository) Config() *provisioning.Repository { return nil }
|
||||
func (s *simpleRepository) Validate() field.ErrorList { return nil }
|
||||
func (s *simpleRepository) Test(ctx context.Context) (*provisioning.TestResults, error) {
|
||||
func (s *simpleRepository) Config() *v0alpha1.Repository { return nil }
|
||||
func (s *simpleRepository) Validate() field.ErrorList { return nil }
|
||||
func (s *simpleRepository) Test(ctx context.Context) (*v0alpha1.TestResults, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestDeleteWorker_IsSupported(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
job provisioning.Job
|
||||
job v0alpha1.Job
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "delete action is supported",
|
||||
job: provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
job: v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "pull action is not supported",
|
||||
job: provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionPull,
|
||||
job: v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionPull,
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "push action is not supported",
|
||||
job: provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionPush,
|
||||
job: v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionPush,
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
@@ -80,9 +81,9 @@ func TestDeleteWorker_IsSupported(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessMissingDeleteSettings(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -92,10 +93,10 @@ func TestDeleteWorker_ProcessMissingDeleteSettings(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessNotReaderWriter(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Paths: []string{"test/path"},
|
||||
},
|
||||
},
|
||||
@@ -121,10 +122,10 @@ func TestDeleteWorker_ProcessNotReaderWriter(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessWrapFnError(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Paths: []string{"test/path"},
|
||||
},
|
||||
},
|
||||
@@ -144,10 +145,10 @@ func TestDeleteWorker_ProcessWrapFnError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessDeleteFilesSuccess(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Paths: []string{"test/path1", "test/path2"},
|
||||
Ref: "main",
|
||||
},
|
||||
@@ -192,10 +193,10 @@ func TestDeleteWorker_ProcessDeleteFilesSuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessDeleteFilesWithError(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Paths: []string{"test/path1", "test/path2"},
|
||||
Ref: "main",
|
||||
},
|
||||
@@ -230,10 +231,10 @@ func TestDeleteWorker_ProcessDeleteFilesWithError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessWithSyncWorker(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Paths: []string{"test/path"},
|
||||
},
|
||||
},
|
||||
@@ -264,7 +265,7 @@ func TestDeleteWorker_ProcessWithSyncWorker(t *testing.T) {
|
||||
mockProgress.On("ResetResults").Return()
|
||||
mockProgress.On("SetMessage", mock.Anything, "pull resources").Return()
|
||||
|
||||
mockSyncWorker.On("Process", mock.Anything, mockRepo, mock.MatchedBy(func(syncJob provisioning.Job) bool {
|
||||
mockSyncWorker.On("Process", mock.Anything, mockRepo, mock.MatchedBy(func(syncJob v0alpha1.Job) bool {
|
||||
return syncJob.Spec.Pull != nil && !syncJob.Spec.Pull.Incremental
|
||||
}), mockProgress).Return(nil)
|
||||
|
||||
@@ -274,10 +275,10 @@ func TestDeleteWorker_ProcessWithSyncWorker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessSyncWorkerError(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Paths: []string{"test/path"},
|
||||
},
|
||||
},
|
||||
@@ -357,7 +358,7 @@ func TestDeleteWorker_deleteFiles(t *testing.T) {
|
||||
}
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
|
||||
opts := provisioning.DeleteJobOptions{
|
||||
opts := v0alpha1.DeleteJobOptions{
|
||||
Ref: "main",
|
||||
}
|
||||
|
||||
@@ -393,12 +394,12 @@ func TestDeleteWorker_deleteFiles(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessWithResourceRefs(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Paths: []string{"test/path1"},
|
||||
Resources: []provisioning.ResourceRef{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
@@ -481,11 +482,11 @@ func TestDeleteWorker_ProcessWithResourceRefs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessResourceRefsOnly(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
Resources: []provisioning.ResourceRef{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
@@ -536,11 +537,11 @@ func TestDeleteWorker_ProcessResourceRefsOnly(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessResourceResolutionError(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
Resources: []provisioning.ResourceRef{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "nonexistent-dashboard",
|
||||
Kind: "Dashboard",
|
||||
@@ -591,7 +592,7 @@ func TestDeleteWorker_ProcessResourceResolutionError(t *testing.T) {
|
||||
mockProgress.On("SetMessage", mock.Anything, "pull resources").Return()
|
||||
|
||||
mockSyncWorker := jobs.NewMockWorker(t)
|
||||
mockSyncWorker.On("Process", mock.Anything, mockRepo, mock.MatchedBy(func(syncJob provisioning.Job) bool {
|
||||
mockSyncWorker.On("Process", mock.Anything, mockRepo, mock.MatchedBy(func(syncJob v0alpha1.Job) bool {
|
||||
return syncJob.Spec.Pull != nil && !syncJob.Spec.Pull.Incremental
|
||||
}), mockProgress).Return(nil)
|
||||
|
||||
@@ -601,11 +602,11 @@ func TestDeleteWorker_ProcessResourceResolutionError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessResourcesFactoryError(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
Resources: []provisioning.ResourceRef{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
@@ -640,11 +641,11 @@ func TestDeleteWorker_ProcessResourcesFactoryError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessResourceRefsNotReaderWriter(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
Resources: []provisioning.ResourceRef{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
@@ -676,11 +677,11 @@ func TestDeleteWorker_ProcessResourceRefsNotReaderWriter(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessResourceResolutionTooManyErrors(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
Resources: []provisioning.ResourceRef{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "nonexistent-dashboard",
|
||||
Kind: "Dashboard",
|
||||
@@ -729,11 +730,11 @@ func TestDeleteWorker_ProcessResourceResolutionTooManyErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteWorker_ProcessMixedResourcesWithPartialFailure(t *testing.T) {
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
Resources: []provisioning.ResourceRef{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "valid-dashboard",
|
||||
Kind: "Dashboard",
|
||||
@@ -827,13 +828,13 @@ func TestDeleteWorker_ProcessMixedResourcesWithPartialFailure(t *testing.T) {
|
||||
|
||||
func TestDeleteWorker_ProcessWithPathDeduplication(t *testing.T) {
|
||||
// Test that duplicate paths from explicit paths and resource resolution are deduplicated
|
||||
job := provisioning.Job{
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionDelete,
|
||||
Delete: &provisioning.DeleteJobOptions{
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Ref: "main", // Add ref to avoid sync worker execution
|
||||
Paths: []string{"dashboards/test-dashboard.json", "folders/test-folder/"}, // Explicit paths
|
||||
Resources: []provisioning.ResourceRef{
|
||||
Resources: []v0alpha1.ResourceRef{
|
||||
{
|
||||
Name: "test-dashboard", // This will resolve to "dashboards/test-dashboard.json" (duplicate)
|
||||
Kind: "Dashboard",
|
||||
@@ -984,3 +985,167 @@ func TestDeduplicatePaths(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteWorker_RefURLsSetWithRef(t *testing.T) {
|
||||
mockRepoWithURLs := repository.NewMockRepositoryWithURLs(t)
|
||||
config := &v0alpha1.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: v0alpha1.RepositorySpec{
|
||||
Type: v0alpha1.GitHubRepositoryType,
|
||||
},
|
||||
}
|
||||
mockRepoWithURLs.On("Config").Return(config).Maybe() // Config may be called multiple times
|
||||
|
||||
// Mock RefURLs method to return expected URLs
|
||||
expectedRefURLs := &v0alpha1.RepositoryURLs{
|
||||
SourceURL: "https://github.com/grafana/grafana/tree/feature-branch",
|
||||
CompareURL: "https://github.com/grafana/grafana/compare/main...feature-branch",
|
||||
NewPullRequestURL: "https://github.com/grafana/grafana/compare/main...feature-branch?quick_pull=1&labels=grafana",
|
||||
}
|
||||
mockRepoWithURLs.On("RefURLs", mock.Anything, "feature-branch").Return(expectedRefURLs, nil)
|
||||
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
mockProgress.On("SetTotal", mock.Anything, 1).Once()
|
||||
mockProgress.On("StrictMaxErrors", 1).Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "Deleting test.json").Once()
|
||||
mockProgress.On("Record", mock.Anything, mock.Anything).Once()
|
||||
mockProgress.On("TooManyErrors").Return(nil).Once()
|
||||
mockProgress.On("SetRefURLs", mock.Anything, expectedRefURLs).Once()
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
mockReaderWriter.On("Delete", mock.Anything, "test.json", "feature-branch", "Delete test.json").Return(nil)
|
||||
|
||||
mockWrapFn := repository.NewMockWrapWithStageFn(t)
|
||||
mockWrapFn.On("Execute", mock.Anything, mockRepoWithURLs, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, opts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
mockResourcesFactory := resources.NewMockRepositoryResourcesFactory(t)
|
||||
|
||||
job := v0alpha1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-job"},
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Ref: "feature-branch",
|
||||
Paths: []string{"test.json"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
worker := NewWorker(nil, mockWrapFn.Execute, mockResourcesFactory)
|
||||
err := worker.Process(context.Background(), mockRepoWithURLs, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was called with the expected RefURLs
|
||||
mockProgress.AssertExpectations(t)
|
||||
mockRepoWithURLs.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDeleteWorker_RefURLsNotSetWithoutRef(t *testing.T) {
|
||||
mockRepoWithURLs := repository.NewMockRepositoryWithURLs(t)
|
||||
config := &v0alpha1.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: v0alpha1.RepositorySpec{
|
||||
Type: v0alpha1.GitHubRepositoryType,
|
||||
},
|
||||
}
|
||||
mockRepoWithURLs.On("Config").Return(config).Maybe() // Config may be called multiple times
|
||||
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
mockProgress.On("SetTotal", mock.Anything, 1).Once()
|
||||
mockProgress.On("StrictMaxErrors", 1).Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "Deleting test.json").Once()
|
||||
mockProgress.On("Record", mock.Anything, mock.Anything).Once()
|
||||
mockProgress.On("TooManyErrors").Return(nil).Once()
|
||||
mockProgress.On("ResetResults").Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "pull resources").Once()
|
||||
// SetRefURLs should NOT be called since no ref is specified
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
mockReaderWriter.On("Delete", mock.Anything, "test.json", "", "Delete test.json").Return(nil)
|
||||
|
||||
mockWrapFn := repository.NewMockWrapWithStageFn(t)
|
||||
mockWrapFn.On("Execute", mock.Anything, mockRepoWithURLs, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, opts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
mockSyncWorker := jobs.NewMockWorker(t)
|
||||
mockSyncWorker.On("Process", mock.Anything, mockRepoWithURLs, mock.Anything, mockProgress).Return(nil)
|
||||
|
||||
mockResourcesFactory := resources.NewMockRepositoryResourcesFactory(t)
|
||||
|
||||
job := v0alpha1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-job"},
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
// No ref specified
|
||||
Paths: []string{"test.json"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
worker := NewWorker(mockSyncWorker, mockWrapFn.Execute, mockResourcesFactory)
|
||||
err := worker.Process(context.Background(), mockRepoWithURLs, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was NOT called since no ref was specified
|
||||
mockProgress.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDeleteWorker_RefURLsNotSetForNonURLRepository(t *testing.T) {
|
||||
mockRepo := repository.NewMockRepository(t)
|
||||
config := &v0alpha1.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: v0alpha1.RepositorySpec{
|
||||
Type: v0alpha1.GitRepositoryType, // Regular git repo, not GitHub
|
||||
},
|
||||
}
|
||||
mockRepo.On("Config").Return(config).Maybe() // Config may be called multiple times
|
||||
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
mockProgress.On("SetTotal", mock.Anything, 1).Once()
|
||||
mockProgress.On("StrictMaxErrors", 1).Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "Deleting test.json").Once()
|
||||
mockProgress.On("Record", mock.Anything, mock.Anything).Once()
|
||||
mockProgress.On("TooManyErrors").Return(nil).Once()
|
||||
// SetRefURLs should NOT be called since repo doesn't support URLs
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
mockReaderWriter.On("Delete", mock.Anything, "test.json", "feature-branch", "Delete test.json").Return(nil)
|
||||
|
||||
mockWrapFn := repository.NewMockWrapWithStageFn(t)
|
||||
mockWrapFn.On("Execute", mock.Anything, mockRepo, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, opts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
mockResourcesFactory := resources.NewMockRepositoryResourcesFactory(t)
|
||||
|
||||
job := v0alpha1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-job"},
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionDelete,
|
||||
Delete: &v0alpha1.DeleteJobOptions{
|
||||
Ref: "feature-branch",
|
||||
Paths: []string{"test.json"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
worker := NewWorker(nil, mockWrapFn.Execute, mockResourcesFactory)
|
||||
err := worker.Process(context.Background(), mockRepo, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was NOT called since repo doesn't support URLs
|
||||
mockProgress.AssertExpectations(t)
|
||||
}
|
||||
|
||||
@@ -88,5 +88,16 @@ func (r *ExportWorker) Process(ctx context.Context, repo repository.Repository,
|
||||
return r.exportFn(ctx, cfg.Name, *options, clients, repositoryResources, progress)
|
||||
}
|
||||
|
||||
return r.wrapWithStageFn(ctx, repo, cloneOptions, fn)
|
||||
err := r.wrapWithStageFn(ctx, repo, cloneOptions, fn)
|
||||
|
||||
// Set RefURLs if the repository supports it and we have a target branch
|
||||
if options.Branch != "" {
|
||||
if repoWithURLs, ok := repo.(repository.RepositoryWithURLs); ok {
|
||||
if refURLs, urlErr := repoWithURLs.RefURLs(ctx, options.Branch); urlErr == nil && refURLs != nil {
|
||||
progress.SetRefURLs(ctx, refURLs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -549,3 +549,181 @@ func TestExportWorker_ProcessGitRepositoryExportFnError(t *testing.T) {
|
||||
err := r.Process(context.Background(), mockRepo, job, mockProgress)
|
||||
require.EqualError(t, err, "export failed")
|
||||
}
|
||||
|
||||
func TestExportWorker_RefURLsSetWithBranch(t *testing.T) {
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionPush,
|
||||
Push: &v0alpha1.ExportJobOptions{
|
||||
Branch: "feature-branch",
|
||||
Message: "test commit",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Create a repository that implements both Repository and RepositoryWithURLs
|
||||
mockRepoWithURLs := repository.NewMockRepositoryWithURLs(t)
|
||||
|
||||
mockRepoWithURLs.On("Config").Return(&v0alpha1.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: v0alpha1.RepositorySpec{
|
||||
Type: v0alpha1.GitHubRepositoryType,
|
||||
Workflows: []v0alpha1.Workflow{v0alpha1.WriteWorkflow, v0alpha1.BranchWorkflow},
|
||||
},
|
||||
})
|
||||
|
||||
// Mock RefURLs method to return expected URLs
|
||||
expectedRefURLs := &v0alpha1.RepositoryURLs{
|
||||
SourceURL: "https://github.com/grafana/grafana/tree/feature-branch",
|
||||
CompareURL: "https://github.com/grafana/grafana/compare/main...feature-branch",
|
||||
NewPullRequestURL: "https://github.com/grafana/grafana/compare/main...feature-branch?quick_pull=1&labels=grafana",
|
||||
}
|
||||
mockRepoWithURLs.On("RefURLs", mock.Anything, "feature-branch").Return(expectedRefURLs, nil)
|
||||
|
||||
// Mock progress recorder to expect SetRefURLs call
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
mockProgress.On("SetRefURLs", mock.Anything, expectedRefURLs).Once()
|
||||
|
||||
// Mock other dependencies
|
||||
mockClients := resources.NewMockClientFactory(t)
|
||||
mockResourceClients := resources.NewMockResourceClients(t)
|
||||
mockClients.On("Clients", mock.Anything, "test-namespace").Return(mockResourceClients, nil)
|
||||
|
||||
mockRepoResources := resources.NewMockRepositoryResourcesFactory(t)
|
||||
mockRepoResourcesClient := resources.NewMockRepositoryResources(t)
|
||||
mockRepoResources.On("Client", mock.Anything, mock.Anything).Return(mockRepoResourcesClient, nil)
|
||||
|
||||
mockExportFn := NewMockExportFn(t)
|
||||
mockExportFn.On("Execute", mock.Anything, "test-repo", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
|
||||
// Mock the ReaderWriter interface that the export function expects
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
|
||||
mockStageFn := NewMockWrapWithStageFn(t)
|
||||
mockStageFn.On("Execute", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, stageOpts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
// The staging function needs to call the inner function with a ReaderWriter
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
r := NewExportWorker(mockClients, mockRepoResources, mockExportFn.Execute, mockStageFn.Execute)
|
||||
err := r.Process(context.Background(), mockRepoWithURLs, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was called with the expected RefURLs
|
||||
mockProgress.AssertExpectations(t)
|
||||
mockRepoWithURLs.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestExportWorker_RefURLsNotSetWithoutBranch(t *testing.T) {
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionPush,
|
||||
Push: &v0alpha1.ExportJobOptions{
|
||||
Message: "test commit",
|
||||
// No branch specified
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
mockRepoWithURLs := repository.NewMockRepositoryWithURLs(t)
|
||||
|
||||
mockRepoWithURLs.On("Config").Return(&v0alpha1.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: v0alpha1.RepositorySpec{
|
||||
Type: v0alpha1.GitHubRepositoryType,
|
||||
Workflows: []v0alpha1.Workflow{v0alpha1.WriteWorkflow},
|
||||
},
|
||||
})
|
||||
|
||||
// Mock progress recorder - SetRefURLs should NOT be called
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
// Explicitly NOT expecting SetRefURLs call
|
||||
|
||||
// Mock other dependencies
|
||||
mockClients := resources.NewMockClientFactory(t)
|
||||
mockResourceClients := resources.NewMockResourceClients(t)
|
||||
mockClients.On("Clients", mock.Anything, "test-namespace").Return(mockResourceClients, nil)
|
||||
|
||||
mockRepoResources := resources.NewMockRepositoryResourcesFactory(t)
|
||||
mockRepoResourcesClient := resources.NewMockRepositoryResources(t)
|
||||
mockRepoResources.On("Client", mock.Anything, mock.Anything).Return(mockRepoResourcesClient, nil)
|
||||
|
||||
mockExportFn := NewMockExportFn(t)
|
||||
mockExportFn.On("Execute", mock.Anything, "test-repo", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
|
||||
mockStageFn := NewMockWrapWithStageFn(t)
|
||||
mockStageFn.On("Execute", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, stageOpts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
r := NewExportWorker(mockClients, mockRepoResources, mockExportFn.Execute, mockStageFn.Execute)
|
||||
err := r.Process(context.Background(), mockRepoWithURLs, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was NOT called since no branch was specified
|
||||
mockProgress.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestExportWorker_RefURLsNotSetForNonURLRepository(t *testing.T) {
|
||||
job := v0alpha1.Job{
|
||||
Spec: v0alpha1.JobSpec{
|
||||
Action: v0alpha1.JobActionPush,
|
||||
Push: &v0alpha1.ExportJobOptions{
|
||||
Branch: "feature-branch",
|
||||
Message: "test commit",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Use a regular Repository that doesn't implement RepositoryWithURLs
|
||||
mockRepo := repository.NewMockRepository(t)
|
||||
|
||||
mockRepo.On("Config").Return(&v0alpha1.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: v0alpha1.RepositorySpec{
|
||||
Type: v0alpha1.GitRepositoryType, // Regular git repo, not GitHub
|
||||
Workflows: []v0alpha1.Workflow{v0alpha1.WriteWorkflow, v0alpha1.BranchWorkflow},
|
||||
},
|
||||
})
|
||||
|
||||
// Mock progress recorder - SetRefURLs should NOT be called
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
// Explicitly NOT expecting SetRefURLs call
|
||||
|
||||
// Mock other dependencies
|
||||
mockClients := resources.NewMockClientFactory(t)
|
||||
mockResourceClients := resources.NewMockResourceClients(t)
|
||||
mockClients.On("Clients", mock.Anything, "test-namespace").Return(mockResourceClients, nil)
|
||||
|
||||
mockRepoResources := resources.NewMockRepositoryResourcesFactory(t)
|
||||
mockRepoResourcesClient := resources.NewMockRepositoryResources(t)
|
||||
mockRepoResources.On("Client", mock.Anything, mock.Anything).Return(mockRepoResourcesClient, nil)
|
||||
|
||||
mockExportFn := NewMockExportFn(t)
|
||||
mockExportFn.On("Execute", mock.Anything, "test-repo", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
|
||||
mockStageFn := NewMockWrapWithStageFn(t)
|
||||
mockStageFn.On("Execute", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, stageOpts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
r := NewExportWorker(mockClients, mockRepoResources, mockExportFn.Execute, mockStageFn.Execute)
|
||||
err := r.Process(context.Background(), mockRepo, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was NOT called since repo doesn't support URLs
|
||||
mockProgress.AssertExpectations(t)
|
||||
}
|
||||
|
||||
@@ -203,6 +203,40 @@ func (_c *MockJobProgressRecorder_SetMessage_Call) RunAndReturn(run func(context
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetRefURLs provides a mock function with given fields: ctx, refURLs
|
||||
func (_m *MockJobProgressRecorder) SetRefURLs(ctx context.Context, refURLs *v0alpha1.RepositoryURLs) {
|
||||
_m.Called(ctx, refURLs)
|
||||
}
|
||||
|
||||
// MockJobProgressRecorder_SetRefURLs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetRefURLs'
|
||||
type MockJobProgressRecorder_SetRefURLs_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// SetRefURLs is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - refURLs *v0alpha1.RepositoryURLs
|
||||
func (_e *MockJobProgressRecorder_Expecter) SetRefURLs(ctx interface{}, refURLs interface{}) *MockJobProgressRecorder_SetRefURLs_Call {
|
||||
return &MockJobProgressRecorder_SetRefURLs_Call{Call: _e.mock.On("SetRefURLs", ctx, refURLs)}
|
||||
}
|
||||
|
||||
func (_c *MockJobProgressRecorder_SetRefURLs_Call) Run(run func(ctx context.Context, refURLs *v0alpha1.RepositoryURLs)) *MockJobProgressRecorder_SetRefURLs_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*v0alpha1.RepositoryURLs))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockJobProgressRecorder_SetRefURLs_Call) Return() *MockJobProgressRecorder_SetRefURLs_Call {
|
||||
_c.Call.Return()
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockJobProgressRecorder_SetRefURLs_Call) RunAndReturn(run func(context.Context, *v0alpha1.RepositoryURLs)) *MockJobProgressRecorder_SetRefURLs_Call {
|
||||
_c.Run(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetTotal provides a mock function with given fields: ctx, total
|
||||
func (_m *MockJobProgressRecorder) SetTotal(ctx context.Context, total int) {
|
||||
_m.Called(ctx, total)
|
||||
|
||||
@@ -89,6 +89,15 @@ func (w *Worker) Process(ctx context.Context, repo repository.Repository, job pr
|
||||
return fmt.Errorf("move files in repository: %w", err)
|
||||
}
|
||||
|
||||
// Set RefURLs if the repository supports it and we have a target ref
|
||||
if opts.Ref != "" {
|
||||
if repoWithURLs, ok := repo.(repository.RepositoryWithURLs); ok {
|
||||
if refURLs, urlErr := repoWithURLs.RefURLs(ctx, opts.Ref); urlErr == nil && refURLs != nil {
|
||||
progress.SetRefURLs(ctx, refURLs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Ref == "" {
|
||||
progress.ResetResults()
|
||||
progress.SetMessage(ctx, "pull resources")
|
||||
|
||||
@@ -833,3 +833,170 @@ func TestMoveWorker_deduplicatePaths(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMoveWorker_RefURLsSetWithRef(t *testing.T) {
|
||||
mockRepoWithURLs := repository.NewMockRepositoryWithURLs(t)
|
||||
config := &provisioning.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: provisioning.RepositorySpec{
|
||||
Type: provisioning.GitHubRepositoryType,
|
||||
},
|
||||
}
|
||||
mockRepoWithURLs.On("Config").Return(config).Maybe() // Config may be called multiple times
|
||||
|
||||
// Mock RefURLs method to return expected URLs
|
||||
expectedRefURLs := &provisioning.RepositoryURLs{
|
||||
SourceURL: "https://github.com/grafana/grafana/tree/feature-branch",
|
||||
CompareURL: "https://github.com/grafana/grafana/compare/main...feature-branch",
|
||||
NewPullRequestURL: "https://github.com/grafana/grafana/compare/main...feature-branch?quick_pull=1&labels=grafana",
|
||||
}
|
||||
mockRepoWithURLs.On("RefURLs", mock.Anything, "feature-branch").Return(expectedRefURLs, nil)
|
||||
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
mockProgress.On("SetTotal", mock.Anything, 1).Once()
|
||||
mockProgress.On("StrictMaxErrors", 1).Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "Moving test.json to target/test.json").Once()
|
||||
mockProgress.On("Record", mock.Anything, mock.Anything).Once()
|
||||
mockProgress.On("TooManyErrors").Return(nil).Once()
|
||||
mockProgress.On("SetRefURLs", mock.Anything, expectedRefURLs).Once()
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
mockReaderWriter.On("Move", mock.Anything, "test.json", "target/test.json", "feature-branch", "Move test.json to target/test.json").Return(nil)
|
||||
|
||||
mockWrapFn := repository.NewMockWrapWithStageFn(t)
|
||||
mockWrapFn.On("Execute", mock.Anything, mockRepoWithURLs, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, opts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
mockResourcesFactory := resources.NewMockRepositoryResourcesFactory(t)
|
||||
|
||||
job := provisioning.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-job"},
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionMove,
|
||||
Move: &provisioning.MoveJobOptions{
|
||||
Ref: "feature-branch",
|
||||
Paths: []string{"test.json"},
|
||||
TargetPath: "target/",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
worker := NewWorker(nil, mockWrapFn.Execute, mockResourcesFactory)
|
||||
err := worker.Process(context.Background(), mockRepoWithURLs, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was called with the expected RefURLs
|
||||
mockProgress.AssertExpectations(t)
|
||||
mockRepoWithURLs.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestMoveWorker_RefURLsNotSetWithoutRef(t *testing.T) {
|
||||
mockRepoWithURLs := repository.NewMockRepositoryWithURLs(t)
|
||||
config := &provisioning.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: provisioning.RepositorySpec{
|
||||
Type: provisioning.GitHubRepositoryType,
|
||||
},
|
||||
}
|
||||
mockRepoWithURLs.On("Config").Return(config).Maybe() // Config may be called multiple times
|
||||
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
mockProgress.On("SetTotal", mock.Anything, 1).Once()
|
||||
mockProgress.On("StrictMaxErrors", 1).Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "Moving test.json to target/test.json").Once()
|
||||
mockProgress.On("Record", mock.Anything, mock.Anything).Once()
|
||||
mockProgress.On("TooManyErrors").Return(nil).Once()
|
||||
mockProgress.On("ResetResults").Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "pull resources").Once()
|
||||
// SetRefURLs should NOT be called since no ref is specified
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
mockReaderWriter.On("Move", mock.Anything, "test.json", "target/test.json", "", "Move test.json to target/test.json").Return(nil)
|
||||
|
||||
mockWrapFn := repository.NewMockWrapWithStageFn(t)
|
||||
mockWrapFn.On("Execute", mock.Anything, mockRepoWithURLs, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, opts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
mockSyncWorker := jobs.NewMockWorker(t)
|
||||
mockSyncWorker.On("Process", mock.Anything, mockRepoWithURLs, mock.Anything, mockProgress).Return(nil)
|
||||
|
||||
mockResourcesFactory := resources.NewMockRepositoryResourcesFactory(t)
|
||||
|
||||
job := provisioning.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-job"},
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionMove,
|
||||
Move: &provisioning.MoveJobOptions{
|
||||
// No ref specified
|
||||
Paths: []string{"test.json"},
|
||||
TargetPath: "target/",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
worker := NewWorker(mockSyncWorker, mockWrapFn.Execute, mockResourcesFactory)
|
||||
err := worker.Process(context.Background(), mockRepoWithURLs, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was NOT called since no ref was specified
|
||||
mockProgress.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestMoveWorker_RefURLsNotSetForNonURLRepository(t *testing.T) {
|
||||
mockRepo := repository.NewMockRepository(t)
|
||||
config := &provisioning.Repository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-repo",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Spec: provisioning.RepositorySpec{
|
||||
Type: provisioning.GitRepositoryType, // Regular git repo, not GitHub
|
||||
},
|
||||
}
|
||||
mockRepo.On("Config").Return(config).Maybe() // Config may be called multiple times
|
||||
|
||||
mockProgress := jobs.NewMockJobProgressRecorder(t)
|
||||
mockProgress.On("SetTotal", mock.Anything, 1).Once()
|
||||
mockProgress.On("StrictMaxErrors", 1).Once()
|
||||
mockProgress.On("SetMessage", mock.Anything, "Moving test.json to target/test.json").Once()
|
||||
mockProgress.On("Record", mock.Anything, mock.Anything).Once()
|
||||
mockProgress.On("TooManyErrors").Return(nil).Once()
|
||||
// SetRefURLs should NOT be called since repo doesn't support URLs
|
||||
|
||||
mockReaderWriter := repository.NewMockReaderWriter(t)
|
||||
mockReaderWriter.On("Move", mock.Anything, "test.json", "target/test.json", "feature-branch", "Move test.json to target/test.json").Return(nil)
|
||||
|
||||
mockWrapFn := repository.NewMockWrapWithStageFn(t)
|
||||
mockWrapFn.On("Execute", mock.Anything, mockRepo, mock.Anything, mock.Anything).Return(func(ctx context.Context, repo repository.Repository, opts repository.StageOptions, fn func(repository.Repository, bool) error) error {
|
||||
return fn(mockReaderWriter, true)
|
||||
})
|
||||
|
||||
mockResourcesFactory := resources.NewMockRepositoryResourcesFactory(t)
|
||||
|
||||
job := provisioning.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-job"},
|
||||
Spec: provisioning.JobSpec{
|
||||
Action: provisioning.JobActionMove,
|
||||
Move: &provisioning.MoveJobOptions{
|
||||
Ref: "feature-branch",
|
||||
Paths: []string{"test.json"},
|
||||
TargetPath: "target/",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
worker := NewWorker(nil, mockWrapFn.Execute, mockResourcesFactory)
|
||||
err := worker.Process(context.Background(), mockRepo, job, mockProgress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that SetRefURLs was NOT called since repo doesn't support URLs
|
||||
mockProgress.AssertExpectations(t)
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ type jobProgressRecorder struct {
|
||||
resultCount int
|
||||
errorCount int
|
||||
errors []string
|
||||
refURLs *provisioning.RepositoryURLs
|
||||
notifyImmediatelyFn ProgressFn
|
||||
maybeNotifyFn ProgressFn
|
||||
summaries map[string]*provisioning.JobResourceSummary
|
||||
@@ -117,6 +118,18 @@ func (r *jobProgressRecorder) SetFinalMessage(ctx context.Context, msg string) {
|
||||
logging.FromContext(ctx).Info("job final message", "message", msg)
|
||||
}
|
||||
|
||||
func (r *jobProgressRecorder) SetRefURLs(ctx context.Context, refURLs *provisioning.RepositoryURLs) {
|
||||
r.mu.Lock()
|
||||
r.refURLs = refURLs
|
||||
r.mu.Unlock()
|
||||
|
||||
if refURLs != nil {
|
||||
logging.FromContext(ctx).Debug("job ref URLs set", "sourceURL", refURLs.SourceURL, "compareURL", refURLs.CompareURL, "newPullRequestURL", refURLs.NewPullRequestURL)
|
||||
} else {
|
||||
logging.FromContext(ctx).Debug("job ref URLs cleared")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *jobProgressRecorder) SetTotal(ctx context.Context, total int) {
|
||||
r.mu.Lock()
|
||||
r.total = total
|
||||
@@ -253,6 +266,7 @@ func (r *jobProgressRecorder) Complete(ctx context.Context, err error) provision
|
||||
|
||||
jobStatus.Summary = r.summary()
|
||||
jobStatus.Errors = r.errors
|
||||
jobStatus.URLs = r.refURLs
|
||||
|
||||
// Check for errors during execution
|
||||
if len(jobStatus.Errors) > 0 && jobStatus.State != provisioning.JobStateError {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestJobProgressRecorderSetRefURLs(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a progress recorder
|
||||
mockProgressFn := func(ctx context.Context, status provisioning.JobStatus) error {
|
||||
return nil
|
||||
}
|
||||
recorder := newJobProgressRecorder(mockProgressFn).(*jobProgressRecorder)
|
||||
|
||||
// Test setting RefURLs
|
||||
expectedRefURLs := &provisioning.RepositoryURLs{
|
||||
SourceURL: "https://github.com/grafana/grafana/tree/feature-branch",
|
||||
CompareURL: "https://github.com/grafana/grafana/compare/main...feature-branch",
|
||||
NewPullRequestURL: "https://github.com/grafana/grafana/compare/main...feature-branch?quick_pull=1&labels=grafana",
|
||||
}
|
||||
|
||||
recorder.SetRefURLs(ctx, expectedRefURLs)
|
||||
|
||||
// Verify RefURLs are stored
|
||||
recorder.mu.RLock()
|
||||
assert.Equal(t, expectedRefURLs, recorder.refURLs)
|
||||
recorder.mu.RUnlock()
|
||||
|
||||
// Test that RefURLs are included in the final status
|
||||
finalStatus := recorder.Complete(ctx, nil)
|
||||
assert.Equal(t, expectedRefURLs, finalStatus.URLs)
|
||||
}
|
||||
|
||||
func TestJobProgressRecorderSetRefURLsNil(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a progress recorder
|
||||
mockProgressFn := func(ctx context.Context, status provisioning.JobStatus) error {
|
||||
return nil
|
||||
}
|
||||
recorder := newJobProgressRecorder(mockProgressFn).(*jobProgressRecorder)
|
||||
|
||||
// Test setting nil RefURLs
|
||||
recorder.SetRefURLs(ctx, nil)
|
||||
|
||||
// Verify nil RefURLs are stored
|
||||
recorder.mu.RLock()
|
||||
assert.Nil(t, recorder.refURLs)
|
||||
recorder.mu.RUnlock()
|
||||
|
||||
// Test that nil RefURLs are included in the final status
|
||||
finalStatus := recorder.Complete(ctx, nil)
|
||||
assert.Nil(t, finalStatus.URLs)
|
||||
}
|
||||
|
||||
func TestJobProgressRecorderCompleteIncludesRefURLs(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a progress recorder
|
||||
mockProgressFn := func(ctx context.Context, status provisioning.JobStatus) error {
|
||||
return nil
|
||||
}
|
||||
recorder := newJobProgressRecorder(mockProgressFn).(*jobProgressRecorder)
|
||||
|
||||
// Set some RefURLs
|
||||
refURLs := &provisioning.RepositoryURLs{
|
||||
SourceURL: "https://github.com/grafana/grafana/tree/test-branch",
|
||||
}
|
||||
recorder.SetRefURLs(ctx, refURLs)
|
||||
|
||||
// Complete the job
|
||||
finalStatus := recorder.Complete(ctx, nil)
|
||||
|
||||
// Verify the final status includes RefURLs
|
||||
require.NotNil(t, finalStatus.URLs)
|
||||
assert.Equal(t, refURLs.SourceURL, finalStatus.URLs.SourceURL)
|
||||
assert.Equal(t, provisioning.JobStateSuccess, finalStatus.State)
|
||||
assert.Equal(t, "completed successfully", finalStatus.Message)
|
||||
}
|
||||
@@ -25,6 +25,7 @@ type JobProgressRecorder interface {
|
||||
SetTotal(ctx context.Context, total int)
|
||||
TooManyErrors() error
|
||||
StrictMaxErrors(maxErrors int)
|
||||
SetRefURLs(ctx context.Context, refURLs *provisioning.RepositoryURLs)
|
||||
Complete(ctx context.Context, err error) provisioning.JobStatus
|
||||
}
|
||||
|
||||
|
||||
@@ -182,6 +182,112 @@ func (_c *MockStore_Complete_Call) RunAndReturn(run func(context.Context, *v0alp
|
||||
return _c
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: ctx, name
|
||||
func (_m *MockStore) Get(ctx context.Context, name string) (*v0alpha1.Job, error) {
|
||||
ret := _m.Called(ctx, name)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Get")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.Job
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*v0alpha1.Job, error)); ok {
|
||||
return rf(ctx, name)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *v0alpha1.Job); ok {
|
||||
r0 = rf(ctx, name)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.Job)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, name)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockStore_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get'
|
||||
type MockStore_Get_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Get is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - name string
|
||||
func (_e *MockStore_Expecter) Get(ctx interface{}, name interface{}) *MockStore_Get_Call {
|
||||
return &MockStore_Get_Call{Call: _e.mock.On("Get", ctx, name)}
|
||||
}
|
||||
|
||||
func (_c *MockStore_Get_Call) Run(run func(ctx context.Context, name string)) *MockStore_Get_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockStore_Get_Call) Return(_a0 *v0alpha1.Job, _a1 error) *MockStore_Get_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockStore_Get_Call) RunAndReturn(run func(context.Context, string) (*v0alpha1.Job, error)) *MockStore_Get_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RenewLease provides a mock function with given fields: ctx, job
|
||||
func (_m *MockStore) RenewLease(ctx context.Context, job *v0alpha1.Job) error {
|
||||
ret := _m.Called(ctx, job)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RenewLease")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *v0alpha1.Job) error); ok {
|
||||
r0 = rf(ctx, job)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockStore_RenewLease_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RenewLease'
|
||||
type MockStore_RenewLease_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RenewLease is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - job *v0alpha1.Job
|
||||
func (_e *MockStore_Expecter) RenewLease(ctx interface{}, job interface{}) *MockStore_RenewLease_Call {
|
||||
return &MockStore_RenewLease_Call{Call: _e.mock.On("RenewLease", ctx, job)}
|
||||
}
|
||||
|
||||
func (_c *MockStore_RenewLease_Call) Run(run func(ctx context.Context, job *v0alpha1.Job)) *MockStore_RenewLease_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*v0alpha1.Job))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockStore_RenewLease_Call) Return(_a0 error) *MockStore_RenewLease_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockStore_RenewLease_Call) RunAndReturn(run func(context.Context, *v0alpha1.Job) error) *MockStore_RenewLease_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, job
|
||||
func (_m *MockStore) Update(ctx context.Context, job *v0alpha1.Job) (*v0alpha1.Job, error) {
|
||||
ret := _m.Called(ctx, job)
|
||||
|
||||
@@ -31,13 +31,9 @@ func NewStagedGitRepository(ctx context.Context, repo *gitRepository, opts repos
|
||||
branch = repo.gitConfig.Branch
|
||||
}
|
||||
|
||||
ref, err := repo.client.GetRef(ctx, "refs/heads/"+branch)
|
||||
ref, err := repo.ensureBranchExists(ctx, branch)
|
||||
if err != nil {
|
||||
// TODO: opts.CreateIfNotExists doesn't make sense in the context of the staged repository
|
||||
// because we only support the branch that is passed in.
|
||||
// we should probably add branch to the repository.CloneOptions which should be repurposed
|
||||
// as some kind of branch creation options.
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("ensure branch exists: %w", err)
|
||||
}
|
||||
|
||||
writer, err := repo.client.NewStagedWriter(ctx, ref)
|
||||
|
||||
@@ -131,7 +131,48 @@ func TestNewStagedGitRepository(t *testing.T) {
|
||||
opts: repository.StageOptions{
|
||||
Mode: repository.StageModeCommitOnEach,
|
||||
},
|
||||
wantError: errors.New("ref not found"),
|
||||
wantError: errors.New("ensure branch exists: check branch exists: ref not found"),
|
||||
},
|
||||
{
|
||||
name: "creates branch when it doesn't exist",
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
// First call to GetRef for feature-branch returns not found
|
||||
// Second call to GetRef for main branch (source) returns success
|
||||
// Third call to CreateRef creates the feature branch
|
||||
// Fourth call to GetRef for feature-branch returns the created branch
|
||||
callCount := 0
|
||||
mockClient.GetRefStub = func(ctx context.Context, ref string) (nanogit.Ref, error) {
|
||||
callCount++
|
||||
switch callCount {
|
||||
case 1:
|
||||
// First call: feature-branch doesn't exist
|
||||
if ref == "refs/heads/feature-branch" {
|
||||
return nanogit.Ref{}, nanogit.ErrObjectNotFound
|
||||
}
|
||||
case 2:
|
||||
// Second call: get source branch (main)
|
||||
if ref == "refs/heads/main" {
|
||||
return nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return nanogit.Ref{}, errors.New("unexpected call")
|
||||
}
|
||||
|
||||
// CreateRef should be called to create the new branch
|
||||
mockClient.CreateRefReturns(nil)
|
||||
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
mockClient.NewStagedWriterReturns(mockWriter, nil)
|
||||
},
|
||||
opts: repository.StageOptions{
|
||||
Ref: "feature-branch",
|
||||
Mode: repository.StageModeCommitOnEach,
|
||||
},
|
||||
expectedRef: "refs/heads/feature-branch",
|
||||
wantError: nil,
|
||||
},
|
||||
{
|
||||
name: "fails with NewStagedWriter error",
|
||||
|
||||
@@ -829,6 +829,65 @@ func (_c *MockGithubRepository_ReadTree_Call) RunAndReturn(run func(context.Cont
|
||||
return _c
|
||||
}
|
||||
|
||||
// RefURLs provides a mock function with given fields: ctx, ref
|
||||
func (_m *MockGithubRepository) RefURLs(ctx context.Context, ref string) (*v0alpha1.RepositoryURLs, error) {
|
||||
ret := _m.Called(ctx, ref)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RefURLs")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.RepositoryURLs
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*v0alpha1.RepositoryURLs, error)); ok {
|
||||
return rf(ctx, ref)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *v0alpha1.RepositoryURLs); ok {
|
||||
r0 = rf(ctx, ref)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.RepositoryURLs)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, ref)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockGithubRepository_RefURLs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RefURLs'
|
||||
type MockGithubRepository_RefURLs_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RefURLs is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - ref string
|
||||
func (_e *MockGithubRepository_Expecter) RefURLs(ctx interface{}, ref interface{}) *MockGithubRepository_RefURLs_Call {
|
||||
return &MockGithubRepository_RefURLs_Call{Call: _e.mock.On("RefURLs", ctx, ref)}
|
||||
}
|
||||
|
||||
func (_c *MockGithubRepository_RefURLs_Call) Run(run func(ctx context.Context, ref string)) *MockGithubRepository_RefURLs_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockGithubRepository_RefURLs_Call) Return(_a0 *v0alpha1.RepositoryURLs, _a1 error) *MockGithubRepository_RefURLs_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockGithubRepository_RefURLs_Call) RunAndReturn(run func(context.Context, string) (*v0alpha1.RepositoryURLs, error)) *MockGithubRepository_RefURLs_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Repo provides a mock function with no fields
|
||||
func (_m *MockGithubRepository) Repo() string {
|
||||
ret := _m.Called()
|
||||
@@ -875,23 +934,23 @@ func (_c *MockGithubRepository_Repo_Call) RunAndReturn(run func() string) *MockG
|
||||
}
|
||||
|
||||
// ResourceURLs provides a mock function with given fields: ctx, file
|
||||
func (_m *MockGithubRepository) ResourceURLs(ctx context.Context, file *repository.FileInfo) (*v0alpha1.ResourceURLs, error) {
|
||||
func (_m *MockGithubRepository) ResourceURLs(ctx context.Context, file *repository.FileInfo) (*v0alpha1.RepositoryURLs, error) {
|
||||
ret := _m.Called(ctx, file)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ResourceURLs")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.ResourceURLs
|
||||
var r0 *v0alpha1.RepositoryURLs
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *repository.FileInfo) (*v0alpha1.ResourceURLs, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *repository.FileInfo) (*v0alpha1.RepositoryURLs, error)); ok {
|
||||
return rf(ctx, file)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *repository.FileInfo) *v0alpha1.ResourceURLs); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *repository.FileInfo) *v0alpha1.RepositoryURLs); ok {
|
||||
r0 = rf(ctx, file)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.ResourceURLs)
|
||||
r0 = ret.Get(0).(*v0alpha1.RepositoryURLs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,12 +982,12 @@ func (_c *MockGithubRepository_ResourceURLs_Call) Run(run func(ctx context.Conte
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockGithubRepository_ResourceURLs_Call) Return(_a0 *v0alpha1.ResourceURLs, _a1 error) *MockGithubRepository_ResourceURLs_Call {
|
||||
func (_c *MockGithubRepository_ResourceURLs_Call) Return(_a0 *v0alpha1.RepositoryURLs, _a1 error) *MockGithubRepository_ResourceURLs_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockGithubRepository_ResourceURLs_Call) RunAndReturn(run func(context.Context, *repository.FileInfo) (*v0alpha1.ResourceURLs, error)) *MockGithubRepository_ResourceURLs_Call {
|
||||
func (_c *MockGithubRepository_ResourceURLs_Call) RunAndReturn(run func(context.Context, *repository.FileInfo) (*v0alpha1.RepositoryURLs, error)) *MockGithubRepository_ResourceURLs_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ func (r *githubRepository) ListRefs(ctx context.Context) ([]provisioning.RefItem
|
||||
}
|
||||
|
||||
// ResourceURLs implements RepositoryWithURLs.
|
||||
func (r *githubRepository) ResourceURLs(ctx context.Context, file *repository.FileInfo) (*provisioning.ResourceURLs, error) {
|
||||
func (r *githubRepository) ResourceURLs(ctx context.Context, file *repository.FileInfo) (*provisioning.RepositoryURLs, error) {
|
||||
cfg := r.config.Spec.GitHub
|
||||
if file.Path == "" || cfg == nil {
|
||||
return nil, nil
|
||||
@@ -209,7 +209,7 @@ func (r *githubRepository) ResourceURLs(ctx context.Context, file *repository.Fi
|
||||
ref = cfg.Branch
|
||||
}
|
||||
|
||||
urls := &provisioning.ResourceURLs{
|
||||
urls := &provisioning.RepositoryURLs{
|
||||
RepositoryURL: cfg.URL,
|
||||
SourceURL: fmt.Sprintf("%s/blob/%s/%s", cfg.URL, ref, file.Path),
|
||||
}
|
||||
@@ -224,6 +224,25 @@ func (r *githubRepository) ResourceURLs(ctx context.Context, file *repository.Fi
|
||||
return urls, nil
|
||||
}
|
||||
|
||||
// RefURLs implements RepositoryWithURLs.
|
||||
func (r *githubRepository) RefURLs(ctx context.Context, ref string) (*provisioning.RepositoryURLs, error) {
|
||||
cfg := r.config.Spec.GitHub
|
||||
if cfg == nil || ref == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
urls := &provisioning.RepositoryURLs{
|
||||
SourceURL: fmt.Sprintf("%s/tree/%s", cfg.URL, ref),
|
||||
}
|
||||
|
||||
if ref != cfg.Branch {
|
||||
urls.CompareURL = fmt.Sprintf("%s/compare/%s...%s", cfg.URL, cfg.Branch, ref)
|
||||
urls.NewPullRequestURL = fmt.Sprintf("%s?quick_pull=1&labels=grafana", urls.CompareURL)
|
||||
}
|
||||
|
||||
return urls, nil
|
||||
}
|
||||
|
||||
func (r *githubRepository) OnCreate(_ context.Context) ([]map[string]interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -688,7 +688,7 @@ func TestGitHubRepositoryResourceURLs(t *testing.T) {
|
||||
name string
|
||||
file *repository.FileInfo
|
||||
config *provisioning.Repository
|
||||
expectedURLs *provisioning.ResourceURLs
|
||||
expectedURLs *provisioning.RepositoryURLs
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
@@ -705,7 +705,7 @@ func TestGitHubRepositoryResourceURLs(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedURLs: &provisioning.ResourceURLs{
|
||||
expectedURLs: &provisioning.RepositoryURLs{
|
||||
RepositoryURL: "https://github.com/grafana/grafana",
|
||||
SourceURL: "https://github.com/grafana/grafana/blob/feature-branch/dashboards/test.json",
|
||||
CompareURL: "https://github.com/grafana/grafana/compare/main...feature-branch",
|
||||
@@ -726,7 +726,7 @@ func TestGitHubRepositoryResourceURLs(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedURLs: &provisioning.ResourceURLs{
|
||||
expectedURLs: &provisioning.RepositoryURLs{
|
||||
RepositoryURL: "https://github.com/grafana/grafana",
|
||||
SourceURL: "https://github.com/grafana/grafana/blob/main/dashboards/test.json",
|
||||
},
|
||||
@@ -783,6 +783,92 @@ func TestGitHubRepositoryResourceURLs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubRepositoryRefURLs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ref string
|
||||
config *provisioning.Repository
|
||||
expectedURLs *provisioning.RepositoryURLs
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "ref different from branch",
|
||||
ref: "feature-branch",
|
||||
config: &provisioning.Repository{
|
||||
Spec: provisioning.RepositorySpec{
|
||||
GitHub: &provisioning.GitHubRepositoryConfig{
|
||||
URL: "https://github.com/grafana/grafana",
|
||||
Branch: "main",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedURLs: &provisioning.RepositoryURLs{
|
||||
SourceURL: "https://github.com/grafana/grafana/tree/feature-branch",
|
||||
CompareURL: "https://github.com/grafana/grafana/compare/main...feature-branch",
|
||||
NewPullRequestURL: "https://github.com/grafana/grafana/compare/main...feature-branch?quick_pull=1&labels=grafana",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ref same as branch",
|
||||
ref: "main",
|
||||
config: &provisioning.Repository{
|
||||
Spec: provisioning.RepositorySpec{
|
||||
GitHub: &provisioning.GitHubRepositoryConfig{
|
||||
URL: "https://github.com/grafana/grafana",
|
||||
Branch: "main",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedURLs: &provisioning.RepositoryURLs{
|
||||
SourceURL: "https://github.com/grafana/grafana/tree/main",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty ref returns nil",
|
||||
ref: "",
|
||||
config: &provisioning.Repository{
|
||||
Spec: provisioning.RepositorySpec{
|
||||
GitHub: &provisioning.GitHubRepositoryConfig{
|
||||
URL: "https://github.com/grafana/grafana",
|
||||
Branch: "main",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedURLs: nil,
|
||||
},
|
||||
{
|
||||
name: "nil github config returns nil",
|
||||
ref: "feature-branch",
|
||||
config: &provisioning.Repository{
|
||||
Spec: provisioning.RepositorySpec{
|
||||
GitHub: nil,
|
||||
},
|
||||
},
|
||||
expectedURLs: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
repo := &githubRepository{
|
||||
config: tt.config,
|
||||
owner: "grafana",
|
||||
repo: "grafana",
|
||||
}
|
||||
|
||||
urls, err := repo.RefURLs(context.Background(), tt.ref)
|
||||
|
||||
if tt.expectedError != nil {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, tt.expectedError.Error(), err.Error())
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.expectedURLs, urls)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test simple delegation functions
|
||||
func TestGitHubRepositoryDelegation(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -0,0 +1,559 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
field "k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
||||
)
|
||||
|
||||
// MockReaderWriter is an autogenerated mock type for the ReaderWriter type
|
||||
type MockReaderWriter struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockReaderWriter_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockReaderWriter) EXPECT() *MockReaderWriter_Expecter {
|
||||
return &MockReaderWriter_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Config provides a mock function with no fields
|
||||
func (_m *MockReaderWriter) Config() *v0alpha1.Repository {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Config")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.Repository
|
||||
if rf, ok := ret.Get(0).(func() *v0alpha1.Repository); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.Repository)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockReaderWriter_Config_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Config'
|
||||
type MockReaderWriter_Config_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Config is a helper method to define mock.On call
|
||||
func (_e *MockReaderWriter_Expecter) Config() *MockReaderWriter_Config_Call {
|
||||
return &MockReaderWriter_Config_Call{Call: _e.mock.On("Config")}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Config_Call) Run(run func()) *MockReaderWriter_Config_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Config_Call) Return(_a0 *v0alpha1.Repository) *MockReaderWriter_Config_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Config_Call) RunAndReturn(run func() *v0alpha1.Repository) *MockReaderWriter_Config_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Create provides a mock function with given fields: ctx, path, ref, data, message
|
||||
func (_m *MockReaderWriter) Create(ctx context.Context, path string, ref string, data []byte, message string) error {
|
||||
ret := _m.Called(ctx, path, ref, data, message)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Create")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte, string) error); ok {
|
||||
r0 = rf(ctx, path, ref, data, message)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockReaderWriter_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create'
|
||||
type MockReaderWriter_Create_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Create is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - path string
|
||||
// - ref string
|
||||
// - data []byte
|
||||
// - message string
|
||||
func (_e *MockReaderWriter_Expecter) Create(ctx interface{}, path interface{}, ref interface{}, data interface{}, message interface{}) *MockReaderWriter_Create_Call {
|
||||
return &MockReaderWriter_Create_Call{Call: _e.mock.On("Create", ctx, path, ref, data, message)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Create_Call) Run(run func(ctx context.Context, path string, ref string, data []byte, message string)) *MockReaderWriter_Create_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].([]byte), args[4].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Create_Call) Return(_a0 error) *MockReaderWriter_Create_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Create_Call) RunAndReturn(run func(context.Context, string, string, []byte, string) error) *MockReaderWriter_Create_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Delete provides a mock function with given fields: ctx, path, ref, message
|
||||
func (_m *MockReaderWriter) Delete(ctx context.Context, path string, ref string, message string) error {
|
||||
ret := _m.Called(ctx, path, ref, message)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Delete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok {
|
||||
r0 = rf(ctx, path, ref, message)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockReaderWriter_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete'
|
||||
type MockReaderWriter_Delete_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Delete is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - path string
|
||||
// - ref string
|
||||
// - message string
|
||||
func (_e *MockReaderWriter_Expecter) Delete(ctx interface{}, path interface{}, ref interface{}, message interface{}) *MockReaderWriter_Delete_Call {
|
||||
return &MockReaderWriter_Delete_Call{Call: _e.mock.On("Delete", ctx, path, ref, message)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Delete_Call) Run(run func(ctx context.Context, path string, ref string, message string)) *MockReaderWriter_Delete_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Delete_Call) Return(_a0 error) *MockReaderWriter_Delete_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Delete_Call) RunAndReturn(run func(context.Context, string, string, string) error) *MockReaderWriter_Delete_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Move provides a mock function with given fields: ctx, oldPath, newPath, ref, message
|
||||
func (_m *MockReaderWriter) Move(ctx context.Context, oldPath string, newPath string, ref string, message string) error {
|
||||
ret := _m.Called(ctx, oldPath, newPath, ref, message)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Move")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string) error); ok {
|
||||
r0 = rf(ctx, oldPath, newPath, ref, message)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockReaderWriter_Move_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Move'
|
||||
type MockReaderWriter_Move_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Move is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - oldPath string
|
||||
// - newPath string
|
||||
// - ref string
|
||||
// - message string
|
||||
func (_e *MockReaderWriter_Expecter) Move(ctx interface{}, oldPath interface{}, newPath interface{}, ref interface{}, message interface{}) *MockReaderWriter_Move_Call {
|
||||
return &MockReaderWriter_Move_Call{Call: _e.mock.On("Move", ctx, oldPath, newPath, ref, message)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Move_Call) Run(run func(ctx context.Context, oldPath string, newPath string, ref string, message string)) *MockReaderWriter_Move_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(string), args[4].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Move_Call) Return(_a0 error) *MockReaderWriter_Move_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Move_Call) RunAndReturn(run func(context.Context, string, string, string, string) error) *MockReaderWriter_Move_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Read provides a mock function with given fields: ctx, path, ref
|
||||
func (_m *MockReaderWriter) Read(ctx context.Context, path string, ref string) (*FileInfo, error) {
|
||||
ret := _m.Called(ctx, path, ref)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Read")
|
||||
}
|
||||
|
||||
var r0 *FileInfo
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) (*FileInfo, error)); ok {
|
||||
return rf(ctx, path, ref)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) *FileInfo); ok {
|
||||
r0 = rf(ctx, path, ref)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*FileInfo)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
|
||||
r1 = rf(ctx, path, ref)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockReaderWriter_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read'
|
||||
type MockReaderWriter_Read_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Read is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - path string
|
||||
// - ref string
|
||||
func (_e *MockReaderWriter_Expecter) Read(ctx interface{}, path interface{}, ref interface{}) *MockReaderWriter_Read_Call {
|
||||
return &MockReaderWriter_Read_Call{Call: _e.mock.On("Read", ctx, path, ref)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Read_Call) Run(run func(ctx context.Context, path string, ref string)) *MockReaderWriter_Read_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Read_Call) Return(_a0 *FileInfo, _a1 error) *MockReaderWriter_Read_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Read_Call) RunAndReturn(run func(context.Context, string, string) (*FileInfo, error)) *MockReaderWriter_Read_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ReadTree provides a mock function with given fields: ctx, ref
|
||||
func (_m *MockReaderWriter) ReadTree(ctx context.Context, ref string) ([]FileTreeEntry, error) {
|
||||
ret := _m.Called(ctx, ref)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ReadTree")
|
||||
}
|
||||
|
||||
var r0 []FileTreeEntry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) ([]FileTreeEntry, error)); ok {
|
||||
return rf(ctx, ref)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []FileTreeEntry); ok {
|
||||
r0 = rf(ctx, ref)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]FileTreeEntry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, ref)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockReaderWriter_ReadTree_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadTree'
|
||||
type MockReaderWriter_ReadTree_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ReadTree is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - ref string
|
||||
func (_e *MockReaderWriter_Expecter) ReadTree(ctx interface{}, ref interface{}) *MockReaderWriter_ReadTree_Call {
|
||||
return &MockReaderWriter_ReadTree_Call{Call: _e.mock.On("ReadTree", ctx, ref)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_ReadTree_Call) Run(run func(ctx context.Context, ref string)) *MockReaderWriter_ReadTree_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_ReadTree_Call) Return(_a0 []FileTreeEntry, _a1 error) *MockReaderWriter_ReadTree_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_ReadTree_Call) RunAndReturn(run func(context.Context, string) ([]FileTreeEntry, error)) *MockReaderWriter_ReadTree_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Test provides a mock function with given fields: ctx
|
||||
func (_m *MockReaderWriter) Test(ctx context.Context) (*v0alpha1.TestResults, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Test")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.TestResults
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) (*v0alpha1.TestResults, error)); ok {
|
||||
return rf(ctx)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context) *v0alpha1.TestResults); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.TestResults)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||
r1 = rf(ctx)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockReaderWriter_Test_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Test'
|
||||
type MockReaderWriter_Test_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Test is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *MockReaderWriter_Expecter) Test(ctx interface{}) *MockReaderWriter_Test_Call {
|
||||
return &MockReaderWriter_Test_Call{Call: _e.mock.On("Test", ctx)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Test_Call) Run(run func(ctx context.Context)) *MockReaderWriter_Test_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Test_Call) Return(_a0 *v0alpha1.TestResults, _a1 error) *MockReaderWriter_Test_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Test_Call) RunAndReturn(run func(context.Context) (*v0alpha1.TestResults, error)) *MockReaderWriter_Test_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, path, ref, data, message
|
||||
func (_m *MockReaderWriter) Update(ctx context.Context, path string, ref string, data []byte, message string) error {
|
||||
ret := _m.Called(ctx, path, ref, data, message)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Update")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte, string) error); ok {
|
||||
r0 = rf(ctx, path, ref, data, message)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockReaderWriter_Update_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Update'
|
||||
type MockReaderWriter_Update_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Update is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - path string
|
||||
// - ref string
|
||||
// - data []byte
|
||||
// - message string
|
||||
func (_e *MockReaderWriter_Expecter) Update(ctx interface{}, path interface{}, ref interface{}, data interface{}, message interface{}) *MockReaderWriter_Update_Call {
|
||||
return &MockReaderWriter_Update_Call{Call: _e.mock.On("Update", ctx, path, ref, data, message)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Update_Call) Run(run func(ctx context.Context, path string, ref string, data []byte, message string)) *MockReaderWriter_Update_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].([]byte), args[4].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Update_Call) Return(_a0 error) *MockReaderWriter_Update_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Update_Call) RunAndReturn(run func(context.Context, string, string, []byte, string) error) *MockReaderWriter_Update_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Validate provides a mock function with no fields
|
||||
func (_m *MockReaderWriter) Validate() field.ErrorList {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Validate")
|
||||
}
|
||||
|
||||
var r0 field.ErrorList
|
||||
if rf, ok := ret.Get(0).(func() field.ErrorList); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(field.ErrorList)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockReaderWriter_Validate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Validate'
|
||||
type MockReaderWriter_Validate_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Validate is a helper method to define mock.On call
|
||||
func (_e *MockReaderWriter_Expecter) Validate() *MockReaderWriter_Validate_Call {
|
||||
return &MockReaderWriter_Validate_Call{Call: _e.mock.On("Validate")}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Validate_Call) Run(run func()) *MockReaderWriter_Validate_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Validate_Call) Return(_a0 field.ErrorList) *MockReaderWriter_Validate_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Validate_Call) RunAndReturn(run func() field.ErrorList) *MockReaderWriter_Validate_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Write provides a mock function with given fields: ctx, path, ref, data, message
|
||||
func (_m *MockReaderWriter) Write(ctx context.Context, path string, ref string, data []byte, message string) error {
|
||||
ret := _m.Called(ctx, path, ref, data, message)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Write")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, []byte, string) error); ok {
|
||||
r0 = rf(ctx, path, ref, data, message)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockReaderWriter_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write'
|
||||
type MockReaderWriter_Write_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Write is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - path string
|
||||
// - ref string
|
||||
// - data []byte
|
||||
// - message string
|
||||
func (_e *MockReaderWriter_Expecter) Write(ctx interface{}, path interface{}, ref interface{}, data interface{}, message interface{}) *MockReaderWriter_Write_Call {
|
||||
return &MockReaderWriter_Write_Call{Call: _e.mock.On("Write", ctx, path, ref, data, message)}
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Write_Call) Run(run func(ctx context.Context, path string, ref string, data []byte, message string)) *MockReaderWriter_Write_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].([]byte), args[4].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Write_Call) Return(_a0 error) *MockReaderWriter_Write_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockReaderWriter_Write_Call) RunAndReturn(run func(context.Context, string, string, []byte, string) error) *MockReaderWriter_Write_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewMockReaderWriter creates a new instance of MockReaderWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockReaderWriter(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockReaderWriter {
|
||||
mock := &MockReaderWriter{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
@@ -119,17 +119,19 @@ type Writer interface {
|
||||
Move(ctx context.Context, oldPath, newPath, ref, message string) error
|
||||
}
|
||||
|
||||
//go:generate mockery --name ReaderWriter --structname MockReaderWriter --inpackage --filename reader_writer_mock.go --with-expecter
|
||||
type ReaderWriter interface {
|
||||
Reader
|
||||
Writer
|
||||
}
|
||||
|
||||
// Hooks called after the repository has been created, updated or deleted
|
||||
//go:generate mockery --name RepositoryWithURLs --structname MockRepositoryWithURLs --inpackage --filename repository_with_urls_mock.go --with-expecter
|
||||
type RepositoryWithURLs interface {
|
||||
Repository
|
||||
|
||||
// Get resource URLs for a file inside a repository
|
||||
ResourceURLs(ctx context.Context, file *FileInfo) (*provisioning.ResourceURLs, error)
|
||||
ResourceURLs(ctx context.Context, file *FileInfo) (*provisioning.RepositoryURLs, error)
|
||||
RefURLs(ctx context.Context, ref string) (*provisioning.RepositoryURLs, error)
|
||||
}
|
||||
|
||||
// Hooks called after the repository has been created, updated or deleted
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
field "k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
||||
)
|
||||
|
||||
// MockRepositoryWithURLs is an autogenerated mock type for the RepositoryWithURLs type
|
||||
type MockRepositoryWithURLs struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockRepositoryWithURLs_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockRepositoryWithURLs) EXPECT() *MockRepositoryWithURLs_Expecter {
|
||||
return &MockRepositoryWithURLs_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Config provides a mock function with no fields
|
||||
func (_m *MockRepositoryWithURLs) Config() *v0alpha1.Repository {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Config")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.Repository
|
||||
if rf, ok := ret.Get(0).(func() *v0alpha1.Repository); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.Repository)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRepositoryWithURLs_Config_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Config'
|
||||
type MockRepositoryWithURLs_Config_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Config is a helper method to define mock.On call
|
||||
func (_e *MockRepositoryWithURLs_Expecter) Config() *MockRepositoryWithURLs_Config_Call {
|
||||
return &MockRepositoryWithURLs_Config_Call{Call: _e.mock.On("Config")}
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Config_Call) Run(run func()) *MockRepositoryWithURLs_Config_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Config_Call) Return(_a0 *v0alpha1.Repository) *MockRepositoryWithURLs_Config_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Config_Call) RunAndReturn(run func() *v0alpha1.Repository) *MockRepositoryWithURLs_Config_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RefURLs provides a mock function with given fields: ctx, ref
|
||||
func (_m *MockRepositoryWithURLs) RefURLs(ctx context.Context, ref string) (*v0alpha1.RepositoryURLs, error) {
|
||||
ret := _m.Called(ctx, ref)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RefURLs")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.RepositoryURLs
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*v0alpha1.RepositoryURLs, error)); ok {
|
||||
return rf(ctx, ref)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *v0alpha1.RepositoryURLs); ok {
|
||||
r0 = rf(ctx, ref)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.RepositoryURLs)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, ref)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRepositoryWithURLs_RefURLs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RefURLs'
|
||||
type MockRepositoryWithURLs_RefURLs_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RefURLs is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - ref string
|
||||
func (_e *MockRepositoryWithURLs_Expecter) RefURLs(ctx interface{}, ref interface{}) *MockRepositoryWithURLs_RefURLs_Call {
|
||||
return &MockRepositoryWithURLs_RefURLs_Call{Call: _e.mock.On("RefURLs", ctx, ref)}
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_RefURLs_Call) Run(run func(ctx context.Context, ref string)) *MockRepositoryWithURLs_RefURLs_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_RefURLs_Call) Return(_a0 *v0alpha1.RepositoryURLs, _a1 error) *MockRepositoryWithURLs_RefURLs_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_RefURLs_Call) RunAndReturn(run func(context.Context, string) (*v0alpha1.RepositoryURLs, error)) *MockRepositoryWithURLs_RefURLs_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ResourceURLs provides a mock function with given fields: ctx, file
|
||||
func (_m *MockRepositoryWithURLs) ResourceURLs(ctx context.Context, file *FileInfo) (*v0alpha1.RepositoryURLs, error) {
|
||||
ret := _m.Called(ctx, file)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ResourceURLs")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.RepositoryURLs
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *FileInfo) (*v0alpha1.RepositoryURLs, error)); ok {
|
||||
return rf(ctx, file)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *FileInfo) *v0alpha1.RepositoryURLs); ok {
|
||||
r0 = rf(ctx, file)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.RepositoryURLs)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *FileInfo) error); ok {
|
||||
r1 = rf(ctx, file)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRepositoryWithURLs_ResourceURLs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ResourceURLs'
|
||||
type MockRepositoryWithURLs_ResourceURLs_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ResourceURLs is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - file *FileInfo
|
||||
func (_e *MockRepositoryWithURLs_Expecter) ResourceURLs(ctx interface{}, file interface{}) *MockRepositoryWithURLs_ResourceURLs_Call {
|
||||
return &MockRepositoryWithURLs_ResourceURLs_Call{Call: _e.mock.On("ResourceURLs", ctx, file)}
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_ResourceURLs_Call) Run(run func(ctx context.Context, file *FileInfo)) *MockRepositoryWithURLs_ResourceURLs_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*FileInfo))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_ResourceURLs_Call) Return(_a0 *v0alpha1.RepositoryURLs, _a1 error) *MockRepositoryWithURLs_ResourceURLs_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_ResourceURLs_Call) RunAndReturn(run func(context.Context, *FileInfo) (*v0alpha1.RepositoryURLs, error)) *MockRepositoryWithURLs_ResourceURLs_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Test provides a mock function with given fields: ctx
|
||||
func (_m *MockRepositoryWithURLs) Test(ctx context.Context) (*v0alpha1.TestResults, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Test")
|
||||
}
|
||||
|
||||
var r0 *v0alpha1.TestResults
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) (*v0alpha1.TestResults, error)); ok {
|
||||
return rf(ctx)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context) *v0alpha1.TestResults); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0alpha1.TestResults)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||
r1 = rf(ctx)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRepositoryWithURLs_Test_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Test'
|
||||
type MockRepositoryWithURLs_Test_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Test is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *MockRepositoryWithURLs_Expecter) Test(ctx interface{}) *MockRepositoryWithURLs_Test_Call {
|
||||
return &MockRepositoryWithURLs_Test_Call{Call: _e.mock.On("Test", ctx)}
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Test_Call) Run(run func(ctx context.Context)) *MockRepositoryWithURLs_Test_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Test_Call) Return(_a0 *v0alpha1.TestResults, _a1 error) *MockRepositoryWithURLs_Test_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Test_Call) RunAndReturn(run func(context.Context) (*v0alpha1.TestResults, error)) *MockRepositoryWithURLs_Test_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Validate provides a mock function with no fields
|
||||
func (_m *MockRepositoryWithURLs) Validate() field.ErrorList {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Validate")
|
||||
}
|
||||
|
||||
var r0 field.ErrorList
|
||||
if rf, ok := ret.Get(0).(func() field.ErrorList); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(field.ErrorList)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRepositoryWithURLs_Validate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Validate'
|
||||
type MockRepositoryWithURLs_Validate_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Validate is a helper method to define mock.On call
|
||||
func (_e *MockRepositoryWithURLs_Expecter) Validate() *MockRepositoryWithURLs_Validate_Call {
|
||||
return &MockRepositoryWithURLs_Validate_Call{Call: _e.mock.On("Validate")}
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Validate_Call) Run(run func()) *MockRepositoryWithURLs_Validate_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Validate_Call) Return(_a0 field.ErrorList) *MockRepositoryWithURLs_Validate_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryWithURLs_Validate_Call) RunAndReturn(run func() field.ErrorList) *MockRepositoryWithURLs_Validate_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewMockRepositoryWithURLs creates a new instance of MockRepositoryWithURLs. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockRepositoryWithURLs(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockRepositoryWithURLs {
|
||||
mock := &MockRepositoryWithURLs{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
@@ -576,7 +576,7 @@ func (r *DualReadWriter) deleteFolder(ctx context.Context, opts DualWriteOptions
|
||||
return folderDeleteResponse(ctx, opts.Path, opts.Ref, r.repo)
|
||||
}
|
||||
|
||||
func getFolderURLs(ctx context.Context, path, ref string, repo repository.Repository) (*provisioning.ResourceURLs, error) {
|
||||
func getFolderURLs(ctx context.Context, path, ref string, repo repository.Repository) (*provisioning.RepositoryURLs, error) {
|
||||
if urlRepo, ok := repo.(repository.RepositoryWithURLs); ok && ref != "" {
|
||||
urls, err := urlRepo.ResourceURLs(ctx, &repository.FileInfo{Path: path, Ref: ref})
|
||||
if err != nil {
|
||||
|
||||
@@ -87,7 +87,7 @@ type ParsedResource struct {
|
||||
Repo provisioning.ResourceRepositoryInfo
|
||||
|
||||
// Resource URLs
|
||||
URLs *provisioning.ResourceURLs
|
||||
URLs *provisioning.RepositoryURLs
|
||||
|
||||
// Check for classic file types (dashboard.json, etc)
|
||||
Classic provisioning.ClassicFileType
|
||||
|
||||
@@ -3135,6 +3135,14 @@
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobResourceSummary"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"description": "URLs contains URLs for the reference branch or commit if applicable.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryURLs"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3516,6 +3524,27 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryURLs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"compareURL": {
|
||||
"description": "Compare this version to the target branch",
|
||||
"type": "string"
|
||||
},
|
||||
"newPullRequestURL": {
|
||||
"description": "A URL that will create a new pull request for this branch",
|
||||
"type": "string"
|
||||
},
|
||||
"repositoryURL": {
|
||||
"description": "A URL pointing to the repository this lives in",
|
||||
"type": "string"
|
||||
},
|
||||
"sourceURL": {
|
||||
"description": "A URL pointing to the file or ref in the repository",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceCount": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -3767,27 +3796,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceURLs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"compareURL": {
|
||||
"description": "Compare this version to the target branch",
|
||||
"type": "string"
|
||||
},
|
||||
"newPullRequestURL": {
|
||||
"description": "A URL that will create a new pull requeset for this branch",
|
||||
"type": "string"
|
||||
},
|
||||
"repositoryURL": {
|
||||
"description": "A URL pointing to the repository this lives in",
|
||||
"type": "string"
|
||||
},
|
||||
"sourceURL": {
|
||||
"description": "A URL pointing to the this file in the repository",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceWrapper": {
|
||||
"description": "This is a container type for any resource type",
|
||||
"type": "object",
|
||||
@@ -3855,7 +3863,7 @@
|
||||
"description": "Typed links for this file (only supported by external systems, github etc)",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceURLs"
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryURLs"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4666,6 +4674,9 @@
|
||||
"description": "Summary of processed actions",
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"url": {
|
||||
"description": "URLs contains URLs for the reference branch or commit if applicable."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4963,6 +4974,27 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryURLs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"compareURL": {
|
||||
"description": "Compare this version to the target branch",
|
||||
"type": "string"
|
||||
},
|
||||
"newPullRequestURL": {
|
||||
"description": "A URL that will create a new pull request for this branch",
|
||||
"type": "string"
|
||||
},
|
||||
"repositoryURL": {
|
||||
"description": "A URL pointing to the repository this lives in",
|
||||
"type": "string"
|
||||
},
|
||||
"sourceURL": {
|
||||
"description": "A URL pointing to the file or ref in the repository",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryView": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -5327,27 +5359,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceURLs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"compareURL": {
|
||||
"description": "Compare this version to the target branch",
|
||||
"type": "string"
|
||||
},
|
||||
"newPullRequestURL": {
|
||||
"description": "A URL that will create a new pull requeset for this branch",
|
||||
"type": "string"
|
||||
},
|
||||
"repositoryURL": {
|
||||
"description": "A URL pointing to the repository this lives in",
|
||||
"type": "string"
|
||||
},
|
||||
"sourceURL": {
|
||||
"description": "A URL pointing to the this file in the repository",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceWrapper": {
|
||||
"description": "This is a container type for any resource type",
|
||||
"type": "object",
|
||||
|
||||
Reference in New Issue
Block a user