From 9f7227946b11dd22c62fdce27466c6a21a74c802 Mon Sep 17 00:00:00 2001 From: Ali AKCA Date: Thu, 26 Oct 2023 16:43:02 +0200 Subject: [PATCH] refactor: remove deprecated opts structs from modules --- daggerverse/gale/dagger.json | 5 +- daggerverse/gale/helpers.go | 22 +---- daggerverse/gale/opts.go | 103 ----------------------- daggerverse/gale/workflow_run.go | 84 ++++++++++++++++--- daggerverse/gale/workflows.go | 85 ++++++++++++++----- daggerverse/repo/go.mod | 10 +-- daggerverse/repo/go.sum | 27 +++++-- daggerverse/repo/repo.go | 135 ++++++++++++++++++------------- daggerverse/source/go.mod | 10 +-- daggerverse/source/go.sum | 28 +++++-- daggerverse/source/helpers.go | 15 ++-- daggerverse/source/source.go | 14 ++-- 12 files changed, 290 insertions(+), 248 deletions(-) delete mode 100644 daggerverse/gale/opts.go diff --git a/daggerverse/gale/dagger.json b/daggerverse/gale/dagger.json index ec7d7736..cdd45bf6 100644 --- a/daggerverse/gale/dagger.json +++ b/daggerverse/gale/dagger.json @@ -1,8 +1,9 @@ { "name": "gale", + "root": "../..", "sdk": "go", "dependencies": [ - "github.com/aweris/gale/daggerverse/repo@main", - "github.com/aweris/gale/daggerverse/source@main" + "../repo", + "../source" ] } diff --git a/daggerverse/gale/helpers.go b/daggerverse/gale/helpers.go index de50c189..e1c748cf 100644 --- a/daggerverse/gale/helpers.go +++ b/daggerverse/gale/helpers.go @@ -4,29 +4,11 @@ import ( "context" "encoding/json" "fmt" - "path/filepath" - "runtime" - "gopkg.in/yaml.v3" ) -// root returns the root directory of the project. -func root() string { - // get location of current file - _, current, _, _ := runtime.Caller(0) - - println(current) - - return filepath.Join(filepath.Dir(current), "../..") -} - -// root returns the root directory of the project. -func (h *Host) root(opts ...HostDirectoryOpts) *Directory { - return h.Directory(root(), opts...) -} - // unmarshalContentsToYAML unmarshal the contents of the file as YAML into the given value. -func (f *File) unmarshalContentsToYAML(ctx context.Context, v interface{}) error { +func unmarshalContentsToYAML(ctx context.Context, f *File, v interface{}) error { stdout, err := f.Contents(ctx) if err != nil { return fmt.Errorf("%w: failed to get file contents", err) @@ -41,7 +23,7 @@ func (f *File) unmarshalContentsToYAML(ctx context.Context, v interface{}) error } // unmarshalContentsToJSON unmarshal the contents of the file as JSON into the given value. -func (f *File) unmarshalContentsToJSON(ctx context.Context, v interface{}) error { +func unmarshalContentsToJSON(ctx context.Context, f *File, v interface{}) error { stdout, err := f.Contents(ctx) if err != nil { return fmt.Errorf("%w: failed to get file contents", err) diff --git a/daggerverse/gale/opts.go b/daggerverse/gale/opts.go deleted file mode 100644 index 8a510ef1..00000000 --- a/daggerverse/gale/opts.go +++ /dev/null @@ -1,103 +0,0 @@ -package main - -// RepoOpts represents the options for getting repository information. -// -// This is copy of RepoOpts from daggerverse/gale/repo.go to be able to expose options with gale module and pass them to -// the repo module just type casting. -type RepoOpts struct { - Source *Directory `doc:"Directory containing the repository source. Has precedence over repo."` - Repo string `doc:"Name of the repository. Format: owner/name."` - Branch string `doc:"Git branch to checkout. Used with --repo. If tag and branch are both specified, tag takes precedence."` - Tag string `doc:"Git tag to checkout. Used with --repo. If tag and branch are both specified, tag takes precedence."` -} - -// WorkflowsDirOpts represents the options for getting workflow information. -type WorkflowsDirOpts struct { - WorkflowsDir string `doc:"Path to the workflow directory." default:".github/workflows"` -} - -// WorkflowsRunOpts represents the options for running a workflow. -type WorkflowsRunOpts struct { - WorkflowFile *File `doc:"External workflow file to run."` - Workflow string `doc:"Name of the workflow to run."` - Job string `doc:"Name of the job to run. If empty, all jobs will be run."` - Event string `doc:"Name of the event that triggered the workflow." default:"push"` - EventFile *File `doc:"The file with the complete webhook json event payload."` - RunnerImage string `doc:"Docker image to use for the runner." default:"ghcr.io/catthehacker/ubuntu:act-latest"` - RunnerDebug bool `doc:"Enables debug mode." default:"false"` - Token *Secret `doc:"GitHub token to use for authentication."` -} - -// WorkflowRunDirectoryOpts represents the options for exporting a workflow run. -type WorkflowRunDirectoryOpts struct { - IncludeRepo bool `doc:"Adds the repository source to the exported directory." default:"false"` - IncludeSecrets bool `doc:"Adds the mounted secrets to the exported directory." default:"false"` - IncludeEvent bool `doc:"Adds the event file to the exported directory." default:"false"` - IncludeArtifacts bool `doc:"Adds the uploaded artifacts to the exported directory." default:"false"` -} - -// FIXME: add jobs to WorkflowRunReport when dagger supports map type - -// WorkflowRunReport represents the result of a workflow run. -type WorkflowRunReport struct { - Ran bool `json:"ran"` // Ran indicates if the execution ran - Duration string `json:"duration"` // Duration of the execution - Name string `json:"name"` // Name is the name of the workflow - Path string `json:"path"` // Path is the path of the workflow - RunID string `json:"run_id"` // RunID is the ID of the run - RunNumber string `json:"run_number"` // RunNumber is the number of the run - RunAttempt string `json:"run_attempt"` // RunAttempt is the attempt number of the run - RetentionDays string `json:"retention_days"` // RetentionDays is the number of days to keep the run logs - Conclusion string `json:"conclusion"` // Conclusion is the result of a completed workflow run after continue-on-error is applied -} - -// Configuration objects - -// When dagger converts objects to commands. All public methods and fields converted to sub commands of that object. -// To keep command DX simple when we need to pass options as a part of the state we're using config objects to hold the -// options. This way we can keep the command DX simple and only one extra command is added to the command tree. - -// These config objects basically holds the options for the commands but to keep code code gen friendly we're duplicating -// the options as fields of the config objects. - -// WorkflowRunConfig holds the configuration of a workflow run. -type WorkflowRunConfig struct { - // Directory containing the repository source. - Source *Directory - - // Name of the repository. Format: owner/name. - Repo string - - // Branch name to check out. Only one of branch or tag can be used. Precedence: tag, branch. - Branch string - - // Tag name to check out. Only one of branch or tag can be used. Precedence: tag, branch. - Tag string - - // Path to the workflow directory. - WorkflowsDir string - - // WorkflowFile is external workflow file to run. - WorkflowFile *File - - // Workflow to run. - Workflow string - - // Job name to run. If empty, all jobs will be run. - Job string - - // Name of the event that triggered the workflow. e.g. push - Event string - - // File with the complete webhook event payload. - EventFile *File - - // Image to use for the runner. - RunnerImage string - - // Enables debug mode. - RunnerDebug bool - - // GitHub token to use for authentication. - Token *Secret -} diff --git a/daggerverse/gale/workflow_run.go b/daggerverse/gale/workflow_run.go index 700a599a..24b9865a 100644 --- a/daggerverse/gale/workflow_run.go +++ b/daggerverse/gale/workflow_run.go @@ -8,22 +8,88 @@ import ( ) type WorkflowRun struct { - // Configuration for the workflow run. Config WorkflowRunConfig } -// Sync evaluates the workflow run and returns the container that executed the workflow. +// WorkflowRunConfig holds the configuration of a workflow run. +type WorkflowRunConfig struct { + // Directory containing the repository source. + Source *Directory + + // Name of the repository. Format: owner/name. + Repo string + + // Branch name to check out. Only one of branch or tag can be used. Precedence: tag, branch. + Branch string + + // Tag name to check out. Only one of branch or tag can be used. Precedence: tag, branch. + Tag string + + // Path to the workflow directory. + WorkflowsDir string + + // WorkflowFile is external workflow file to run. + WorkflowFile *File + + // Workflow to run. + Workflow string + + // Job name to run. If empty, all jobs will be run. + Job string + + // Name of the event that triggered the workflow. e.g. push + Event string + + // File with the complete webhook event payload. + EventFile *File + + // Image to use for the runner. + RunnerImage string + + // Enables debug mode. + RunnerDebug bool + + // GitHub token to use for authentication. + Token *Secret +} + +// FIXME: add jobs to WorkflowRunReport when dagger supports map type + +// WorkflowRunReport represents the result of a workflow run. +type WorkflowRunReport struct { + Ran bool `json:"ran"` // Ran indicates if the execution ran + Duration string `json:"duration"` // Duration of the execution + Name string `json:"name"` // Name is the name of the workflow + Path string `json:"path"` // Path is the path of the workflow + RunID string `json:"run_id"` // RunID is the ID of the run + RunNumber string `json:"run_number"` // RunNumber is the number of the run + RunAttempt string `json:"run_attempt"` // RunAttempt is the attempt number of the run + RetentionDays string `json:"retention_days"` // RetentionDays is the number of days to keep the run logs + Conclusion string `json:"conclusion"` // Conclusion is the result of a completed workflow run after continue-on-error is applied +} + +// Sync runs the workflow and returns the container that ran the workflow. func (wr *WorkflowRun) Sync(ctx context.Context) (*Container, error) { container, err := wr.run(ctx) if err != nil { return nil, err } - return container.Sync(ctx) + return container, nil } // Directory returns the directory of the workflow run information. -func (wr *WorkflowRun) Directory(ctx context.Context, opts WorkflowRunDirectoryOpts) (*Directory, error) { +func (wr *WorkflowRun) Directory( + ctx context.Context, + // Adds the repository source to the exported directory. (default: false) + includeRepo Optional[bool], + // Adds the mounted secrets to the exported directory. (default: false) + includeSecrets Optional[bool], + // Adds the event file to the exported directory. (default: false) + includeEvent Optional[bool], + // Adds the uploaded artifacts to the exported directory. (default: false) + includeArtifacts Optional[bool], +) (*Directory, error) { container, err := wr.run(ctx) if err != nil { return nil, err @@ -31,22 +97,22 @@ func (wr *WorkflowRun) Directory(ctx context.Context, opts WorkflowRunDirectoryO dir := dag.Directory().WithDirectory("run", container.Directory("/home/runner/_temp/ghx/run")) - if opts.IncludeRepo { + if includeRepo.GetOr(false) { dir = dir.WithDirectory("repo", container.Directory(".")) } - if opts.IncludeSecrets { + if includeSecrets.GetOr(false) { dir = dir.WithDirectory("secrets", container.Directory("/home/runner/_temp/ghx/secrets")) } - if opts.IncludeEvent && wr.Config.EventFile != nil { + if includeEvent.GetOr(false) && wr.Config.EventFile != nil { dir = dir.WithFile("event.json", container.File("/home/runner/_temp/_github_workflow/event.json")) } - if opts.IncludeArtifacts { + if includeArtifacts.GetOr(false) { var report WorkflowRunReport - err := dir.File("run/workflow_run.json").unmarshalContentsToJSON(ctx, &report) + err := unmarshalContentsToJSON(ctx, dir.File("run/workflow_run.json"), &report) if err != nil { return nil, err } diff --git a/daggerverse/gale/workflows.go b/daggerverse/gale/workflows.go index baec5242..7ee64487 100644 --- a/daggerverse/gale/workflows.go +++ b/daggerverse/gale/workflows.go @@ -9,9 +9,31 @@ import ( type Workflows struct{} -func (w *Workflows) List(ctx context.Context, repoOpts RepoOpts, dirOpts WorkflowsDirOpts) (string, error) { - dir := dag.Repo().Source((RepoSourceOpts)(repoOpts)).Directory(dirOpts.WorkflowsDir) +func (w *Workflows) List( + ctx context.Context, + // The directory containing the repository source. If source is provided, rest of the options are ignored. + source Optional[*Directory], + // The name of the repository. Format: owner/name. + repo Optional[string], + // Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + tag Optional[string], + // Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + branch Optional[string], + // Path to the workflows directory. (default: .github/workflows) + workflowsDir Optional[string], +) (string, error) { + // convert workflows list options to repo source options + opts := RepoSourceOpts{ + Source: source.GetOr(nil), + Repo: repo.GetOr(""), + Tag: tag.GetOr(""), + Branch: branch.GetOr(""), + } + + // get the repository source working directory from the options + dir := dag.Repo().Source(opts).Directory(workflowsDir.GetOr(".github/workflows")) + // list all entries in the workflows directory entries, err := dir.Entries(ctx) if err != nil { return "", err @@ -23,7 +45,7 @@ func (w *Workflows) List(ctx context.Context, repoOpts RepoOpts, dirOpts Workflo // load only .yaml and .yml files if strings.HasSuffix(entry, ".yaml") || strings.HasSuffix(entry, ".yml") { file := dir.File(entry) - path := filepath.Join(dirOpts.WorkflowsDir, entry) + path := filepath.Join(workflowsDir.GetOr(".github/workflows"), entry) // dagger do not support maps yet, so we're defining anonymous struct to unmarshal the yaml file to avoid // hit this limitation. @@ -33,7 +55,7 @@ func (w *Workflows) List(ctx context.Context, repoOpts RepoOpts, dirOpts Workflo Jobs map[string]interface{} `yaml:"jobs"` } - if err := file.unmarshalContentsToYAML(ctx, &workflow); err != nil { + if err := unmarshalContentsToYAML(ctx, file, &workflow); err != nil { return "", err } @@ -57,22 +79,49 @@ func (w *Workflows) List(ctx context.Context, repoOpts RepoOpts, dirOpts Workflo return sb.String(), nil } -func (w *Workflows) Run(repoOpts RepoOpts, pathOpts WorkflowsDirOpts, runOpts WorkflowsRunOpts) *WorkflowRun { +func (w *Workflows) Run( + // The directory containing the repository source. If source is provided, rest of the options are ignored. + source Optional[*Directory], + // The name of the repository. Format: owner/name. + repo Optional[string], + // Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + tag Optional[string], + // Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + branch Optional[string], + // Path to the workflows directory. (default: .github/workflows) + workflowsDir Optional[string], + // External workflow file to run. + workflowFile Optional[*File], + // Name of the workflow to run. + workflow Optional[string], + // Name of the job to run. If empty, all jobs will be run. + job Optional[string], + // Name of the event that triggered the workflow. e.g. push + event Optional[string], + // File with the complete webhook event payload. + eventFile Optional[*File], + // Image to use for the runner. + runnerImage Optional[string], + // Enables debug mode. + runnerDebug Optional[bool], + // GitHub token to use for authentication. + token Optional[*Secret], +) *WorkflowRun { return &WorkflowRun{ Config: WorkflowRunConfig{ - Source: repoOpts.Source, - Repo: repoOpts.Repo, - Branch: repoOpts.Branch, - Tag: repoOpts.Tag, - WorkflowsDir: pathOpts.WorkflowsDir, - WorkflowFile: runOpts.WorkflowFile, - Workflow: runOpts.Workflow, - Job: runOpts.Job, - Event: runOpts.Event, - EventFile: runOpts.EventFile, - RunnerImage: runOpts.RunnerImage, - RunnerDebug: runOpts.RunnerDebug, - Token: runOpts.Token, + Source: source.GetOr(nil), + Repo: repo.GetOr(""), + Branch: branch.GetOr(""), + Tag: tag.GetOr(""), + WorkflowsDir: workflowsDir.GetOr(".github/workflows"), + WorkflowFile: workflowFile.GetOr(nil), + Workflow: workflow.GetOr(""), + Job: job.GetOr(""), + Event: event.GetOr("push"), + EventFile: eventFile.GetOr(nil), + RunnerImage: runnerImage.GetOr("ghcr.io/catthehacker/ubuntu:act-latest"), + RunnerDebug: runnerDebug.GetOr(false), + Token: token.GetOr(nil), }, } } diff --git a/daggerverse/repo/go.mod b/daggerverse/repo/go.mod index cbab3def..eeaca282 100644 --- a/daggerverse/repo/go.mod +++ b/daggerverse/repo/go.mod @@ -3,15 +3,13 @@ module repo go 1.21 require ( - github.com/99designs/gqlgen v0.17.39 + github.com/99designs/gqlgen v0.17.31 github.com/Khan/genqlient v0.6.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d - golang.org/x/sync v0.4.0 + golang.org/x/sync v0.3.0 ) require ( - github.com/google/uuid v1.3.1 // indirect - github.com/sosodev/duration v1.2.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect - github.com/vektah/gqlparser/v2 v2.5.10 // indirect + github.com/stretchr/testify v1.8.3 // indirect + github.com/vektah/gqlparser/v2 v2.5.6 // indirect ) diff --git a/daggerverse/repo/go.sum b/daggerverse/repo/go.sum index fd35b26b..4551ee79 100644 --- a/daggerverse/repo/go.sum +++ b/daggerverse/repo/go.sum @@ -1,20 +1,35 @@ -github.com/99designs/gqlgen v0.17.39 h1:wPTAyc2fqVjAWT5DsJ21k/lLudgnXzURwbsjVNegFpU= +github.com/99designs/gqlgen v0.17.31 h1:VncSQ82VxieHkea8tz11p7h/zSbvHSxSDZfywqWt158= +github.com/99designs/gqlgen v0.17.31/go.mod h1:i4rEatMrzzu6RXaHydq1nmEPZkb3bKQsnxNRHS4DQB4= github.com/Khan/genqlient v0.6.0 h1:Bwb1170ekuNIVIwTJEqvO8y7RxBxXu639VJOkKSrwAk= github.com/Khan/genqlient v0.6.0/go.mod h1:rvChwWVTqXhiapdhLDV4bp9tz/Xvtewwkon4DpWWCRM= +github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/vektah/gqlparser/v2 v2.5.6 h1:Ou14T0N1s191eRMZ1gARVqohcbe1e8FrcONScsq8cRU= +github.com/vektah/gqlparser/v2 v2.5.6/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/daggerverse/repo/repo.go b/daggerverse/repo/repo.go index e114a79b..9ca87774 100644 --- a/daggerverse/repo/repo.go +++ b/daggerverse/repo/repo.go @@ -9,14 +9,6 @@ import ( type Repo struct{} -// RepoOpts represents the options for getting repository information. -type RepoOpts struct { - Source *Directory `doc:"The directory containing the repository source. If source is provided, rest of the options are ignored."` - Repo string `doc:"The name of the repository. Format: owner/name."` - Branch string `doc:"Branch name to checkout. Only one of branch or tag can be used. Precedence is as follows: tag, branch."` - Tag string `doc:"Tag name to checkout. Only one of branch or tag can be used. Precedence is as follows: tag, branch."` -} - // RepoInfo represents a repository information. type RepoInfo struct { Owner string // Owner of the repository. @@ -35,19 +27,38 @@ type RepoInfo struct { // this method is separate from the RepoInfo struct because we're not able to return *Directory as part of RepoInfo. // Until it is fixed, we're returning *Directory from this method. -func (_ *Repo) Source(opts RepoOpts) (*Directory, error) { - return getRepoSource(opts) +func (_ *Repo) Source( + // The directory containing the repository source. If source is provided, rest of the options are ignored. + source Optional[*Directory], + // The name of the repository. Format: owner/name. + repo Optional[string], + // Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + tag Optional[string], + // Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + branch Optional[string], +) (*Directory, error) { + return getRepoSource(source, repo, tag, branch) } -func (_ *Repo) Info(ctx context.Context, opts RepoOpts) (*RepoInfo, error) { +func (_ *Repo) Info( + ctx context.Context, + // The directory containing the repository source. If source is provided, rest of the options are ignored. + source Optional[*Directory], + // The name of the repository. Format: owner/name. + repo Optional[string], + // Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + tag Optional[string], + // Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch. + branch Optional[string], +) (*RepoInfo, error) { // get the repository source from the options - source, err := getRepoSource(opts) + dir, err := getRepoSource(source, repo, tag, branch) if err != nil { return nil, err } // create a git container with the repository source to execute git commands - container := gitContainer(source) + container := gitContainer(dir) // get the repository url url, err := getTrimmedOutput(ctx, container, "config", "--get", "remote.origin.url") @@ -67,7 +78,7 @@ func (_ *Repo) Info(ctx context.Context, opts RepoOpts) (*RepoInfo, error) { } // get the ref and ref type - ref, refType, err := getRefAndRefType(ctx, opts, container, sha) + ref, refType, err := getRefAndRefType(ctx, branch, tag, container, sha) if err != nil { return nil, err } @@ -78,6 +89,8 @@ func (_ *Repo) Info(ctx context.Context, opts RepoOpts) (*RepoInfo, error) { return nil, err } + _, isLocal := source.Get() + return &RepoInfo{ Owner: owner, Name: repoName, @@ -88,7 +101,7 @@ func (_ *Repo) Info(ctx context.Context, opts RepoOpts) (*RepoInfo, error) { RefType: refType, SHA: sha, ShortSHA: shortSHA, - IsRemote: opts.Source == nil, + IsRemote: !isLocal, }, nil } @@ -109,8 +122,41 @@ func (ri *RepoInfo) Configure(_ context.Context, c *Container) (*Container, erro WithEnvVariable("GITHUB_SHA", ri.SHA), nil } +// getRepoSource returns the repository source based on the options provided. +func getRepoSource(sourceOpt Optional[*Directory], repoOpt, tagOpt, branchOpt Optional[string]) (*Directory, error) { + if source, ok := sourceOpt.Get(); ok { + return source, nil + } + + repo, ok := repoOpt.Get() + if !ok { + return nil, fmt.Errorf("either a repo or a source directory must be provided") + } + + var ( + gitURL = fmt.Sprintf("https://github.com/%s.git", repo) + gitRepo = dag.Git(gitURL, GitOpts{KeepGitDir: true}) + ) + + if tag, ok := tagOpt.Get(); ok { + return gitRepo.Tag(tag).Tree(), nil + } + + if branch, ok := branchOpt.Get(); ok { + return gitRepo.Branch(branch).Tree(), nil + } + + return nil, fmt.Errorf("when repo is provided, either a branch or a tag must be provided") +} + // getRefAndRefType returns the ref and ref type for given options. -func getRefAndRefType(ctx context.Context, opts RepoOpts, container *Container, sha string) (string, string, error) { +func getRefAndRefType( + ctx context.Context, + tagOpt Optional[string], + branchOpt Optional[string], + container *Container, + sha string, +) (string, string, error) { var ( ref string refType string @@ -120,55 +166,34 @@ func getRefAndRefType(ctx context.Context, opts RepoOpts, container *Container, // if branch or tag is provided, then repository cloned would be in detached head state. In that case, to work // around the issue, we're using given options to get the ref. If no branch or tag is provided, then we're using // the ref from the source code of the repository. - switch { - case opts.Tag != "": - ref = fmt.Sprintf("refs/tags/%s", opts.Tag) - refType = "tag" - case opts.Branch != "": - ref = fmt.Sprintf("refs/heads/%s", opts.Branch) - refType = "branch" - default: - ref, err = getRefFromSource(ctx, container, sha) - if err != nil { - return "", "", err - } - switch { - case strings.HasPrefix(ref, "refs/tags/"): - refType = "tag" - case strings.HasPrefix(ref, "refs/heads/"): - refType = "branch" - default: - return "", "", fmt.Errorf("unsupported ref type: %s", ref) - } + if tag, ok := tagOpt.Get(); ok { + ref = fmt.Sprintf("refs/tags/%s", tag) + refType = "tag" + return ref, refType, nil } - return ref, refType, nil -} - -// getRepoSource returns the repository source based on the options provided. -func getRepoSource(opts RepoOpts) (*Directory, error) { - if opts.Source != nil { - return opts.Source, nil + if branch, ok := branchOpt.Get(); ok { + ref = fmt.Sprintf("refs/heads/%s", branch) + refType = "branch" + return ref, refType, nil } - if opts.Repo == "" { - return nil, fmt.Errorf("either a repo or a source directory must be provided") + ref, err = getRefFromSource(ctx, container, sha) + if err != nil { + return "", "", err } - var ( - gitURL = fmt.Sprintf("https://github.com/%s.git", opts.Repo) - gitRepo = dag.Git(gitURL, GitOpts{KeepGitDir: true}) - ) - switch { - case opts.Tag != "": - return gitRepo.Tag(opts.Tag).Tree(), nil - case opts.Branch != "": - return gitRepo.Branch(opts.Branch).Tree(), nil + case strings.HasPrefix(ref, "refs/tags/"): + refType = "tag" + case strings.HasPrefix(ref, "refs/heads/"): + refType = "branch" + default: + return "", "", fmt.Errorf("unsupported ref type: %s", ref) } - return nil, fmt.Errorf("when repo is provided, either a branch or a tag must be provided") + return ref, refType, nil } // getRefFromSource returns the ref for given head from the repository source. diff --git a/daggerverse/source/go.mod b/daggerverse/source/go.mod index 8a13a976..862caaa2 100644 --- a/daggerverse/source/go.mod +++ b/daggerverse/source/go.mod @@ -3,16 +3,14 @@ module source go 1.21 require ( - github.com/99designs/gqlgen v0.17.39 + github.com/99designs/gqlgen v0.17.31 github.com/Khan/genqlient v0.6.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d golang.org/x/mod v0.13.0 - golang.org/x/sync v0.4.0 + golang.org/x/sync v0.3.0 ) require ( - github.com/google/uuid v1.3.1 // indirect - github.com/sosodev/duration v1.2.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect - github.com/vektah/gqlparser/v2 v2.5.10 // indirect + github.com/stretchr/testify v1.8.3 // indirect + github.com/vektah/gqlparser/v2 v2.5.6 // indirect ) diff --git a/daggerverse/source/go.sum b/daggerverse/source/go.sum index c942cb5d..73e51971 100644 --- a/daggerverse/source/go.sum +++ b/daggerverse/source/go.sum @@ -1,21 +1,37 @@ -github.com/99designs/gqlgen v0.17.39 h1:wPTAyc2fqVjAWT5DsJ21k/lLudgnXzURwbsjVNegFpU= +github.com/99designs/gqlgen v0.17.31 h1:VncSQ82VxieHkea8tz11p7h/zSbvHSxSDZfywqWt158= +github.com/99designs/gqlgen v0.17.31/go.mod h1:i4rEatMrzzu6RXaHydq1nmEPZkb3bKQsnxNRHS4DQB4= github.com/Khan/genqlient v0.6.0 h1:Bwb1170ekuNIVIwTJEqvO8y7RxBxXu639VJOkKSrwAk= github.com/Khan/genqlient v0.6.0/go.mod h1:rvChwWVTqXhiapdhLDV4bp9tz/Xvtewwkon4DpWWCRM= +github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/vektah/gqlparser/v2 v2.5.6 h1:Ou14T0N1s191eRMZ1gARVqohcbe1e8FrcONScsq8cRU= +github.com/vektah/gqlparser/v2 v2.5.6/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/daggerverse/source/helpers.go b/daggerverse/source/helpers.go index 2824165e..0e140af5 100644 --- a/daggerverse/source/helpers.go +++ b/daggerverse/source/helpers.go @@ -17,11 +17,6 @@ func root() string { return filepath.Join(filepath.Dir(current), "../..") } -// root returns the root directory of the project. -func (h *Host) root(opts ...HostDirectoryOpts) *Directory { - return h.Directory(root(), opts...) -} - func GoVersion(ctx context.Context, gomod *File) (string, error) { mod, err := gomod.Contents(ctx) if err != nil { @@ -36,17 +31,17 @@ func GoVersion(ctx context.Context, gomod *File) (string, error) { return f.Go.Version, nil } -func ModCache(container *Container) *Container { +func modCache(container *Container) *Container { return container.WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-cache")) } -func BuildCache(container *Container) *Container { +func buildCache(container *Container) *Container { return container.WithMountedCache("/root/.cache/go-build", dag.CacheVolume("go-build-cache")) } -func GoBase(version string) *Container { +func goBase(version string) *Container { return dag.Container(). From(fmt.Sprintf("golang:%s", version)). - With(ModCache). - With(BuildCache) + With(modCache). + With(buildCache) } diff --git a/daggerverse/source/source.go b/daggerverse/source/source.go index 32d43faf..03229e7c 100644 --- a/daggerverse/source/source.go +++ b/daggerverse/source/source.go @@ -10,7 +10,7 @@ type Source struct{} // Repo returns the source code of the repository. func (m *Source) Repo() *Directory { - return dag.Host().root() + return dag.Host().Directory(root()) } func (m *Source) Ghx() *GhxSource { @@ -30,7 +30,7 @@ type GhxSource struct{} // Code returns the source code of the ghx module. func (m *GhxSource) Code() *Directory { - return dag.Host().root(HostDirectoryOpts{ + return dag.Host().Directory(root(), HostDirectoryOpts{ Include: []string{ "common/**/*.go", "common/go.*", @@ -63,7 +63,7 @@ func (m *GhxSource) Binary(ctx context.Context, container *Container) (*Containe return nil, err } - source, err := GoBase(version). + source, err := goBase(version). With(m.MountedCode). WithExec([]string{"go", "mod", "download"}). WithExec([]string{"go", "build", "-o", "bin/ghx", "."}). @@ -93,7 +93,7 @@ type ArtifactServiceSource struct{} // Code returns the source code of the artifact service. func (m *ArtifactServiceSource) Code() *Directory { - return dag.Host().root(HostDirectoryOpts{ + return dag.Host().Directory(root(), HostDirectoryOpts{ Include: []string{ "common/**/*.go", "common/go.*", @@ -129,7 +129,7 @@ func (m *ArtifactServiceSource) Container(ctx context.Context) (*Container, erro return nil, err } - return GoBase(version). + return goBase(version). With(m.MountedCode). WithExec([]string{"go", "mod", "download"}). WithMountedCache("/artifacts", m.CacheVolume(), ContainerWithMountedCacheOpts{Sharing: Shared}). @@ -167,7 +167,7 @@ type ArtifactCacheServiceSource struct{} // Code returns the source code of the artifact cache service. func (m *ArtifactCacheServiceSource) Code() *Directory { - return dag.Host().root(HostDirectoryOpts{ + return dag.Host().Directory(root(), HostDirectoryOpts{ Include: []string{ "common/**/*.go", "common/go.*", @@ -203,7 +203,7 @@ func (m *ArtifactCacheServiceSource) Container(ctx context.Context) (*Container, return nil, err } - return GoBase(version). + return goBase(version). With(m.MountedCode). WithExec([]string{"go", "mod", "download"}). WithMountedCache("/cache", m.CacheVolume(), ContainerWithMountedCacheOpts{Sharing: Shared}).