Skip to content

Commit a77c573

Browse files
authored
Merge pull request diggerhq#1008 from diggerhq/feat/lowlevel-run
support lowlevel run command with digger
2 parents 9fa870d + 12ce264 commit a77c573

File tree

17 files changed

+610
-146
lines changed

17 files changed

+610
-146
lines changed

cli/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
**/digger
22
!/pkg/digger
3+
!/cmd/digger

cli/cmd/digger/apply.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package main
2+
3+
import (
4+
core_backend "github.com/diggerhq/digger/cli/pkg/core/backend"
5+
core_locking "github.com/diggerhq/digger/cli/pkg/core/locking"
6+
core_policy "github.com/diggerhq/digger/cli/pkg/core/policy"
7+
core_reporting "github.com/diggerhq/digger/cli/pkg/core/reporting"
8+
"github.com/diggerhq/digger/libs/orchestrator"
9+
"github.com/spf13/cobra"
10+
"github.com/spf13/pflag"
11+
"github.com/spf13/viper"
12+
"strings"
13+
)
14+
15+
var vipApply *viper.Viper
16+
17+
func apply(actor string, projectName string, repoNamespace string, prNumber int, lock core_locking.Lock, policyChecker core_policy.Checker, reporter core_reporting.Reporter, prService orchestrator.PullRequestService, orgService orchestrator.OrgService, backendApi core_backend.Api) {
18+
exec(actor, projectName, repoNamespace, "digger apply", prNumber, lock, policyChecker, prService, orgService, reporter, backendApi)
19+
}
20+
21+
var applyCmd = &cobra.Command{
22+
Use: "apply project_name [flags]",
23+
Short: "Apply a project, if no project specified it will plan for all projects",
24+
Long: `Apply a project, if no project specified it will plan for all projects`,
25+
Run: func(cmd *cobra.Command, args []string) {
26+
var runConfig RunConfig
27+
vipApply.Unmarshal(&runConfig)
28+
29+
prService, orgService, reporter, err := runConfig.GetServices()
30+
if err != nil {
31+
reportErrorAndExit(runConfig.Actor, "Unrecognised reporter: "+runConfig.Reporter, 1)
32+
}
33+
34+
apply(runConfig.Actor, args[0], runConfig.RepoNamespace, runConfig.PRNumber, lock, PolicyChecker, *reporter, *prService, *orgService, BackendApi)
35+
},
36+
}
37+
38+
func init() {
39+
flags := []pflag.Flag{
40+
{Name: "github-token", Usage: "Github token (for github reporter)"},
41+
{Name: "repo-namespace", Usage: "The namespace of this repo"},
42+
{Name: "actor", Usage: "The actor of this command"},
43+
{Name: "reporter", Usage: "The reporter to use (defaults to stdout)"},
44+
{Name: "pr-number", Usage: "The PR number for reporting"},
45+
{Name: "comment-id", Usage: "The PR comment for reporting"},
46+
}
47+
48+
vipApply = viper.New()
49+
vipApply.SetEnvPrefix("DIGGER")
50+
vipApply.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
51+
vipApply.AutomaticEnv()
52+
53+
for _, flag := range flags {
54+
applyCmd.Flags().String(flag.Name, "", flag.Usage)
55+
vipApply.BindPFlag(flag.Name, applyCmd.Flags().Lookup(flag.Name))
56+
}
57+
58+
rootCmd.AddCommand(applyCmd)
59+
}

