mirror of
https://github.com/harness/drone.git
synced 2025-05-31 11:43:15 +00:00
Support Repo Migration APIs (create repo, import PRs, webhooks, and branch rules) (#2158)
* update migrator mdoule * added formatted forbidden error helper * delete work sum * check branch rule identifier check * match migrator data contract for webhooks * self review * self review * self review, code cleaning * resolve conflicts * updated import api calls * resolve conflicts * lint * bypass pre-receive block ref update on push if it's migrator push * migrate controller and apis * pull main * add migrate routes to terminate path prefix apis * move apis to migrate pkg * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into atmsn/import_meta * import branch rules API * wip import webhooks
This commit is contained in:
parent
91291b8b27
commit
cef6708a1e
@ -62,8 +62,10 @@ func (c *Controller) PostReceive(
|
||||
// as the branch could be different than the configured default value.
|
||||
c.handleEmptyRepoPush(ctx, repo, in.PostReceiveInput, &out)
|
||||
|
||||
// report ref events (best effort)
|
||||
c.reportReferenceEvents(ctx, rgit, repo, in.PrincipalID, in.PostReceiveInput)
|
||||
// report ref events if repo is in an active state (best effort)
|
||||
if repo.State == enum.RepoStateActive {
|
||||
c.reportReferenceEvents(ctx, rgit, repo, in.PrincipalID, in.PostReceiveInput)
|
||||
}
|
||||
|
||||
// handle branch updates related to PRs - best effort
|
||||
c.handlePRMessaging(ctx, repo, in.PostReceiveInput, &out)
|
||||
|
@ -67,13 +67,13 @@ func (c *Controller) PreReceive(
|
||||
}
|
||||
|
||||
// For external calls (git pushes) block modification of pullreq references.
|
||||
if !in.Internal && c.blockPullReqRefUpdate(refUpdates) {
|
||||
if !in.Internal && c.blockPullReqRefUpdate(refUpdates, repo.State) {
|
||||
output.Error = ptr.String(usererror.ErrPullReqRefsCantBeModified.Error())
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// For internal calls - through the application interface (API) - no need to verify protection rules.
|
||||
if !in.Internal {
|
||||
if !in.Internal && repo.State == enum.RepoStateActive {
|
||||
// TODO: use store.PrincipalInfoCache once we abstracted principals.
|
||||
principal, err := c.principalStore.Find(ctx, in.PrincipalID)
|
||||
if err != nil {
|
||||
@ -109,7 +109,11 @@ func (c *Controller) PreReceive(
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (c *Controller) blockPullReqRefUpdate(refUpdates changedRefs) bool {
|
||||
func (c *Controller) blockPullReqRefUpdate(refUpdates changedRefs, state enum.RepoState) bool {
|
||||
if state == enum.RepoStateMigrateGitPush {
|
||||
return false
|
||||
}
|
||||
|
||||
fn := func(ref string) bool {
|
||||
return strings.HasPrefix(ref, gitReferenceNamePullReq)
|
||||
}
|
||||
|
@ -15,21 +15,88 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/api/controller/limiter"
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/auth/authz"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/app/services/publicaccess"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/app/url"
|
||||
"github.com/harness/gitness/audit"
|
||||
"github.com/harness/gitness/git"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
authorizer authz.Authorizer
|
||||
principalStore store.PrincipalStore
|
||||
authorizer authz.Authorizer
|
||||
publicAccess publicaccess.Service
|
||||
git git.Interface
|
||||
urlProvider url.Provider
|
||||
pullreqImporter *migrate.PullReq
|
||||
ruleImporter *migrate.Rule
|
||||
webhookImporter *migrate.Webhook
|
||||
resourceLimiter limiter.ResourceLimiter
|
||||
auditService audit.Service
|
||||
identifierCheck check.RepoIdentifier
|
||||
tx dbtx.Transactor
|
||||
spaceStore store.SpaceStore
|
||||
repoStore store.RepoStore
|
||||
}
|
||||
|
||||
func NewController(
|
||||
authorizer authz.Authorizer,
|
||||
principalStore store.PrincipalStore,
|
||||
publicAccess publicaccess.Service,
|
||||
git git.Interface,
|
||||
urlProvider url.Provider,
|
||||
pullreqImporter *migrate.PullReq,
|
||||
ruleImporter *migrate.Rule,
|
||||
webhookImporter *migrate.Webhook,
|
||||
resourceLimiter limiter.ResourceLimiter,
|
||||
auditService audit.Service,
|
||||
identifierCheck check.RepoIdentifier,
|
||||
tx dbtx.Transactor,
|
||||
spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore,
|
||||
) *Controller {
|
||||
return &Controller{
|
||||
authorizer: authorizer,
|
||||
principalStore: principalStore,
|
||||
authorizer: authorizer,
|
||||
publicAccess: publicAccess,
|
||||
git: git,
|
||||
urlProvider: urlProvider,
|
||||
pullreqImporter: pullreqImporter,
|
||||
ruleImporter: ruleImporter,
|
||||
webhookImporter: webhookImporter,
|
||||
resourceLimiter: resourceLimiter,
|
||||
auditService: auditService,
|
||||
identifierCheck: identifierCheck,
|
||||
tx: tx,
|
||||
spaceStore: spaceStore,
|
||||
repoStore: repoStore,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getRepoCheckAccess(ctx context.Context,
|
||||
session *auth.Session, repoRef string, reqPermission enum.Permission) (*types.Repository, error) {
|
||||
if repoRef == "" {
|
||||
return nil, usererror.BadRequest("A valid repository reference must be provided.")
|
||||
}
|
||||
|
||||
repo, err := c.repoStore.FindByRef(ctx, repoRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find repo: %w", err)
|
||||
}
|
||||
|
||||
if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission); err != nil {
|
||||
return nil, fmt.Errorf("failed to verify authorization: %w", err)
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
206
app/api/controller/migrate/create_repo.go
Normal file
206
app/api/controller/migrate/create_repo.go
Normal file
@ -0,0 +1,206 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/api/controller/limiter"
|
||||
repoCtrl "github.com/harness/gitness/app/api/controller/repo"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/bootstrap"
|
||||
"github.com/harness/gitness/app/githook"
|
||||
"github.com/harness/gitness/app/paths"
|
||||
"github.com/harness/gitness/audit"
|
||||
"github.com/harness/gitness/git"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type CreateRepoInput struct {
|
||||
ParentRef string `json:"parent_ref"`
|
||||
Identifier string `json:"identifier"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
IsPublic bool `json:"is_public"`
|
||||
}
|
||||
|
||||
func (c *Controller) CreateRepo(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
in *CreateRepoInput,
|
||||
) (*repoCtrl.RepositoryOutput, error) {
|
||||
if err := c.sanitizeCreateRepoInput(in); err != nil {
|
||||
return nil, fmt.Errorf("failed to sanitize input: %w", err)
|
||||
}
|
||||
|
||||
parentSpace, err := c.spaceCheckAuth(ctx, session, in.ParentRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to check auth in parent '%s': %w", in.ParentRef, err)
|
||||
}
|
||||
|
||||
// generate envars (add everything githook CLI needs for execution)
|
||||
envVars, err := githook.GenerateEnvironmentVariables(
|
||||
ctx,
|
||||
c.urlProvider.GetInternalAPIURL(ctx),
|
||||
0,
|
||||
session.Principal.ID,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate git hook environment variables: %w", err)
|
||||
}
|
||||
|
||||
actor := &git.Identity{
|
||||
Name: session.Principal.DisplayName,
|
||||
Email: session.Principal.Email,
|
||||
}
|
||||
committer := bootstrap.NewSystemServiceSession().Principal
|
||||
now := time.Now()
|
||||
|
||||
gitResp, err := c.git.CreateRepository(ctx, &git.CreateRepositoryParams{
|
||||
Actor: *actor,
|
||||
EnvVars: envVars,
|
||||
DefaultBranch: in.DefaultBranch,
|
||||
Files: nil,
|
||||
Author: actor,
|
||||
AuthorDate: &now,
|
||||
Committer: &git.Identity{
|
||||
Name: committer.DisplayName,
|
||||
Email: committer.Email,
|
||||
},
|
||||
CommitterDate: &now,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create git repository: %w", err)
|
||||
}
|
||||
|
||||
var repo *types.Repository
|
||||
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
if err := c.resourceLimiter.RepoCount(ctx, parentSpace.ID, 1); err != nil {
|
||||
return fmt.Errorf("resource limit exceeded: %w", limiter.ErrMaxNumReposReached)
|
||||
}
|
||||
|
||||
// lock the space for update during repo creation to prevent racing conditions with space soft delete.
|
||||
parentSpace, err = c.spaceStore.FindForUpdate(ctx, parentSpace.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find the parent space: %w", err)
|
||||
}
|
||||
|
||||
repo = &types.Repository{
|
||||
Version: 0,
|
||||
ParentID: parentSpace.ID,
|
||||
Identifier: in.Identifier,
|
||||
GitUID: gitResp.UID,
|
||||
CreatedBy: session.Principal.ID,
|
||||
Created: now.UnixMilli(),
|
||||
Updated: now.UnixMilli(),
|
||||
DefaultBranch: in.DefaultBranch,
|
||||
IsEmpty: true,
|
||||
State: enum.RepoStateMigrateGitPush,
|
||||
}
|
||||
|
||||
return c.repoStore.Create(ctx, repo)
|
||||
}, sql.TxOptions{Isolation: sql.LevelSerializable})
|
||||
if err != nil {
|
||||
// TODO: best effort cleanup
|
||||
return nil, fmt.Errorf("failed to create a repo on db: %w", err)
|
||||
}
|
||||
|
||||
repo.GitURL = c.urlProvider.GenerateGITCloneURL(ctx, repo.Path)
|
||||
repo.GitSSHURL = c.urlProvider.GenerateGITCloneSSHURL(ctx, repo.Path)
|
||||
|
||||
isPublicAccessSupported, err := c.publicAccess.IsPublicAccessSupported(ctx, parentSpace.Path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to check if public access is supported for parent space %s: %w",
|
||||
parentSpace.Path,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
isRepoPublic := in.IsPublic
|
||||
if !isPublicAccessSupported {
|
||||
log.Debug().Msgf("public access is not supported, create migrating repo %s as private instead", repo.Identifier)
|
||||
isRepoPublic = false
|
||||
}
|
||||
err = c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, isRepoPublic)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to set repo access mode: %w", err)
|
||||
}
|
||||
|
||||
err = c.auditService.Log(ctx,
|
||||
session.Principal,
|
||||
audit.NewResource(audit.ResourceTypeRepository, repo.Identifier),
|
||||
audit.ActionCreated,
|
||||
paths.Parent(repo.Path),
|
||||
audit.WithNewObject(audit.RepositoryObject{
|
||||
Repository: *repo,
|
||||
IsPublic: isRepoPublic,
|
||||
}),
|
||||
audit.WithData("created by", "migrator"),
|
||||
)
|
||||
if err != nil {
|
||||
log.Warn().Msgf("failed to insert audit log for import repository operation: %s", err)
|
||||
}
|
||||
|
||||
return &repoCtrl.RepositoryOutput{
|
||||
Repository: *repo,
|
||||
IsPublic: isRepoPublic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Controller) spaceCheckAuth(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
parentRef string,
|
||||
) (*types.Space, error) {
|
||||
space, err := c.spaceStore.FindByRef(ctx, parentRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parent space not found: %w", err)
|
||||
}
|
||||
|
||||
// create is a special case - check permission without specific resource
|
||||
scope := &types.Scope{SpacePath: space.Path}
|
||||
resource := &types.Resource{
|
||||
Type: enum.ResourceTypeRepo,
|
||||
Identifier: "",
|
||||
}
|
||||
|
||||
err = apiauth.Check(ctx, c.authorizer, session, scope, resource, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("auth check failed: %w", err)
|
||||
}
|
||||
|
||||
return space, nil
|
||||
}
|
||||
|
||||
func (c *Controller) sanitizeCreateRepoInput(in *CreateRepoInput) error {
|
||||
if err := repoCtrl.ValidateParentRef(in.ParentRef); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.identifierCheck(in.Identifier); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
19
app/api/controller/migrate/error.go
Normal file
19
app/api/controller/migrate/error.go
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import "github.com/harness/gitness/errors"
|
||||
|
||||
var errInvalidRepoState = errors.PreconditionFailed("Repository data can't be imported at this point")
|
53
app/api/controller/migrate/pullreq.go
Normal file
53
app/api/controller/migrate/pullreq.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type PullreqsInput struct {
|
||||
PullRequestData []*migrate.ExternalPullRequest `json:"pull_request_data"`
|
||||
}
|
||||
|
||||
func (c *Controller) PullRequests(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
in *PullreqsInput,
|
||||
) ([]*types.PullReq, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to repo: %w", err)
|
||||
}
|
||||
|
||||
if repo.State != enum.RepoStateMigrateDataImport {
|
||||
return nil, fmt.Errorf("repo state is %s want %s: %w",
|
||||
repo.State, enum.RepoStateMigrateDataImport, errInvalidRepoState)
|
||||
}
|
||||
|
||||
pullreqs, err := c.pullreqImporter.Import(ctx, session.Principal, repo, in.PullRequestData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to import pull requests and/or comments: %w", err)
|
||||
}
|
||||
|
||||
return pullreqs, nil
|
||||
}
|
54
app/api/controller/migrate/rules.go
Normal file
54
app/api/controller/migrate/rules.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type RulesInput struct {
|
||||
Rules []*migrate.ExternalRule `json:"rules"`
|
||||
Type migrate.ExternalRuleType `json:"type"`
|
||||
}
|
||||
|
||||
func (c *Controller) Rules(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
in *RulesInput,
|
||||
) ([]*types.Rule, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to repo: %w", err)
|
||||
}
|
||||
|
||||
if repo.State != enum.RepoStateMigrateDataImport {
|
||||
return nil, fmt.Errorf("repo state is %s want %s: %w",
|
||||
repo.State, enum.RepoStateMigrateDataImport, errInvalidRepoState)
|
||||
}
|
||||
|
||||
rulesOut, err := c.ruleImporter.Import(ctx, session.Principal, repo, in.Type, in.Rules)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to import rules: %w", err)
|
||||
}
|
||||
|
||||
return rulesOut, nil
|
||||
}
|
71
app/api/controller/migrate/update_state.go
Normal file
71
app/api/controller/migrate/update_state.go
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
var validTransitions = map[enum.RepoState][]enum.RepoState{
|
||||
enum.RepoStateActive: {enum.RepoStateMigrateDataImport},
|
||||
enum.RepoStateMigrateDataImport: {enum.RepoStateActive},
|
||||
enum.RepoStateMigrateGitPush: {enum.RepoStateActive, enum.RepoStateMigrateDataImport},
|
||||
}
|
||||
|
||||
type UpdateStateInput struct {
|
||||
State enum.RepoState `json:"state"`
|
||||
}
|
||||
|
||||
func (c *Controller) UpdateRepoState(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
in *UpdateStateInput,
|
||||
) (*types.Repository, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to repo: %w", err)
|
||||
}
|
||||
|
||||
if !stateTransitionValid(repo, in.State) {
|
||||
return nil, usererror.BadRequestf("Changing repo state from %s to %s is not allowed.", repo.State, in.State)
|
||||
}
|
||||
|
||||
repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(r *types.Repository) error {
|
||||
r.State = in.State
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update the repo state: %w", err)
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func stateTransitionValid(repo *types.Repository, newState enum.RepoState) bool {
|
||||
for _, validState := range validTransitions[repo.State] {
|
||||
if validState == newState {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
53
app/api/controller/migrate/webhooks.go
Normal file
53
app/api/controller/migrate/webhooks.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type WebhooksInput struct {
|
||||
Webhooks []*migrate.ExternalWebhook `json:"hooks"`
|
||||
}
|
||||
|
||||
func (c *Controller) Webhooks(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
in *WebhooksInput,
|
||||
) ([]*types.Webhook, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to repo: %w", err)
|
||||
}
|
||||
|
||||
if repo.State != enum.RepoStateMigrateDataImport {
|
||||
return nil, fmt.Errorf("repo state is %s want %s: %w",
|
||||
repo.State, enum.RepoStateMigrateDataImport, errInvalidRepoState)
|
||||
}
|
||||
|
||||
hookOut, err := c.webhookImporter.Import(ctx, session.Principal, repo, in.Webhooks)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to import webhooks: %w", err)
|
||||
}
|
||||
|
||||
return hookOut, nil
|
||||
}
|
@ -15,8 +15,16 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/app/api/controller/limiter"
|
||||
"github.com/harness/gitness/app/auth/authz"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/app/services/publicaccess"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/app/url"
|
||||
"github.com/harness/gitness/audit"
|
||||
"github.com/harness/gitness/git"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
@ -28,10 +36,32 @@ var WireSet = wire.NewSet(
|
||||
|
||||
func ProvideController(
|
||||
authorizer authz.Authorizer,
|
||||
principalStore store.PrincipalStore,
|
||||
publicAccess publicaccess.Service,
|
||||
rpcClient git.Interface,
|
||||
urlProvider url.Provider,
|
||||
pullreqImporter *migrate.PullReq,
|
||||
ruleImporter *migrate.Rule,
|
||||
webhookImporter *migrate.Webhook,
|
||||
resourceLimiter limiter.ResourceLimiter,
|
||||
auditService audit.Service,
|
||||
identifierCheck check.RepoIdentifier,
|
||||
tx dbtx.Transactor,
|
||||
spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore,
|
||||
) *Controller {
|
||||
return NewController(
|
||||
authorizer,
|
||||
principalStore,
|
||||
publicAccess,
|
||||
rpcClient,
|
||||
urlProvider,
|
||||
pullreqImporter,
|
||||
ruleImporter,
|
||||
webhookImporter,
|
||||
resourceLimiter,
|
||||
auditService,
|
||||
identifierCheck,
|
||||
tx,
|
||||
spaceStore,
|
||||
repoStore,
|
||||
)
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ import (
|
||||
pullreqevents "github.com/harness/gitness/app/events/pullreq"
|
||||
"github.com/harness/gitness/app/services/codecomments"
|
||||
"github.com/harness/gitness/app/services/codeowners"
|
||||
"github.com/harness/gitness/app/services/importer"
|
||||
"github.com/harness/gitness/app/services/label"
|
||||
locker "github.com/harness/gitness/app/services/locker"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/app/services/protection"
|
||||
"github.com/harness/gitness/app/services/pullreq"
|
||||
"github.com/harness/gitness/app/sse"
|
||||
@ -66,7 +66,7 @@ type Controller struct {
|
||||
sseStreamer sse.Streamer
|
||||
codeOwners *codeowners.Service
|
||||
locker *locker.Locker
|
||||
importer *importer.PullReq
|
||||
importer *migrate.PullReq
|
||||
labelSvc *label.Service
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ func NewController(
|
||||
sseStreamer sse.Streamer,
|
||||
codeowners *codeowners.Service,
|
||||
locker *locker.Locker,
|
||||
importer *importer.PullReq,
|
||||
importer *migrate.PullReq,
|
||||
labelSvc *label.Service,
|
||||
) *Controller {
|
||||
return &Controller{
|
||||
|
@ -19,9 +19,9 @@ import (
|
||||
pullreqevents "github.com/harness/gitness/app/events/pullreq"
|
||||
"github.com/harness/gitness/app/services/codecomments"
|
||||
"github.com/harness/gitness/app/services/codeowners"
|
||||
"github.com/harness/gitness/app/services/importer"
|
||||
"github.com/harness/gitness/app/services/label"
|
||||
"github.com/harness/gitness/app/services/locker"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/app/services/protection"
|
||||
"github.com/harness/gitness/app/services/pullreq"
|
||||
"github.com/harness/gitness/app/sse"
|
||||
@ -48,7 +48,7 @@ func ProvideController(tx dbtx.Transactor, urlProvider url.Provider, authorizer
|
||||
checkStore store.CheckStore,
|
||||
rpcClient git.Interface, eventReporter *pullreqevents.Reporter, codeCommentMigrator *codecomments.Migrator,
|
||||
pullreqService *pullreq.Service, ruleManager *protection.Manager, sseStreamer sse.Streamer,
|
||||
codeOwners *codeowners.Service, locker *locker.Locker, importer *importer.PullReq,
|
||||
codeOwners *codeowners.Service, locker *locker.Locker, importer *migrate.PullReq,
|
||||
labelSvc *label.Service,
|
||||
) *Controller {
|
||||
return NewController(tx, urlProvider, authorizer,
|
||||
|
@ -203,7 +203,7 @@ func (c *Controller) getRepoCheckAccessForGit(
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Controller) validateParentRef(parentRef string) error {
|
||||
func ValidateParentRef(parentRef string) error {
|
||||
parentRefAsID, err := strconv.ParseInt(parentRef, 10, 64)
|
||||
if (err == nil && parentRefAsID <= 0) || (len(strings.TrimSpace(parentRef)) == 0) {
|
||||
return errRepositoryRequiresParent
|
||||
|
@ -208,7 +208,7 @@ func (c *Controller) sanitizeCreateInput(in *CreateInput) error {
|
||||
in.Identifier = in.UID
|
||||
}
|
||||
|
||||
if err := c.validateParentRef(in.ParentRef); err != nil {
|
||||
if err := ValidateParentRef(in.ParentRef); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ func (c *Controller) sanitizeImportInput(in *ImportInput) error {
|
||||
in.Identifier = in.UID
|
||||
}
|
||||
|
||||
if err := c.validateParentRef(in.ParentRef); err != nil {
|
||||
if err := ValidateParentRef(in.ParentRef); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,8 @@ const (
|
||||
|
||||
var ErrInternalWebhookOperationNotAllowed = usererror.Forbidden("changes to internal webhooks are not allowed")
|
||||
|
||||
// checkURL validates the url of a webhook.
|
||||
func checkURL(rawURL string, allowLoopback bool, allowPrivateNetwork bool) error {
|
||||
// CheckURL validates the url of a webhook.
|
||||
func CheckURL(rawURL string, allowLoopback bool, allowPrivateNetwork bool) error {
|
||||
// check URL
|
||||
if len(rawURL) > webhookMaxURLLength {
|
||||
return check.NewValidationErrorf("The URL of a webhook can be at most %d characters long.",
|
||||
@ -84,8 +84,8 @@ func checkSecret(secret string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkTriggers validates the triggers of a webhook.
|
||||
func checkTriggers(triggers []enum.WebhookTrigger) error {
|
||||
// CheckTriggers validates the triggers of a webhook.
|
||||
func CheckTriggers(triggers []enum.WebhookTrigger) error {
|
||||
// ignore duplicates here, should be deduplicated later
|
||||
for _, trigger := range triggers {
|
||||
if _, ok := trigger.Sanitize(); !ok {
|
||||
@ -96,8 +96,8 @@ func checkTriggers(triggers []enum.WebhookTrigger) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// deduplicateTriggers de-duplicates the triggers provided by the user.
|
||||
func deduplicateTriggers(in []enum.WebhookTrigger) []enum.WebhookTrigger {
|
||||
// DeduplicateTriggers de-duplicates the triggers provided by the user.
|
||||
func DeduplicateTriggers(in []enum.WebhookTrigger) []enum.WebhookTrigger {
|
||||
if len(in) == 0 {
|
||||
return []enum.WebhookTrigger{}
|
||||
}
|
||||
@ -114,3 +114,11 @@ func deduplicateTriggers(in []enum.WebhookTrigger) []enum.WebhookTrigger {
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func ConvertTriggers(vals []string) []enum.WebhookTrigger {
|
||||
res := make([]enum.WebhookTrigger, len(vals))
|
||||
for i := range vals {
|
||||
res[i] = enum.WebhookTrigger(vals[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ func (c *Controller) Create(
|
||||
Secret: string(encryptedSecret),
|
||||
Enabled: in.Enabled,
|
||||
Insecure: in.Insecure,
|
||||
Triggers: deduplicateTriggers(in.Triggers),
|
||||
Triggers: DeduplicateTriggers(in.Triggers),
|
||||
LatestExecutionResult: nil,
|
||||
}
|
||||
|
||||
@ -149,13 +149,13 @@ func sanitizeCreateInput(in *CreateInput, allowLoopback bool, allowPrivateNetwor
|
||||
if err := check.Description(in.Description); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkURL(in.URL, allowLoopback, allowPrivateNetwork); err != nil {
|
||||
if err := CheckURL(in.URL, allowLoopback, allowPrivateNetwork); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkSecret(in.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkTriggers(in.Triggers); err != nil { //nolint:revive
|
||||
if err := CheckTriggers(in.Triggers); err != nil { //nolint:revive
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ func (c *Controller) Update(
|
||||
hook.Insecure = *in.Insecure
|
||||
}
|
||||
if in.Triggers != nil {
|
||||
hook.Triggers = deduplicateTriggers(in.Triggers)
|
||||
hook.Triggers = DeduplicateTriggers(in.Triggers)
|
||||
}
|
||||
|
||||
if err = c.webhookStore.Update(ctx, hook); err != nil {
|
||||
@ -125,7 +125,7 @@ func sanitizeUpdateInput(in *UpdateInput, allowLoopback bool, allowPrivateNetwor
|
||||
}
|
||||
}
|
||||
if in.URL != nil {
|
||||
if err := checkURL(*in.URL, allowLoopback, allowPrivateNetwork); err != nil {
|
||||
if err := CheckURL(*in.URL, allowLoopback, allowPrivateNetwork); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -135,7 +135,7 @@ func sanitizeUpdateInput(in *UpdateInput, allowLoopback bool, allowPrivateNetwor
|
||||
}
|
||||
}
|
||||
if in.Triggers != nil {
|
||||
if err := checkTriggers(in.Triggers); err != nil {
|
||||
if err := CheckTriggers(in.Triggers); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
47
app/api/handler/migrate/create_repo.go
Normal file
47
app/api/handler/migrate/create_repo.go
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/migrate"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleCreateRepo handles API that create an empty repo ready for migration.
|
||||
func HandleCreateRepo(migCtrl *migrate.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
in := new(migrate.CreateRepoInput)
|
||||
err := json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := migCtrl.CreateRepo(ctx, session, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusCreated, repo)
|
||||
}
|
||||
}
|
53
app/api/handler/migrate/pullreq.go
Normal file
53
app/api/handler/migrate/pullreq.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/migrate"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandlePullRequests handles API that imports pull requests to a repository.
|
||||
func HandlePullRequests(migCtrl *migrate.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
in := new(migrate.PullreqsInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
pullReqs, err := migCtrl.PullRequests(ctx, session, repoRef, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusCreated, pullReqs)
|
||||
}
|
||||
}
|
53
app/api/handler/migrate/rules.go
Normal file
53
app/api/handler/migrate/rules.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/migrate"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleRules handles API that imports protection rule(s) to a repository.
|
||||
func HandleRules(migCtrl *migrate.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
in := new(migrate.RulesInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
rules, err := migCtrl.Rules(ctx, session, repoRef, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusCreated, rules)
|
||||
}
|
||||
}
|
53
app/api/handler/migrate/update_state.go
Normal file
53
app/api/handler/migrate/update_state.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/migrate"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleUpdateRepoState handles API that updates the repository state.
|
||||
func HandleUpdateRepoState(migCtrl *migrate.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
in := new(migrate.UpdateStateInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := migCtrl.UpdateRepoState(ctx, session, repoRef, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, repo)
|
||||
}
|
||||
}
|
53
app/api/handler/migrate/webhooks.go
Normal file
53
app/api/handler/migrate/webhooks.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/migrate"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleWebhooks returns a http.HandlerFunc that import webhooks.
|
||||
func HandleWebhooks(migCtrl *migrate.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
in := new(migrate.WebhooksInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
hooks, err := migCtrl.Webhooks(ctx, session, repoRef, in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusCreated, hooks)
|
||||
}
|
||||
}
|
@ -43,6 +43,11 @@ func Forbidden(ctx context.Context, w http.ResponseWriter) {
|
||||
UserError(ctx, w, usererror.ErrForbidden)
|
||||
}
|
||||
|
||||
// Forbiddenf writes the json-encoded message with a forbidden error.
|
||||
func Forbiddenf(ctx context.Context, w http.ResponseWriter, format string, args ...interface{}) {
|
||||
UserError(ctx, w, usererror.Newf(http.StatusForbidden, format, args...))
|
||||
}
|
||||
|
||||
// BadRequest writes the json-encoded message for a bad request error.
|
||||
func BadRequest(ctx context.Context, w http.ResponseWriter) {
|
||||
UserError(ctx, w, usererror.ErrBadRequest)
|
||||
|
@ -52,6 +52,7 @@ import (
|
||||
handlerinfraProvider "github.com/harness/gitness/app/api/handler/infraprovider"
|
||||
handlerkeywordsearch "github.com/harness/gitness/app/api/handler/keywordsearch"
|
||||
handlerlogs "github.com/harness/gitness/app/api/handler/logs"
|
||||
handlermigrate "github.com/harness/gitness/app/api/handler/migrate"
|
||||
handlerpipeline "github.com/harness/gitness/app/api/handler/pipeline"
|
||||
handlerplugin "github.com/harness/gitness/app/api/handler/plugin"
|
||||
handlerprincipal "github.com/harness/gitness/app/api/handler/principal"
|
||||
@ -92,7 +93,8 @@ import (
|
||||
var (
|
||||
// terminatedPathPrefixesAPI is the list of prefixes that will require resolving terminated paths.
|
||||
terminatedPathPrefixesAPI = []string{"/v1/spaces/", "/v1/repos/",
|
||||
"/v1/secrets/", "/v1/connectors", "/v1/templates/step", "/v1/templates/stage", "/v1/gitspaces", "/v1/infraproviders"}
|
||||
"/v1/secrets/", "/v1/connectors", "/v1/templates/step", "/v1/templates/stage",
|
||||
"/v1/gitspaces", "/v1/infraproviders", "/v1/migrate/repos"}
|
||||
)
|
||||
|
||||
// NewAPIHandler returns a new APIHandler.
|
||||
@ -658,6 +660,7 @@ func SetupRules(r chi.Router, repoCtrl *repo.Controller) {
|
||||
r.Route("/rules", func(r chi.Router) {
|
||||
r.Post("/", handlerrepo.HandleRuleCreate(repoCtrl))
|
||||
r.Get("/", handlerrepo.HandleRuleList(repoCtrl))
|
||||
|
||||
r.Route(fmt.Sprintf("/{%s}", request.PathParamRuleIdentifier), func(r chi.Router) {
|
||||
r.Patch("/", handlerrepo.HandleRuleUpdate(repoCtrl))
|
||||
r.Delete("/", handlerrepo.HandleRuleDelete(repoCtrl))
|
||||
@ -813,12 +816,16 @@ func setupAccountWithAuth(r chi.Router, userCtrl *user.Controller, config *types
|
||||
r.Post("/logout", account.HandleLogout(userCtrl, cookieName))
|
||||
}
|
||||
|
||||
func setupMigrate(r chi.Router, ctrl *migrate.Controller) {
|
||||
func setupMigrate(r chi.Router, migCtrl *migrate.Controller) {
|
||||
r.Route("/migrate", func(r chi.Router) {
|
||||
SetupMigrateRoutes(r, ctrl)
|
||||
r.Route("/repos", func(r chi.Router) {
|
||||
r.Post("/", handlermigrate.HandleCreateRepo(migCtrl))
|
||||
r.Route(fmt.Sprintf("/{%s}", request.PathParamRepoRef), func(r chi.Router) {
|
||||
r.Patch("/update-state", handlermigrate.HandleUpdateRepoState(migCtrl))
|
||||
r.Post("/pullreqs", handlermigrate.HandlePullRequests(migCtrl))
|
||||
r.Post("/webhooks", handlermigrate.HandleWebhooks(migCtrl))
|
||||
r.Post("/rules", handlermigrate.HandleRules(migCtrl))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func SetupMigrateRoutes(_ chi.Router, _ *migrate.Controller) {
|
||||
// add migrate routes with spaces
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import (
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideRepoImporter,
|
||||
ProvidePullReqImporter,
|
||||
)
|
||||
|
||||
func ProvideRepoImporter(
|
||||
@ -74,25 +73,3 @@ func ProvideRepoImporter(
|
||||
|
||||
return importer, nil
|
||||
}
|
||||
|
||||
func ProvidePullReqImporter(
|
||||
urlProvider url.Provider,
|
||||
git git.Interface,
|
||||
principalStore store.PrincipalStore,
|
||||
repoStore store.RepoStore,
|
||||
pullReqStore store.PullReqStore,
|
||||
pullReqActStore store.PullReqActivityStore,
|
||||
tx dbtx.Transactor,
|
||||
) *PullReq {
|
||||
importer := &PullReq{
|
||||
urlProvider: urlProvider,
|
||||
git: git,
|
||||
principalStore: principalStore,
|
||||
repoStore: repoStore,
|
||||
pullReqStore: pullReqStore,
|
||||
pullReqActStore: pullReqActStore,
|
||||
tx: tx,
|
||||
}
|
||||
|
||||
return importer
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package importer
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -27,6 +27,7 @@ import (
|
||||
"github.com/harness/gitness/errors"
|
||||
"github.com/harness/gitness/git"
|
||||
"github.com/harness/gitness/git/parser"
|
||||
gitness_store "github.com/harness/gitness/store"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
@ -34,7 +35,7 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// PullReq is pull request importer.
|
||||
// PullReq is pull request migrate.
|
||||
type PullReq struct {
|
||||
urlProvider url.Provider
|
||||
git git.Interface
|
||||
@ -45,6 +46,26 @@ type PullReq struct {
|
||||
tx dbtx.Transactor
|
||||
}
|
||||
|
||||
func NewPullReq(
|
||||
urlProvider url.Provider,
|
||||
git git.Interface,
|
||||
principalStore store.PrincipalStore,
|
||||
repoStore store.RepoStore,
|
||||
pullReqStore store.PullReqStore,
|
||||
pullReqActStore store.PullReqActivityStore,
|
||||
tx dbtx.Transactor,
|
||||
) *PullReq {
|
||||
return &PullReq{
|
||||
urlProvider: urlProvider,
|
||||
git: git,
|
||||
principalStore: principalStore,
|
||||
repoStore: repoStore,
|
||||
pullReqStore: pullReqStore,
|
||||
pullReqActStore: pullReqActStore,
|
||||
tx: tx,
|
||||
}
|
||||
}
|
||||
|
||||
type repoImportState struct {
|
||||
git git.Interface
|
||||
readParams git.ReadParams
|
||||
@ -52,29 +73,30 @@ type repoImportState struct {
|
||||
pullReqActivityStore store.PullReqActivityStore
|
||||
branchCheck map[string]*git.Branch
|
||||
principals map[string]*types.Principal
|
||||
unknownEmails map[int]map[string]bool
|
||||
migrator types.Principal
|
||||
}
|
||||
|
||||
// Import load provided pull requests in go-scm format and imports them.
|
||||
//
|
||||
//nolint:gocognit
|
||||
func (importer PullReq) Import(
|
||||
func (migrate PullReq) Import(
|
||||
ctx context.Context,
|
||||
migrator types.Principal,
|
||||
repo *types.Repository,
|
||||
extPullReqs []*ExternalPullRequest,
|
||||
) ([]*types.PullReq, error) {
|
||||
if repo.State != enum.RepoStateMigrateDataImport {
|
||||
return nil, errors.PreconditionFailed("Repository data can't be imported at this point")
|
||||
}
|
||||
|
||||
readParams := git.ReadParams{RepoUID: repo.GitUID}
|
||||
|
||||
repoState := repoImportState{
|
||||
git: importer.git,
|
||||
git: migrate.git,
|
||||
readParams: readParams,
|
||||
principalStore: importer.principalStore,
|
||||
pullReqActivityStore: importer.pullReqActStore,
|
||||
principalStore: migrate.principalStore,
|
||||
pullReqActivityStore: migrate.pullReqActStore,
|
||||
branchCheck: map[string]*git.Branch{},
|
||||
principals: map[string]*types.Principal{},
|
||||
unknownEmails: map[int]map[string]bool{},
|
||||
migrator: migrator,
|
||||
}
|
||||
|
||||
pullReqUnique := map[int]struct{}{}
|
||||
@ -103,13 +125,13 @@ func (importer PullReq) Import(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err := importer.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
err := migrate.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
var deltaOpen, deltaClosed, deltaMerged int
|
||||
var maxNumber int64
|
||||
|
||||
// Store the pull request objects and the comments.
|
||||
for _, pullReq := range pullReqs {
|
||||
if err := importer.pullReqStore.Create(ctx, pullReq); err != nil {
|
||||
if err := migrate.pullReqStore.Create(ctx, pullReq); err != nil {
|
||||
return fmt.Errorf("failed to import the pull request %d: %w", pullReq.Number, err)
|
||||
}
|
||||
|
||||
@ -131,18 +153,28 @@ func (importer PullReq) Import(
|
||||
return fmt.Errorf("failed to import pull request comments: %w", err)
|
||||
}
|
||||
|
||||
// Add a comment if any principal (PR author or commenter) were replaced by the fallback migrator principal
|
||||
if prUnknownEmails, ok := repoState.unknownEmails[int(pullReq.Number)]; ok && len(prUnknownEmails) != 0 {
|
||||
infoComment, err := repoState.createInfoComment(ctx, repo, pullReq)
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Warn().Err(err).Msg("failed to add an informational comment for replacing non-existing users")
|
||||
} else {
|
||||
comments = append(comments, infoComment)
|
||||
}
|
||||
}
|
||||
|
||||
if len(comments) == 0 { // no need to update the pull request object in the DB if there are no comments.
|
||||
continue
|
||||
}
|
||||
|
||||
if err := importer.pullReqStore.Update(ctx, pullReq); err != nil {
|
||||
if err := migrate.pullReqStore.Update(ctx, pullReq); err != nil {
|
||||
return fmt.Errorf("failed to update pull request after importing of the comments: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the repository
|
||||
|
||||
repoUpdate, err := importer.repoStore.Find(ctx, repo.ID)
|
||||
repoUpdate, err := migrate.repoStore.Find(ctx, repo.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch repo in pull request import: %w", err)
|
||||
}
|
||||
@ -155,7 +187,7 @@ func (importer PullReq) Import(
|
||||
repoUpdate.NumClosedPulls += deltaClosed
|
||||
repoUpdate.NumMergedPulls += deltaMerged
|
||||
|
||||
if err := importer.repoStore.Update(ctx, repoUpdate); err != nil {
|
||||
if err := migrate.repoStore.Update(ctx, repoUpdate); err != nil {
|
||||
return fmt.Errorf("failed to update repo in pull request import: %w", err)
|
||||
}
|
||||
|
||||
@ -181,7 +213,7 @@ func (r *repoImportState) convertPullReq(
|
||||
Int("pullreq.number", extPullReq.Number).
|
||||
Logger()
|
||||
|
||||
author, err := r.getPrincipalByEmail(ctx, extPullReq.Author.Email)
|
||||
author, err := r.getPrincipalByEmail(ctx, extPullReq.Author.Email, extPullReq.Number, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get pull request author: %w", err)
|
||||
}
|
||||
@ -200,7 +232,7 @@ func (r *repoImportState) convertPullReq(
|
||||
Edited: updatedAt,
|
||||
Closed: nil,
|
||||
State: enum.PullReqStateOpen,
|
||||
IsDraft: false,
|
||||
IsDraft: extPullReq.Draft,
|
||||
CommentCount: 0,
|
||||
UnresolvedCount: 0,
|
||||
Title: extPullReq.Title,
|
||||
@ -239,14 +271,16 @@ func (r *repoImportState) convertPullReq(
|
||||
pr.MergeCheckStatus = enum.MergeCheckStatusMergeable
|
||||
pr.SourceSHA = extPullReq.Head.SHA
|
||||
pr.MergeTargetSHA = &extPullReq.Base.SHA
|
||||
pr.MergeBaseSHA = extPullReq.Head.SHA // Don't have the real value. Set the value to SourceSHA.
|
||||
pr.MergeSHA = nil // Don't have this.
|
||||
pr.MergeBaseSHA = extPullReq.Base.SHA
|
||||
pr.MergeSHA = nil // Don't have this.
|
||||
pr.MergeConflicts = nil
|
||||
|
||||
case enum.PullReqStateClosed:
|
||||
// For closed PR's it's not important to verify existence of branches and commits.
|
||||
// If these don't exist the PR will be impossible to open.
|
||||
|
||||
pr.SourceSHA = extPullReq.Head.SHA
|
||||
pr.MergeTargetSHA = &extPullReq.Base.SHA
|
||||
pr.MergeBaseSHA = extPullReq.Base.SHA
|
||||
pr.MergeCheckStatus = enum.MergeCheckStatusUnchecked
|
||||
pr.MergeSHA = nil
|
||||
pr.MergeConflicts = nil
|
||||
@ -353,11 +387,10 @@ func (r *repoImportState) createComment(
|
||||
order, subOrder, replySeq int,
|
||||
extComment *ExternalComment,
|
||||
) (*types.PullReqActivity, error) {
|
||||
commenter, err := r.getPrincipalByEmail(ctx, extComment.Author.Email)
|
||||
commenter, err := r.getPrincipalByEmail(ctx, extComment.Author.Email, int(pullReq.Number), false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get comment ID=%d author: %w", extComment.ID, err)
|
||||
}
|
||||
|
||||
commentedAt := extComment.Created.UnixMilli()
|
||||
|
||||
// Mark comments as resolved if the PR is merged, otherwise they are unresolved.
|
||||
@ -440,17 +473,87 @@ func (r *repoImportState) createComment(
|
||||
return comment, nil
|
||||
}
|
||||
|
||||
func (r *repoImportState) getPrincipalByEmail(ctx context.Context, emailAddress string) (*types.Principal, error) {
|
||||
// createInfoComment creates an informational comment on the PR
|
||||
// if any of the principals were replaced with the migrator.
|
||||
func (r *repoImportState) createInfoComment(
|
||||
ctx context.Context,
|
||||
repo *types.Repository,
|
||||
pullReq *types.PullReq,
|
||||
) (*types.PullReqActivity, error) {
|
||||
var unknownEmails []string
|
||||
for email := range r.unknownEmails[int(pullReq.Number)] {
|
||||
unknownEmails = append(unknownEmails, email)
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
text := fmt.Sprintf(InfoCommentMessage, r.migrator.UID, strings.Join(unknownEmails, ", "))
|
||||
comment := &types.PullReqActivity{
|
||||
CreatedBy: r.migrator.ID,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
Deleted: nil,
|
||||
ParentID: nil,
|
||||
RepoID: repo.ID,
|
||||
PullReqID: pullReq.ID,
|
||||
Order: pullReq.ActivitySeq + 1,
|
||||
SubOrder: 0,
|
||||
ReplySeq: 0,
|
||||
Type: enum.PullReqActivityTypeComment,
|
||||
Kind: enum.PullReqActivityKindComment,
|
||||
Text: text,
|
||||
PayloadRaw: json.RawMessage("{}"),
|
||||
Metadata: nil,
|
||||
ResolvedBy: &r.migrator.ID,
|
||||
Resolved: &now,
|
||||
CodeComment: nil,
|
||||
Mentions: nil,
|
||||
}
|
||||
|
||||
if err := r.pullReqActivityStore.Create(ctx, comment); err != nil {
|
||||
return nil, fmt.Errorf("failed to store the info comment author: %w", err)
|
||||
}
|
||||
|
||||
pullReq.ActivitySeq++
|
||||
pullReq.CommentCount++
|
||||
|
||||
return comment, nil
|
||||
}
|
||||
|
||||
func (r *repoImportState) getPrincipalByEmail(
|
||||
ctx context.Context,
|
||||
emailAddress string,
|
||||
prNumber int,
|
||||
strict bool,
|
||||
) (*types.Principal, error) {
|
||||
if principal, exists := r.principals[emailAddress]; exists {
|
||||
return principal, nil
|
||||
}
|
||||
|
||||
principal, err := r.principalStore.FindByEmail(ctx, emailAddress)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, gitness_store.ErrResourceNotFound) {
|
||||
return nil, fmt.Errorf("failed to load principal by email: %w", err)
|
||||
}
|
||||
|
||||
return principal, nil
|
||||
if err == nil {
|
||||
r.principals[emailAddress] = principal
|
||||
return principal, nil
|
||||
}
|
||||
|
||||
if strict {
|
||||
return nil, fmt.Errorf(
|
||||
"could not find principal by email %s and automatic replacing unknown prinicapls is disabled: %w",
|
||||
emailAddress, err)
|
||||
}
|
||||
|
||||
// ignore not found emails if is not strict
|
||||
if _, exists := r.unknownEmails[prNumber]; !exists {
|
||||
r.unknownEmails[prNumber] = make(map[string]bool, 0)
|
||||
}
|
||||
|
||||
if _, ok := r.unknownEmails[prNumber][emailAddress]; !ok && len(r.unknownEmails[prNumber]) < MaxNumberOfUnknownEmails {
|
||||
r.unknownEmails[prNumber][emailAddress] = true
|
||||
}
|
||||
|
||||
return &r.migrator, nil
|
||||
}
|
||||
|
||||
func timestampMillis(t time.Time, def int64) int64 {
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package importer
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"testing"
|
32
app/services/migrate/pullreq_types.go
Normal file
32
app/services/migrate/pullreq_types.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import migratetypes "github.com/harness/harness-migrate/types"
|
||||
|
||||
type ExternalPullRequest = migratetypes.PullRequestData
|
||||
type ExternalComment = migratetypes.Comment
|
||||
|
||||
type externalCommentThread struct {
|
||||
TopLevel ExternalComment
|
||||
Replies []ExternalComment
|
||||
}
|
||||
|
||||
const (
|
||||
InfoCommentMessage = "This pull request has been imported. Non-existent users who were originally listed " +
|
||||
"as the pull request author or commenter have been replaced by the principal '%s' which performed the migration.\n" +
|
||||
"Unknown emails: %v"
|
||||
MaxNumberOfUnknownEmails = 500 // limit keeping unknown users to avoid info comment text exceed ~1000 characters
|
||||
)
|
178
app/services/migrate/rule.go
Normal file
178
app/services/migrate/rule.go
Normal file
@ -0,0 +1,178 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/app/services/protection"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/errors"
|
||||
gitness_store "github.com/harness/gitness/store"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
migratetypes "github.com/harness/harness-migrate/types"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Rule struct {
|
||||
ruleStore store.RuleStore
|
||||
principalStore store.PrincipalStore
|
||||
tx dbtx.Transactor
|
||||
|
||||
DefDeserializationMap map[migratetypes.RuleType]definitionDeserializer
|
||||
PatternDeserializationMap map[migratetypes.RuleType]patternDeserializer
|
||||
}
|
||||
|
||||
func NewRule(
|
||||
ruleStore store.RuleStore,
|
||||
tx dbtx.Transactor,
|
||||
principalStore store.PrincipalStore,
|
||||
) *Rule {
|
||||
rule := &Rule{
|
||||
ruleStore: ruleStore,
|
||||
principalStore: principalStore,
|
||||
tx: tx,
|
||||
DefDeserializationMap: make(map[ExternalRuleType]definitionDeserializer),
|
||||
PatternDeserializationMap: make(map[ExternalRuleType]patternDeserializer),
|
||||
}
|
||||
|
||||
rule.registerDeserializers(principalStore)
|
||||
|
||||
return rule
|
||||
}
|
||||
|
||||
func (migrate Rule) Import(
|
||||
ctx context.Context,
|
||||
migrator types.Principal,
|
||||
repo *types.Repository,
|
||||
typ ExternalRuleType,
|
||||
extRules []*ExternalRule,
|
||||
) ([]*types.Rule, error) {
|
||||
rules := make([]*types.Rule, len(extRules))
|
||||
for i, extRule := range extRules {
|
||||
if err := check.Identifier(extRule.Identifier); err != nil {
|
||||
return nil, fmt.Errorf("branch rule identifier '%s' is invalid: %w", extRule.Identifier, err)
|
||||
}
|
||||
|
||||
def, err := migrate.DefDeserializationMap[typ](ctx, string(extRule.Definition))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to deserialize rule definition: %w", err)
|
||||
}
|
||||
|
||||
if err = def.Sanitize(); err != nil {
|
||||
return nil, fmt.Errorf("provided rule definition is invalid: %w", err)
|
||||
}
|
||||
|
||||
definitionJSON, err := json.Marshal(def)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal rule definition: %w", err)
|
||||
}
|
||||
|
||||
pattern, err := migrate.PatternDeserializationMap[typ](ctx, string(extRule.Pattern))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to deserialize rule pattern: %w", err)
|
||||
}
|
||||
|
||||
if err = pattern.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("provided rule pattern is invalid: %w", err)
|
||||
}
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
r := &types.Rule{
|
||||
CreatedBy: migrator.ID,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
RepoID: &repo.ID,
|
||||
SpaceID: nil,
|
||||
Type: protection.TypeBranch,
|
||||
State: enum.RuleStateActive,
|
||||
Identifier: extRule.Identifier,
|
||||
Pattern: pattern.JSON(),
|
||||
Definition: json.RawMessage(definitionJSON),
|
||||
}
|
||||
rules[i] = r
|
||||
}
|
||||
|
||||
err := migrate.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
for _, rule := range rules {
|
||||
err := migrate.ruleStore.Create(ctx, rule)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create branch rule: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to store external branch rules: %w", err)
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func mapToBranchRules(
|
||||
ctx context.Context,
|
||||
rule ExternalDefinition,
|
||||
principalStore store.PrincipalStore,
|
||||
) (*protection.Branch, error) {
|
||||
// map users
|
||||
var userIDs []int64
|
||||
for _, email := range rule.Bypass.UserEmails {
|
||||
principal, err := principalStore.FindByEmail(ctx, email)
|
||||
if err != nil && !errors.Is(err, gitness_store.ErrResourceNotFound) {
|
||||
return nil, fmt.Errorf("failed to find principal by email for '%s': %w", email, err)
|
||||
}
|
||||
|
||||
if errors.Is(err, gitness_store.ErrResourceNotFound) {
|
||||
log.Ctx(ctx).Warn().Msgf("skipping principal '%s' on bypass list", email)
|
||||
continue
|
||||
}
|
||||
|
||||
userIDs = append(userIDs, principal.ID)
|
||||
}
|
||||
|
||||
return &protection.Branch{
|
||||
Bypass: protection.DefBypass{
|
||||
UserIDs: userIDs,
|
||||
RepoOwners: rule.Bypass.RepoOwners,
|
||||
},
|
||||
|
||||
PullReq: protection.DefPullReq{
|
||||
Approvals: protection.DefApprovals(rule.PullReq.Approvals),
|
||||
Comments: protection.DefComments(rule.PullReq.Comments),
|
||||
StatusChecks: protection.DefStatusChecks(rule.PullReq.StatusChecks),
|
||||
Merge: protection.DefMerge{
|
||||
StrategiesAllowed: convertMergeMethods(rule.PullReq.Merge.StrategiesAllowed),
|
||||
DeleteBranch: rule.PullReq.Merge.DeleteBranch,
|
||||
},
|
||||
},
|
||||
|
||||
Lifecycle: protection.DefLifecycle(rule.Lifecycle),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertMergeMethods(vals []string) []enum.MergeMethod {
|
||||
res := make([]enum.MergeMethod, len(vals))
|
||||
for i := range vals {
|
||||
res[i] = enum.MergeMethod(vals[i])
|
||||
}
|
||||
return res
|
||||
}
|
82
app/services/migrate/rule_types.go
Normal file
82
app/services/migrate/rule_types.go
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/services/protection"
|
||||
"github.com/harness/gitness/app/store"
|
||||
|
||||
migratetypes "github.com/harness/harness-migrate/types"
|
||||
)
|
||||
|
||||
const ExternalRuleTypeBranch = migratetypes.RuleTypeBranch
|
||||
|
||||
type (
|
||||
ExternalRuleType = migratetypes.RuleType
|
||||
ExternalRule = migratetypes.Rule
|
||||
|
||||
ExternalDefinition = migratetypes.Definition
|
||||
ExternalBranchPattern = migratetypes.BranchPattern
|
||||
|
||||
definitionDeserializer func(context.Context, string) (protection.Definition, error)
|
||||
patternDeserializer func(context.Context, string) (*protection.Pattern, error)
|
||||
)
|
||||
|
||||
func (migrate *Rule) registerDeserializers(principalStore store.PrincipalStore) {
|
||||
// banch rules definition deserializer
|
||||
migrate.DefDeserializationMap[ExternalRuleTypeBranch] = func(
|
||||
ctx context.Context,
|
||||
rawDef string,
|
||||
) (protection.Definition, error) {
|
||||
// deserialize string into external branch rule type
|
||||
var extrDef ExternalDefinition
|
||||
|
||||
decoder := json.NewDecoder(bytes.NewReader([]byte(rawDef)))
|
||||
if err := decoder.Decode(&extrDef); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode external branch rule definition: %w", err)
|
||||
}
|
||||
|
||||
rule, err := mapToBranchRules(ctx, extrDef, principalStore)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to map external branch rule definition to internal: %w", err)
|
||||
}
|
||||
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
// branch rules pattern deserializer
|
||||
migrate.PatternDeserializationMap[ExternalRuleTypeBranch] = func(
|
||||
_ context.Context,
|
||||
rawDef string,
|
||||
) (*protection.Pattern, error) {
|
||||
var extrPattern ExternalBranchPattern
|
||||
|
||||
decoder := json.NewDecoder(bytes.NewReader([]byte(rawDef)))
|
||||
if err := decoder.Decode(&extrPattern); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode external branch rule pattern: %w", err)
|
||||
}
|
||||
|
||||
return &protection.Pattern{
|
||||
Default: extrPattern.Default,
|
||||
Include: extrPattern.Include,
|
||||
Exclude: extrPattern.Exclude,
|
||||
}, nil
|
||||
}
|
||||
}
|
129
app/services/migrate/webhook.go
Normal file
129
app/services/migrate/webhook.go
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
webhookpkg "github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/services/webhook"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// Webhook is webhook migrate.
|
||||
type Webhook struct {
|
||||
// webhook configs
|
||||
allowLoopback bool
|
||||
allowPrivateNetwork bool
|
||||
|
||||
tx dbtx.Transactor
|
||||
webhookStore store.WebhookStore
|
||||
}
|
||||
|
||||
func NewWebhook(
|
||||
config webhook.Config,
|
||||
tx dbtx.Transactor,
|
||||
webhookStore store.WebhookStore,
|
||||
) *Webhook {
|
||||
return &Webhook{
|
||||
allowLoopback: config.AllowLoopback,
|
||||
allowPrivateNetwork: config.AllowPrivateNetwork,
|
||||
tx: tx,
|
||||
webhookStore: webhookStore,
|
||||
}
|
||||
}
|
||||
|
||||
func (migrate Webhook) Import(
|
||||
ctx context.Context,
|
||||
migrator types.Principal,
|
||||
repo *types.Repository,
|
||||
extWebhooks []*ExternalWebhook,
|
||||
) ([]*types.Webhook, error) {
|
||||
now := time.Now().UnixMilli()
|
||||
hooks := make([]*types.Webhook, len(extWebhooks))
|
||||
|
||||
// sanitize and convert webhooks
|
||||
for i, whook := range extWebhooks {
|
||||
triggers := webhookpkg.ConvertTriggers(whook.Events)
|
||||
err := sanitizeWebhook(whook, triggers, migrate.allowLoopback, migrate.allowPrivateNetwork)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to sanitize external webhook input: %w", err)
|
||||
}
|
||||
|
||||
// create new webhook object
|
||||
hook := &types.Webhook{
|
||||
ID: 0, // the ID will be populated in the data layer
|
||||
Version: 0, // the Version will be populated in the data layer
|
||||
CreatedBy: migrator.ID,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
ParentID: repo.ID,
|
||||
ParentType: enum.WebhookParentRepo,
|
||||
|
||||
// user input
|
||||
Identifier: whook.Identifier,
|
||||
DisplayName: whook.Identifier,
|
||||
URL: whook.Target,
|
||||
Enabled: whook.Active,
|
||||
Insecure: whook.SkipVerify,
|
||||
Triggers: webhookpkg.DeduplicateTriggers(triggers),
|
||||
LatestExecutionResult: nil,
|
||||
}
|
||||
|
||||
hooks[i] = hook
|
||||
}
|
||||
|
||||
err := migrate.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
for _, hook := range hooks {
|
||||
err := migrate.webhookStore.Create(ctx, hook)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to store webhook: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to store external webhooks: %w", err)
|
||||
}
|
||||
|
||||
return hooks, nil
|
||||
}
|
||||
|
||||
func sanitizeWebhook(
|
||||
in *ExternalWebhook,
|
||||
triggers []enum.WebhookTrigger,
|
||||
allowLoopback bool,
|
||||
allowPrivateNetwork bool,
|
||||
) error {
|
||||
if err := check.Identifier(in.Identifier); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := webhookpkg.CheckURL(in.Target, allowLoopback, allowPrivateNetwork); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := webhookpkg.CheckTriggers(triggers); err != nil { //nolint:revive
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -12,16 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package importer
|
||||
package migrate
|
||||
|
||||
import (
|
||||
migratetypes "github.com/harness/harness-migrate/types"
|
||||
import migratetypes "github.com/harness/harness-migrate/types"
|
||||
|
||||
type (
|
||||
ExternalWebhook = migratetypes.Hook
|
||||
)
|
||||
|
||||
type ExternalPullRequest = migratetypes.PullRequestData
|
||||
type ExternalComment = migratetypes.Comment
|
||||
|
||||
type externalCommentThread struct {
|
||||
TopLevel ExternalComment
|
||||
Replies []ExternalComment
|
||||
}
|
59
app/services/migrate/wire.go
Normal file
59
app/services/migrate/wire.go
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/app/services/webhook"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/app/url"
|
||||
"github.com/harness/gitness/git"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvidePullReqImporter,
|
||||
ProvideRuleImporter,
|
||||
ProvideWebhookImporter,
|
||||
)
|
||||
|
||||
func ProvidePullReqImporter(
|
||||
urlProvider url.Provider,
|
||||
git git.Interface,
|
||||
principalStore store.PrincipalStore,
|
||||
repoStore store.RepoStore,
|
||||
pullReqStore store.PullReqStore,
|
||||
pullReqActStore store.PullReqActivityStore,
|
||||
tx dbtx.Transactor,
|
||||
) *PullReq {
|
||||
return NewPullReq(urlProvider, git, principalStore, repoStore, pullReqStore, pullReqActStore, tx)
|
||||
}
|
||||
|
||||
func ProvideRuleImporter(
|
||||
ruleStore store.RuleStore,
|
||||
tx dbtx.Transactor,
|
||||
principalStore store.PrincipalStore,
|
||||
) *Rule {
|
||||
return NewRule(ruleStore, tx, principalStore)
|
||||
}
|
||||
|
||||
func ProvideWebhookImporter(
|
||||
config webhook.Config,
|
||||
tx dbtx.Transactor,
|
||||
webhookStore store.WebhookStore,
|
||||
) *Webhook {
|
||||
return NewWebhook(config, tx, webhookStore)
|
||||
}
|
@ -74,6 +74,7 @@ import (
|
||||
svclabel "github.com/harness/gitness/app/services/label"
|
||||
locker "github.com/harness/gitness/app/services/locker"
|
||||
"github.com/harness/gitness/app/services/metric"
|
||||
migrateservice "github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/app/services/notification"
|
||||
"github.com/harness/gitness/app/services/notification/mailer"
|
||||
"github.com/harness/gitness/app/services/protection"
|
||||
@ -203,6 +204,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
|
||||
plugin.WireSet,
|
||||
resolver.WireSet,
|
||||
importer.WireSet,
|
||||
migrateservice.WireSet,
|
||||
canceler.WireSet,
|
||||
exporter.WireSet,
|
||||
metric.WireSet,
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
keywordsearch2 "github.com/harness/gitness/app/api/controller/keywordsearch"
|
||||
"github.com/harness/gitness/app/api/controller/limiter"
|
||||
logs2 "github.com/harness/gitness/app/api/controller/logs"
|
||||
"github.com/harness/gitness/app/api/controller/migrate"
|
||||
migrate2 "github.com/harness/gitness/app/api/controller/migrate"
|
||||
"github.com/harness/gitness/app/api/controller/pipeline"
|
||||
"github.com/harness/gitness/app/api/controller/plugin"
|
||||
"github.com/harness/gitness/app/api/controller/principal"
|
||||
@ -75,6 +75,7 @@ import (
|
||||
"github.com/harness/gitness/app/services/label"
|
||||
"github.com/harness/gitness/app/services/locker"
|
||||
"github.com/harness/gitness/app/services/metric"
|
||||
"github.com/harness/gitness/app/services/migrate"
|
||||
"github.com/harness/gitness/app/services/notification"
|
||||
"github.com/harness/gitness/app/services/notification/mailer"
|
||||
"github.com/harness/gitness/app/services/protection"
|
||||
@ -302,7 +303,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pullReq := importer.ProvidePullReqImporter(provider, gitInterface, principalStore, repoStore, pullReqStore, pullReqActivityStore, transactor)
|
||||
pullReq := migrate.ProvidePullReqImporter(provider, gitInterface, principalStore, repoStore, pullReqStore, pullReqActivityStore, transactor)
|
||||
pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, principalInfoCache, pullReqFileViewStore, membershipStore, checkStore, gitInterface, reporter2, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker, pullReq, labelService)
|
||||
webhookConfig := server.ProvideWebhookConfig(config)
|
||||
webhookStore := database.ProvideWebhookStore(db)
|
||||
@ -366,7 +367,9 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
||||
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter4, orchestratorConfig, vsCode, vsCodeWeb)
|
||||
gitspaceEventStore := database.ProvideGitspaceEventStore(db)
|
||||
gitspaceController := gitspace2.ProvideController(transactor, authorizer, infraproviderService, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter4, orchestratorOrchestrator, gitspaceEventStore, statefulLogger, scmSCM, repoStore, gitspaceService)
|
||||
migrateController := migrate.ProvideController(authorizer, principalStore)
|
||||
rule := migrate.ProvideRuleImporter(ruleStore, transactor, principalStore)
|
||||
migrateWebhook := migrate.ProvideWebhookImporter(webhookConfig, transactor, webhookStore)
|
||||
migrateController := migrate2.ProvideController(authorizer, publicaccessService, gitInterface, provider, pullReq, rule, migrateWebhook, resourceLimiter, auditService, repoIdentifier, transactor, spaceStore, repoStore)
|
||||
openapiService := openapi.ProvideOpenAPIService()
|
||||
routerRouter := router.ProvideRouter(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, checkController, systemController, uploadController, keywordsearchController, infraproviderController, gitspaceController, migrateController, provider, openapiService)
|
||||
serverServer := server2.ProvideServer(config, routerRouter)
|
||||
|
25
go.mod
25
go.mod
@ -18,7 +18,7 @@ require (
|
||||
github.com/drone/funcmap v0.0.0-20240227160611-7e19e9cd5a1c
|
||||
github.com/drone/go-convert v0.0.0-20240307072510-6bd371c65e61
|
||||
github.com/drone/go-generate v1.1.0
|
||||
github.com/drone/go-scm v1.38.2
|
||||
github.com/drone/go-scm v1.38.4
|
||||
github.com/drone/runner-go v1.12.0
|
||||
github.com/drone/spec v0.0.0-20230920145636-3827abdce961
|
||||
github.com/fatih/color v1.17.0
|
||||
@ -36,7 +36,7 @@ require (
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75
|
||||
github.com/gotidy/ptr v1.4.0
|
||||
github.com/guregu/null v4.0.0+incompatible
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240703163651-0641dc7290d8
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240804180936-b1de602aa8e7
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
@ -80,6 +80,10 @@ require (
|
||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/BobuSumisu/aho-corasick v1.0.3 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0 // indirect
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||
github.com/antonmedv/expr v1.15.5 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
@ -90,15 +94,21 @@ require (
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.12.1 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.1.4 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/drone/envsubst v1.0.3 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/fatih/semgroup v1.2.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/gitleaks/go-gitdiff v0.9.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.4.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.5.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
@ -107,11 +117,15 @@ require (
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
github.com/h2non/filetype v1.1.3 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/jackc/pgx/v4 v4.12.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
@ -121,6 +135,7 @@ require (
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pjbgf/sha1cd v0.2.3 // indirect
|
||||
github.com/prometheus/client_golang v1.19.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
@ -129,12 +144,17 @@ require (
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/schollz/progressbar/v3 v3.13.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/skeema/knownhosts v1.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.19.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect
|
||||
@ -150,6 +170,7 @@ require (
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
|
93
go.sum
93
go.sum
@ -34,14 +34,23 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
|
||||
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
|
||||
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
|
||||
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@ -60,6 +69,7 @@ github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
@ -86,6 +96,7 @@ github.com/bradrydzewski/spec v1.0.2 h1:spQ8nLjsV4IFieEqHAnob5S4Vfx+0EQG/L91mVVr
|
||||
github.com/bradrydzewski/spec v1.0.2/go.mod h1:ZrrxQBqUvBoqAaH9ClsskjE3LPMHra+NbKdqDIQqRNQ=
|
||||
github.com/buildkite/yaml v2.1.0+incompatible h1:xirI+ql5GzfikVNDmt+yeiXpf/v1Gt03qXTtT5WXdr8=
|
||||
github.com/buildkite/yaml v2.1.0+incompatible/go.mod h1:UoU8vbcwu1+vjZq01+KrpSeLBgQQIjL/H7Y6KwikUrI=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
|
||||
@ -100,6 +111,9 @@ github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831
|
||||
github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
@ -117,6 +131,7 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
@ -133,6 +148,8 @@ github.com/djherbis/buffer v1.2.0 h1:PH5Dd2ss0C7CRRhQCZ2u7MssF+No9ide8Ye71nPHcrQ
|
||||
github.com/djherbis/buffer v1.2.0/go.mod h1:fjnebbZjCUpPinBRD+TDwXSOeNQ7fPQWLfGQqiAiUyE=
|
||||
github.com/djherbis/nio/v3 v3.0.1 h1:6wxhnuppteMa6RHA4L81Dq7ThkZH8SwnDzXDYy95vB4=
|
||||
github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmWgZxOcmg=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
@ -163,6 +180,8 @@ github.com/drone/go-generate v1.1.0 h1:JoWB4emGS/hlIaKNlcI1Amjvm5ajub1lqocLHMSwu
|
||||
github.com/drone/go-generate v1.1.0/go.mod h1:rnOS/ww//Mz5XM88u6+xT3Bd2ftJdYAYi1k2vtGUkUQ=
|
||||
github.com/drone/go-scm v1.38.2 h1:u8fEuz2vbcn5y93YPiT0nkcmQKKAxNuL08N0xuHCLTY=
|
||||
github.com/drone/go-scm v1.38.2/go.mod h1:DFIJJjhMj0TSXPz+0ni4nyZ9gtTtC40Vh/TGRugtyWw=
|
||||
github.com/drone/go-scm v1.38.4 h1:KW+znh2tg3tJwbiFfzhjZQ2gbyasJ213V7hZ00QaVpc=
|
||||
github.com/drone/go-scm v1.38.4/go.mod h1:DFIJJjhMj0TSXPz+0ni4nyZ9gtTtC40Vh/TGRugtyWw=
|
||||
github.com/drone/runner-go v1.12.0 h1:zUjDj9ylsJ4n4Mvy4znddq/Z4EBzcUXzTltpzokKtgs=
|
||||
github.com/drone/runner-go v1.12.0/go.mod h1:vu4pPPYDoeN6vdYQAY01GGGsAIW4aLganJNaa8Fx8zE=
|
||||
github.com/drone/signal v1.0.0/go.mod h1:S8t92eFT0g4WUgEc/LxG+LCuiskpMNsG0ajAMGnyZpc=
|
||||
@ -173,6 +192,8 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@ -198,12 +219,21 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gitleaks/go-gitdiff v0.9.0 h1:SHAU2l0ZBEo8g82EeFewhVy81sb7JCxW76oSPtR/Nqg=
|
||||
github.com/gitleaks/go-gitdiff v0.9.0/go.mod h1:pKz0X4YzCKZs30BL+weqBIG7mx0jl4tF1uXV9ZyNvrA=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
|
||||
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.4.0 h1:Vaw7LaSTRJOUric7pe4vnzBSgyuf2KrLsu2Y4ZpQBDE=
|
||||
github.com/go-git/go-billy/v5 v5.4.0/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||
github.com/go-git/go-git/v5 v5.5.2 h1:v8lgZa5k9ylUw+OR/roJHTxR4QItsNFI5nKtAXFuynw=
|
||||
github.com/go-git/go-git/v5 v5.5.2/go.mod h1:BE5hUJ5yaV2YMxhmaP4l6RBQ08kMxKSPD4BlxtH7OjI=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
@ -328,6 +358,10 @@ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslC
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240703163651-0641dc7290d8 h1:X0/Nk9aCkIKoF3kavxZcr9EtfARSBqnJK33c59m+xmw=
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240703163651-0641dc7290d8/go.mod h1:HiUX39ZfhBGY+OkEEN6JpglbodNJlbzayOt/l3nkk6w=
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240801225636-542cd216f84e h1:Do+0drtv74/mOkXo07mj9JMIn6jy6dDlK6FrRW7pgpI=
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240801225636-542cd216f84e/go.mod h1:DSqjRv/0GKxBTkqgayOOX/rIktw9KTIBMxJUvHdZK4Q=
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240804180936-b1de602aa8e7 h1:hvQPC9k0V4tSYccVLqYFbT7HPH9kzwRqcInfbK6z7ag=
|
||||
github.com/harness/harness-migrate v0.21.1-0.20240804180936-b1de602aa8e7/go.mod h1:hlyMG5yMpTUesICvSYz61mInT+dMGN7HdTujv+RHcgU=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -359,6 +393,8 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK
|
||||
github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc=
|
||||
github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
@ -419,6 +455,9 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
|
||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
@ -435,8 +474,11 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
@ -444,6 +486,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@ -475,6 +518,7 @@ github.com/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3eu
|
||||
github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U=
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0 h1:P64+dmq21hhWdtvZfEAofnvJULaRR1Yib0+PnU669bE=
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0/go.mod h1:KlbGNQ+FhrUNIHUxZdL63t7tl4LaPkZNpUULS8H4uVM=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
@ -491,10 +535,12 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
@ -503,6 +549,8 @@ github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxU
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
@ -536,6 +584,7 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
@ -573,6 +622,8 @@ github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzk
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI=
|
||||
github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@ -612,6 +663,7 @@ github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0
|
||||
github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo=
|
||||
github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
@ -633,10 +685,13 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/schollz/progressbar/v3 v3.13.0 h1:9TeeWRcjW2qd05I8Kf9knPkW4vLM/hYoa6z9ABvxje8=
|
||||
github.com/schollz/progressbar/v3 v3.13.0/go.mod h1:ZBYnSuLAX2LU8P8UiKN/KgF2DY58AJC8yfVYLPC8Ly4=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY=
|
||||
github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
@ -646,8 +701,11 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
|
||||
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
@ -695,8 +753,6 @@ github.com/swaggest/jsonschema-go v0.3.72 h1:IHaGlR1bdBUBPfhe4tfacN2TGAPKENEGiNy
|
||||
github.com/swaggest/jsonschema-go v0.3.72/go.mod h1:OrGyEoVqpfSFJ4Am4V/FQcQ3mlEC1vVeleA+5ggbVW4=
|
||||
github.com/swaggest/openapi-go v0.2.23 h1:DYUezSTyw180z1bL51wUnalYYbTMwHBjp1Itvji8/rs=
|
||||
github.com/swaggest/openapi-go v0.2.23/go.mod h1:T1Koc6EAFAvnCI1MUqOOPDniqGzZy6dOiHtA/j54k14=
|
||||
github.com/swaggest/openapi-go v0.2.53 h1:lWHKgC9IN48nBYxvuBrmAVJgki/1xsrGZWaWJnOLenE=
|
||||
github.com/swaggest/openapi-go v0.2.53/go.mod h1:2Q7NpuG9NgpGeTaNOo852GSR6cCzSP4IznA9DNdUTQw=
|
||||
github.com/swaggest/refl v1.3.0 h1:PEUWIku+ZznYfsoyheF97ypSduvMApYyGkYF3nabS0I=
|
||||
github.com/swaggest/refl v1.3.0/go.mod h1:3Ujvbmh1pfSbDYjC6JGG7nMgPvpG0ehQL4iNonnLNbg=
|
||||
github.com/swaggest/swgui v1.8.1 h1:OLcigpoelY0spbpvp6WvBt0I1z+E9egMQlUeEKya+zU=
|
||||
@ -709,6 +765,11 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
|
||||
github.com/vearutop/statigz v1.4.0 h1:RQL0KG3j/uyA/PFpHeZ/L6l2ta920/MxlOAIGEOuwmU=
|
||||
github.com/vearutop/statigz v1.4.0/go.mod h1:LYTolBLiz9oJISwiVKnOQoIwhO1LWX1A7OECawGS8XE=
|
||||
github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d/go.mod h1:mb5taDqMnJiZNRQ3+02W2IFG+oEz1+dTuCXkp4jpkfo=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xhit/go-str2duration v1.2.0 h1:BcV5u025cITWxEQKGWr1URRzrcXtu7uk8+luz3Yuhwc=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
@ -749,8 +810,6 @@ go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lI
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 h1:hzy3LFnSN8kuQK8h9tHl4ndF6UruMj47OqwqsS+/Ai4=
|
||||
go.starlark.net v0.0.0-20231121155337-90ade8b19d09/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
|
||||
go.starlark.net v0.0.0-20240705175910-70002002b310 h1:tEAOMoNmN2MqVNi0MMEWpTtPI4YNCXgxmAGtuv3mST0=
|
||||
go.starlark.net v0.0.0-20240705175910-70002002b310/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
@ -782,6 +841,10 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
@ -825,7 +888,10 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
@ -872,14 +938,24 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -890,6 +966,9 @@ golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
@ -902,6 +981,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
@ -993,6 +1073,8 @@ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gG
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
@ -1008,14 +1090,17 @@ gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
|
Loading…
x
Reference in New Issue
Block a user