Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api, repositories, hooks): compute semver for workflow run git context #6769

Merged
merged 10 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
Expand Down
55 changes: 28 additions & 27 deletions engine/api/operation/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,31 +194,32 @@ func Poll(ctx context.Context, db gorp.SqlExecutor, operationUUID string) (*sdk.
}

func CheckoutAndAnalyzeOperation(ctx context.Context, db gorp.SqlExecutor, proj sdk.Project, vcsWithSecret sdk.VCSProject, repoName, repoCloneURL string, commit, branch string) (*sdk.Operation, error) {
ope := &sdk.Operation{
VCSServer: vcsWithSecret.Name,
RepoFullName: repoName,
URL: repoCloneURL,
RepositoryStrategy: sdk.RepositoryStrategy{
SSHKey: vcsWithSecret.Auth.SSHKeyName,
User: vcsWithSecret.Auth.Username,
Password: vcsWithSecret.Auth.Token,
},
Setup: sdk.OperationSetup{
Checkout: sdk.OperationCheckout{
Commit: commit,
Branch: branch,
CheckSignature: true,
},
},
}
if vcsWithSecret.Auth.SSHKeyName != "" {
ope.RepositoryStrategy.ConnectionType = "ssh"
} else {
ope.RepositoryStrategy.ConnectionType = "https"
}

if err := PostRepositoryOperation(ctx, db, proj, ope, nil); err != nil {
return nil, err
}
return ope, nil
ope := &sdk.Operation{
VCSServer: vcsWithSecret.Name,
RepoFullName: repoName,
URL: repoCloneURL,
RepositoryStrategy: sdk.RepositoryStrategy{
SSHKey: vcsWithSecret.Auth.SSHKeyName,
User: vcsWithSecret.Auth.Username,
Password: vcsWithSecret.Auth.Token,
},
Setup: sdk.OperationSetup{
Checkout: sdk.OperationCheckout{
Commit: commit,
Branch: branch,
CheckSignature: true,
ProcessSemver: true,
},
},
}
if vcsWithSecret.Auth.SSHKeyName != "" {
ope.RepositoryStrategy.ConnectionType = "ssh"
} else {
ope.RepositoryStrategy.ConnectionType = "https"
}

if err := PostRepositoryOperation(ctx, db, proj, ope, nil); err != nil {
return nil, err
}
return ope, nil
}
16 changes: 11 additions & 5 deletions engine/api/v2_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,20 @@ func (api *API) postHookEventRetrieveSignKeyHandler() ([]service.RbacChecker, se
HookEventUUID: hookRetrieveSignKey.HookEventUUID,
SigningKeyCallback: &sdk.HookSigninKeyCallback{},
}
if ope.Status == sdk.OperationStatusDone && ope.Setup.Checkout.Result.CommitVerified {
callback.SigningKeyCallback.SignKey = ope.Setup.Checkout.Result.SignKeyID
} else if ope.Status == sdk.OperationStatusDone && !ope.Setup.Checkout.Result.CommitVerified {
callback.SigningKeyCallback.SignKey = ope.Setup.Checkout.Result.SignKeyID
callback.SigningKeyCallback.Error = ope.Setup.Checkout.Result.Msg
if ope.Status == sdk.OperationStatusDone {
callback.SigningKeyCallback.SemverCurrent = ope.Setup.Checkout.Result.Semver.Current
callback.SigningKeyCallback.SemverNext = ope.Setup.Checkout.Result.Semver.Next

if ope.Setup.Checkout.Result.CommitVerified {
callback.SigningKeyCallback.SignKey = ope.Setup.Checkout.Result.SignKeyID
} else {
callback.SigningKeyCallback.SignKey = ope.Setup.Checkout.Result.SignKeyID
callback.SigningKeyCallback.Error = ope.Setup.Checkout.Result.Msg
}
} else {
callback.SigningKeyCallback.Error = ope.Error.Message
}

if _, code, err := services.NewClient(api.mustDB(), srvs).DoJSONRequest(ctx, http.MethodPost, "/v2/repository/event/callback", callback, nil); err != nil {
log.ErrorWithStackTrace(ctx, sdk.WrapError(err, "unable to send analysis call to hook [HTTP: %d]", code))
return
Expand Down
2 changes: 0 additions & 2 deletions engine/api/v2_repository_analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,8 +643,6 @@ func sendAnalysisHookCallback(ctx context.Context, db *gorp.DbMap, analysis sdk.
AnalysisID: analysis.ID,
Models: make([]sdk.EntityFullName, 0),
Workflows: make([]sdk.EntityFullName, 0),
UserID: analysis.Data.CDSUserID,
Username: analysis.Data.CDSUserName,
},
}
for _, e := range entities {
Expand Down
12 changes: 7 additions & 5 deletions engine/api/v2_workflow_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -731,10 +731,12 @@ func (api *API) postWorkflowRunFromHookV2Handler() ([]service.RbacChecker, servi
}
case sdk.WorkflowHookTypeRepository:
runEvent.GitTrigger = &sdk.GitTrigger{
Payload: runRequest.Payload,
EventName: runRequest.EventName,
Ref: runRequest.Ref,
Sha: runRequest.Sha,
Payload: runRequest.Payload,
EventName: runRequest.EventName,
Ref: runRequest.Ref,
Sha: runRequest.Sha,
SemverCurrent: runRequest.SemverCurrent,
SemverNext: runRequest.SemverNext,
}
default:
return sdk.WrapError(sdk.ErrWrongRequest, "unknown event: %v", runRequest)
Expand Down Expand Up @@ -1144,7 +1146,7 @@ func (api *API) postWorkflowRunV2Handler() ([]service.RbacChecker, service.Handl
return err
}

runEvent := sdk.V2WorkflowRunEvent{
runEvent := sdk.V2WorkflowRunEvent{ // TODO handler semver ?
Manual: &sdk.ManualTrigger{
Payload: runRequest,
},
Expand Down
49 changes: 43 additions & 6 deletions engine/api/v2_workflow_run_craft.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"time"

"github.com/Masterminds/semver/v3"
"github.com/go-gorp/gorp"
"github.com/rockbears/log"
"github.com/rockbears/yaml"
Expand Down Expand Up @@ -548,7 +549,7 @@ func stopRun(ctx context.Context, db *gorp.DbMap, run *sdk.V2WorkflowRun, messag
func buildRunContext(ctx context.Context, db *gorp.DbMap, store cache.Store, p sdk.Project, wr sdk.V2WorkflowRun, vcsServer sdk.VCSProject, repo sdk.ProjectRepository, u sdk.AuthentifiedUser) (*sdk.WorkflowRunContext, error) {
var runContext sdk.WorkflowRunContext

var ref, commit string
var ref, commit, semverNext, semverCurrent string

cdsContext := sdk.CDSContext{
ProjectKey: wr.ProjectKey,
Expand Down Expand Up @@ -583,6 +584,39 @@ func buildRunContext(ctx context.Context, db *gorp.DbMap, store cache.Store, p s
cdsContext.Event = wr.RunEvent.GitTrigger.Payload
ref = wr.RunEvent.GitTrigger.Ref
commit = wr.RunEvent.GitTrigger.Sha

semverNext = wr.RunEvent.GitTrigger.SemverNext

// Compute current semver version with CDS metadata
currentVersion, _ := semver.NewVersion(wr.RunEvent.GitTrigger.SemverCurrent)
if currentVersion != nil {
if currentVersion.Metadata() == "" { // Tags doesn't have metadata
semverCurrent = wr.RunEvent.GitTrigger.SemverCurrent
} else {
suffix := currentVersion.Metadata()
splittedSuffix := strings.Split(suffix, ".")
var metadataStr string
if len(splittedSuffix) >= 2 {
metadataStr += splittedSuffix[0] + ".sha." + splittedSuffix[1]
}
for i := 2; i < len(splittedSuffix); i++ {
metadataStr += "." + splittedSuffix[i]
}
preRelease := currentVersion.Prerelease()
var v = *currentVersion
if preRelease != "" {
v, _ = currentVersion.SetPrerelease(preRelease + "-" + strconv.FormatInt(wr.RunNumber, 10))
} else {
v, _ = currentVersion.SetPrerelease(strconv.FormatInt(wr.RunNumber, 10))
}
v, _ = v.SetMetadata(metadataStr)
semverCurrent = v.String()
}
} else {
// If no semver found, compute it from 0.1.0
semverCurrent = "0.1.0+" + strconv.FormatInt(wr.RunNumber, 10) + ".sha." + commit
}

case wr.RunEvent.ModelUpdateTrigger != nil:
ref = wr.RunEvent.ModelUpdateTrigger.Ref
case wr.RunEvent.WorkflowUpdateTrigger != nil:
Expand All @@ -604,12 +638,15 @@ func buildRunContext(ctx context.Context, db *gorp.DbMap, store cache.Store, p s
workflowVCSServer := *vcsTmp

gitContext := sdk.GitContext{
Server: workflowVCSServer.Name,
SSHKey: workflowVCSServer.Auth.SSHKeyName,
Username: workflowVCSServer.Auth.Username,
Ref: ref,
Sha: commit,
Server: workflowVCSServer.Name,
SSHKey: workflowVCSServer.Auth.SSHKeyName,
Username: workflowVCSServer.Auth.Username,
Ref: ref,
Sha: commit,
SemverCurrent: semverCurrent,
SemverNext: semverNext,
}

if gitContext.SSHKey != "" {
gitContext.Connection = "ssh"
} else {
Expand Down
76 changes: 40 additions & 36 deletions engine/hooks/scheduler_repository_event_callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,48 +81,52 @@ func (s *Service) updateHookEventWithCallback(ctx context.Context, callback sdk.
return nil
}

if hre.Status != sdk.HookEventStatusAnalysis && hre.Status != sdk.HookEventStatusSignKey {
return nil
}

if callback.AnalysisCallback != nil {
if callback.AnalysisCallback.UserID != "" {
hre.UserID = callback.AnalysisCallback.UserID
hre.Username = callback.AnalysisCallback.Username
}
for i := range hre.Analyses {
a := &hre.Analyses[i]
if a.AnalyzeID == callback.AnalysisCallback.AnalysisID {
if a.Status == sdk.RepositoryAnalysisStatusInProgress {
a.Status = callback.AnalysisCallback.AnalysisStatus
hre.ModelUpdated = append(hre.ModelUpdated, callback.AnalysisCallback.Models...)
hre.WorkflowUpdated = append(hre.WorkflowUpdated, callback.AnalysisCallback.Workflows...)
if err := s.Dao.SaveRepositoryEvent(ctx, &hre); err != nil {
return err
switch hre.Status {
case sdk.HookEventStatusAnalysis:
if callback.AnalysisCallback != nil {
for i := range hre.Analyses {
a := &hre.Analyses[i]
if a.AnalyzeID == callback.AnalysisCallback.AnalysisID {
if a.Status == sdk.RepositoryAnalysisStatusInProgress {
a.Status = callback.AnalysisCallback.AnalysisStatus
hre.ModelUpdated = append(hre.ModelUpdated, callback.AnalysisCallback.Models...)
hre.WorkflowUpdated = append(hre.WorkflowUpdated, callback.AnalysisCallback.Workflows...)
if err := s.Dao.SaveRepositoryEvent(ctx, &hre); err != nil {
return err
}
break
}
break
}
}
} else {
return sdk.Errorf("missing analysis callback data")
}
}

// Manage signinKey
if callback.SigningKeyCallback != nil {
if callback.SigningKeyCallback.SignKey != "" && callback.SigningKeyCallback.Error != "" {
// event on error commit unverified
hre.Status = sdk.HookEventStatusSkipped
hre.LastError = callback.SigningKeyCallback.Error
hre.NbErrors++
} else if callback.SigningKeyCallback.SignKey != "" && callback.SigningKeyCallback.Error == "" {
// commit verified
hre.SignKey = callback.SigningKeyCallback.SignKey
} else if callback.SigningKeyCallback.Error != "" {
hre.LastError = "Unable to get signing key: " + callback.SigningKeyCallback.Error
hre.NbErrors++
}
if err := s.Dao.SaveRepositoryEvent(ctx, &hre); err != nil {
return err
case sdk.HookEventStatusSignKey:
if callback.SigningKeyCallback != nil {
hre.SemverCurrent = callback.SigningKeyCallback.SemverCurrent
hre.SemverNext = callback.SigningKeyCallback.SemverNext
if callback.SigningKeyCallback.SignKey != "" && callback.SigningKeyCallback.Error != "" {
// event on error commit unverified
hre.Status = sdk.HookEventStatusSkipped
hre.LastError = callback.SigningKeyCallback.Error
hre.NbErrors++
} else if callback.SigningKeyCallback.SignKey != "" && callback.SigningKeyCallback.Error == "" {
// commit verified
hre.SignKey = callback.SigningKeyCallback.SignKey
} else if callback.SigningKeyCallback.Error != "" {
hre.LastError = "Unable to get signing key: " + callback.SigningKeyCallback.Error
hre.NbErrors++
}
} else {
return sdk.Errorf("missing analysis callback data")
}
default:
return nil
}

if err := s.Dao.SaveRepositoryEvent(ctx, &hre); err != nil {
return err
}

if err := s.Dao.EnqueueRepositoryEvent(ctx, &hre); err != nil {
Expand Down
5 changes: 4 additions & 1 deletion engine/hooks/trigger_signingkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package hooks
import (
"context"
"fmt"
"github.com/rockbears/log"
"time"

"github.com/rockbears/log"

"github.com/ovh/cds/sdk"
"github.com/ovh/cds/sdk/telemetry"
)
Expand Down Expand Up @@ -60,6 +61,8 @@ func (s *Service) triggerGetSigningKey(ctx context.Context, hre *sdk.HookReposit
}
if ope.Status == sdk.OperationStatusDone {
hre.SignKey = ope.Setup.Checkout.Result.SignKeyID
hre.SemverCurrent = ope.Setup.Checkout.Result.Semver.Current
hre.SemverNext = ope.Setup.Checkout.Result.Semver.Next
if !ope.Setup.Checkout.Result.CommitVerified {
hre.Status = sdk.HookEventStatusSkipped
hre.LastError = fmt.Sprintf("User with key '%s' not found in CDS", hre.SignKey)
Expand Down
20 changes: 10 additions & 10 deletions engine/hooks/trigger_workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,21 @@ func (s *Service) triggerWorkflows(ctx context.Context, hre *sdk.HookRepositoryE
wh := &hre.WorkflowHooks[i]
if wh.Status == sdk.HookEventWorkflowStatusScheduler {

targetCommit := "HEAD"

runRequest := sdk.V2WorkflowRunHookRequest{
HookEventID: hre.UUID,
UserID: hre.UserID,
Ref: wh.TargetBranch,
Sha: targetCommit,
Payload: event,
EventName: hre.EventName,
HookType: wh.Type,
HookEventID: hre.UUID,
UserID: hre.UserID,
Ref: wh.TargetBranch,
Sha: "HEAD",
Payload: event,
EventName: hre.EventName,
HookType: wh.Type,
SemverCurrent: hre.SemverCurrent,
SemverNext: hre.SemverNext,
}

switch wh.Type {
case sdk.WorkflowHookTypeRepository:
targetCommit = hre.ExtractData.Commit
runRequest.Sha = hre.ExtractData.Commit
if runRequest.Ref == "" {
runRequest.Ref = hre.ExtractData.Branch
}
Expand Down
Loading