cli/cmd/digger/default.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/diggerhq/digger/cli/pkg/azure"
6+
"github.com/diggerhq/digger/cli/pkg/digger"
7+
"github.com/diggerhq/digger/cli/pkg/usage"
8+
"github.com/spf13/cobra"
9+
"log"
10+
"os"
11+
"runtime/debug"
12+
)
13+
14+
var defaultCmd = &cobra.Command{
15+
Use: "default",
16+
Run: func(cmd *cobra.Command, args []string) {
17+
var logLeader = "Unknown CI"
18+
ci := digger.DetectCI()
19+
20+
switch ci {
21+
case digger.GitHub:
22+
logLeader = os.Getenv("GITHUB_ACTOR")
23+
gitHubCI(lock, PolicyChecker, BackendApi, ReportStrategy)
24+
case digger.GitLab:
25+
logLeader = os.Getenv("CI_PROJECT_NAME")
26+
gitLabCI(lock, PolicyChecker, BackendApi, ReportStrategy)
27+
case digger.Azure:
28+
// This should be refactored in the future because in this way the parsing
29+
// is done twice, both here and inside azureCI, a better solution might be
30+
// to encapsulate it into a method on the azure package and then grab the
31+
// value here and pass it into the azureCI call.
32+
azureContext := os.Getenv("AZURE_CONTEXT")
33+
parsedAzureContext, _ := azure.GetAzureReposContext(azureContext)
34+
logLeader = parsedAzureContext.BaseUrl
35+
azureCI(lock, PolicyChecker, BackendApi, ReportStrategy)
36+
case digger.BitBucket:
37+
logLeader = os.Getenv("BITBUCKET_STEP_TRIGGERER_UUID")
38+
bitbucketCI(lock, PolicyChecker, BackendApi, ReportStrategy)
39+
case digger.None:
40+
print("No CI detected.")
41+
os.Exit(10)
42+
}
43+
44+
defer func() {
45+
if r := recover(); r != nil {
46+
log.Println(fmt.Sprintf("stacktrace from panic: \n" + string(debug.Stack())))
47+
err := usage.SendLogRecord(logLeader, fmt.Sprintf("Panic occurred. %s", r))
48+
if err != nil {
49+
log.Printf("Failed to send log record. %s\n", err)
50+
}
51+
os.Exit(1)
52+
}
53+
}()
54+
},
55+
}
56+
57+
func init() {
58+
rootCmd.AddCommand(defaultCmd)
59+
}

cli/cmd/digger/destroy.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package main
2+
3+
import (
4+
core_backend "github.com/diggerhq/digger/cli/pkg/core/backend"
5+
core_locking "github.com/diggerhq/digger/cli/pkg/core/locking"
6+
core_policy "github.com/diggerhq/digger/cli/pkg/core/policy"
7+
core_reporting "github.com/diggerhq/digger/cli/pkg/core/reporting"
8+
"github.com/diggerhq/digger/libs/orchestrator"
9+
"github.com/spf13/cobra"
10+
"github.com/spf13/pflag"
11+
"github.com/spf13/viper"
12+
"strings"
13+
)
14+
15+
var vipDestroy *viper.Viper
16+
17+
func destroy(actor string, projectName string, repoNamespace string, prNumber int, lock core_locking.Lock, policyChecker core_policy.Checker, reporter core_reporting.Reporter, prService orchestrator.PullRequestService, orgService orchestrator.OrgService, backendApi core_backend.Api) {
18+
exec(actor, projectName, repoNamespace, "digger destroy", prNumber, lock, policyChecker, prService, orgService, reporter, backendApi)
19+
}
20+
21+
var destroyCmd = &cobra.Command{
22+
Use: "destroy project_name [flags]",
23+
Short: "Destroy a project",
24+
Long: `Destroy a project`,
25+
Run: func(cmd *cobra.Command, args []string) {
26+
var runConfig RunConfig
27+
vipDestroy.Unmarshal(&runConfig)
28+
29+
prService, orgService, reporter, err := runConfig.GetServices()
30+
if err != nil {
31+
reportErrorAndExit(runConfig.Actor, "Unrecognised reporter: "+runConfig.Reporter, 1)
32+
}
33+
34+
destroy(runConfig.Actor, args[0], runConfig.RepoNamespace, runConfig.PRNumber, lock, PolicyChecker, *reporter, *prService, *orgService, BackendApi)
35+
},
36+
}
37+
38+
func init() {
39+
flags := []pflag.Flag{
40+
{Name: "github-token", Usage: "Github token (for github reporter)"},
41+
{Name: "repo-namespace", Usage: "The namespace of this repo"},
42+
{Name: "actor", Usage: "The actor of this command"},
43+
{Name: "reporter", Usage: "The reporter to use (defaults to stdout)"},
44+
{Name: "pr-number", Usage: "The PR number for reporting"},
45+
{Name: "comment-id", Usage: "The PR comment for reporting"},
46+
}
47+
48+
vipDestroy = viper.New()
49+
vipDestroy.SetEnvPrefix("DIGGER")
50+
vipDestroy.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
51+
vipDestroy.AutomaticEnv()
52+
53+
for _, flag := range flags {
54+
destroyCmd.Flags().String(flag.Name, "", flag.Usage)
55+
vipDestroy.BindPFlag(flag.Name, destroyCmd.Flags().Lookup(flag.Name))
56+
}
57+
58+
rootCmd.AddCommand(destroyCmd)
59+
}

cli/cmd/digger/main.go

Lines changed: 33 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
core_reporting "github.com/diggerhq/digger/cli/pkg/core/reporting"
78
"log"
89
"net/http"
910
"os"
10-
"runtime/debug"
1111
"strconv"
1212
"strings"
1313
"time"
1414

1515
"github.com/diggerhq/digger/cli/pkg/azure"
16-
"github.com/diggerhq/digger/cli/pkg/backend"
1716
"github.com/diggerhq/digger/cli/pkg/bitbucket"
1817
core_backend "github.com/diggerhq/digger/cli/pkg/core/backend"
1918
core_locking "github.com/diggerhq/digger/cli/pkg/core/locking"
@@ -23,8 +22,6 @@ import (
2322
"github.com/diggerhq/digger/cli/pkg/gcp"
2423
github_models "github.com/diggerhq/digger/cli/pkg/github/models"
2524
"github.com/diggerhq/digger/cli/pkg/gitlab"
26-
"github.com/diggerhq/digger/cli/pkg/locking"
27-
"github.com/diggerhq/digger/cli/pkg/policy"
2825
"github.com/diggerhq/digger/cli/pkg/reporting"
2926
"github.com/diggerhq/digger/cli/pkg/storage"
3027
"github.com/diggerhq/digger/cli/pkg/usage"
@@ -86,8 +83,7 @@ func gitHubCI(lock core_locking.Lock, policyChecker core_policy.Checker, backend
8683
reportErrorAndExit(githubActor, "GITHUB_REPOSITORY is not defined", 3)
8784
}
8885

89-
splitRepositoryName := strings.Split(ghRepository, "/")
90-
repoOwner, repositoryName := splitRepositoryName[0], splitRepositoryName[1]
86+
repoOwner, repositoryName := utils.ParseRepoNamespace(ghRepository)
9187
githubPrService := dg_github.NewGitHubService(ghToken, repositoryName, repoOwner)
9288

9389
currentDir, err := os.Getwd()
@@ -771,6 +767,33 @@ func bitbucketCI(lock core_locking.Lock, policyChecker core_policy.Checker, back
771767
reportErrorAndExit(actor, "Digger finished successfully", 0)
772768
}
773769

770+
func exec(actor string, projectName string, repoNamespace string, command string, prNumber int, lock core_locking.Lock, policyChecker core_policy.Checker, prService orchestrator.PullRequestService, orgService orchestrator.OrgService, reporter core_reporting.Reporter, backendApi core_backend.Api) {
771+
772+
//SCMOrganisation, SCMrepository := utils.ParseRepoNamespace(runConfig.RepoNamespace)
773+
currentDir, err := os.Getwd()
774+
if err != nil {
775+
776+
reportErrorAndExit(actor, fmt.Sprintf("Failed to get current dir. %s", err), 4)
777+
778+
}
779+
780+
planStorage := newPlanStorage("", "", "", actor, nil)
781+
782+
diggerConfig, _, dependencyGraph, err := digger_config.LoadDiggerConfig("./")
783+
if err != nil {
784+
reportErrorAndExit(actor, fmt.Sprintf("Failed to load digger config. %s", err), 4)
785+
}
786+
//impactedProjects := diggerConfig.GetModifiedProjects(strings.Split(runConfig.FilesChanged, ","))
787+
impactedProjects := diggerConfig.GetProjects(projectName)
788+
jobs, _, err := orchestrator.ConvertProjectsToJobs(actor, repoNamespace, command, prNumber, impactedProjects, nil, diggerConfig.Workflows)
789+
if err != nil {
790+
reportErrorAndExit(actor, fmt.Sprintf("Failed to convert impacted projects to commands. %s", err), 4)
791+
}
792+
793+
jobs = digger.SortedCommandsByDependency(jobs, &dependencyGraph)
794+
_, _, err = digger.RunJobs(jobs, prService, orgService, lock, reporter, planStorage, policyChecker, backendApi, "", false, 123, currentDir)
795+
}
796+
774797
/*
775798
Exit codes:
776799
0 - No errors
@@ -786,100 +809,13 @@ Exit codes:
786809
*/
787810

788811
func main() {
789-
args := os.Args[1:]
790-
if len(args) > 0 && args[0] == "version" {
791-
log.Println(utils.GetVersion())
792-
os.Exit(0)
812+
if len(os.Args) == 1 {
813+
os.Args = append([]string{os.Args[0]}, "default")
793814
}
794-
if len(args) > 0 && args[0] == "help" {
795-
utils.DisplayCommands()
796-
os.Exit(0)
797-
}
798-
var policyChecker core_policy.Checker
799-
var backendApi core_backend.Api
800-
if os.Getenv("NO_BACKEND") == "true" {
801-
log.Println("WARNING: running in 'backendless' mode. Features that require backend will not be available.")
802-
policyChecker = policy.NoOpPolicyChecker{}
803-
backendApi = backend.NoopApi{}
804-
} else if os.Getenv("DIGGER_TOKEN") != "" {
805-
if os.Getenv("DIGGER_ORGANISATION") == "" {
806-
log.Fatalf("Token specified but missing organisation: DIGGER_ORGANISATION. Please set this value in action digger_config.")
807-
}
808-
policyChecker = policy.DiggerPolicyChecker{
809-
PolicyProvider: &policy.DiggerHttpPolicyProvider{
810-
DiggerHost: os.Getenv("DIGGER_HOSTNAME"),
811-
DiggerOrganisation: os.Getenv("DIGGER_ORGANISATION"),
812-
AuthToken: os.Getenv("DIGGER_TOKEN"),
813-
HttpClient: http.DefaultClient,
814-
}}
815-
backendApi = backend.DiggerApi{
816-
DiggerHost: os.Getenv("DIGGER_HOSTNAME"),
817-
AuthToken: os.Getenv("DIGGER_TOKEN"),
818-
HttpClient: http.DefaultClient,
819-
}
820-
} else {
821-
reportErrorAndExit("", "DIGGER_TOKEN not specified. You can get one at https://cloud.digger.dev, or self-manage a backend of Digger Community Edition (change DIGGER_HOSTNAME). You can also pass 'no-backend: true' option; in this case some of the features may not be available.", 1)
815+
if err := rootCmd.Execute(); err != nil {
816+
reportErrorAndExit("", fmt.Sprintf("Error occured during command exec: %v", err), 8)
822817
}
823818

824-
var reportStrategy reporting.ReportStrategy
825-
826-
if os.Getenv("REPORTING_STRATEGY") == "comments_per_run" || os.Getenv("ACCUMULATE_PLANS") == "true" {
827-
reportStrategy = &reporting.CommentPerRunStrategy{
828-
TimeOfRun: time.Now(),
829-
}
830-
} else if os.Getenv("REPORTING_STRATEGY") == "latest_run_comment" {
831-
reportStrategy = &reporting.LatestRunCommentStrategy{
832-
TimeOfRun: time.Now(),
833-
}
834-
} else {
835-
reportStrategy = &reporting.MultipleCommentsStrategy{}
836-
}
837-
838-
lock, err := locking.GetLock()
839-
if err != nil {
840-
log.Printf("Failed to create lock provider. %s\n", err)
841-
os.Exit(2)
842-
}
843-
log.Println("Lock provider has been created successfully")
844-
845-
ci := digger.DetectCI()
846-
847-
var logLeader = "Unknown CI"
848-
849-
switch ci {
850-
case digger.GitHub:
851-
logLeader = os.Getenv("GITHUB_ACTOR")
852-
gitHubCI(lock, policyChecker, backendApi, reportStrategy)
853-
case digger.GitLab:
854-
logLeader = os.Getenv("CI_PROJECT_NAME")
855-
gitLabCI(lock, policyChecker, backendApi, reportStrategy)
856-
case digger.Azure:
857-
// This should be refactored in the future because in this way the parsing
858-
// is done twice, both here and inside azureCI, a better solution might be
859-
// to encapsulate it into a method on the azure package and then grab the
860-
// value here and pass it into the azureCI call.
861-
azureContext := os.Getenv("AZURE_CONTEXT")
862-
parsedAzureContext, _ := azure.GetAzureReposContext(azureContext)
863-
logLeader = parsedAzureContext.BaseUrl
864-
azureCI(lock, policyChecker, backendApi, reportStrategy)
865-
case digger.BitBucket:
866-
logLeader = os.Getenv("BITBUCKET_STEP_TRIGGERER_UUID")
867-
bitbucketCI(lock, policyChecker, backendApi, reportStrategy)
868-
case digger.None:
869-
print("No CI detected.")
870-
os.Exit(10)
871-
}
872-
873-
defer func() {
874-
if r := recover(); r != nil {
875-
log.Println(fmt.Sprintf("stacktrace from panic: \n" + string(debug.Stack())))
876-
err := usage.SendLogRecord(logLeader, fmt.Sprintf("Panic occurred. %s", r))
877-
if err != nil {
878-
log.Printf("Failed to send log record. %s\n", err)
879-
}
880-
os.Exit(1)
881-
}
882-
}()
883819
}
884820

885821
func newPlanStorage(ghToken string, ghRepoOwner string, ghRepositoryName string, requestedBy string, prNumber *int) core_storage.PlanStorage {

0 commit comments

Comments
 (0)