| package repo_manager |
| |
| import ( |
| "context" |
| "net/http" |
| "path/filepath" |
| |
| "go.skia.org/infra/autoroll/go/codereview" |
| "go.skia.org/infra/autoroll/go/config" |
| "go.skia.org/infra/autoroll/go/config_vars" |
| "go.skia.org/infra/autoroll/go/repo_manager/child" |
| "go.skia.org/infra/autoroll/go/repo_manager/child/revision_filter" |
| "go.skia.org/infra/autoroll/go/repo_manager/parent" |
| "go.skia.org/infra/autoroll/go/revision" |
| "go.skia.org/infra/go/git" |
| "go.skia.org/infra/go/skerr" |
| "go.skia.org/infra/go/sklog" |
| ) |
| |
| // parentChildRepoManager combines a Parent and a Child to implement the |
| // RepoManager interface. |
| type parentChildRepoManager struct { |
| child.Child |
| parent.Parent |
| revFilters revision_filter.RevisionFilters |
| } |
| |
| // newParentChildRepoManager returns a RepoManager which pairs a Parent with a |
| // Child. |
| func newParentChildRepoManager(ctx context.Context, c *config.ParentChildRepoManagerConfig, reg *config_vars.Registry, workdir, rollerName, serverURL string, client *http.Client, cr codereview.CodeReview) (*parentChildRepoManager, error) { |
| var childRM child.Child |
| var parentRM parent.Parent |
| var err error |
| |
| // Some Child implementations require that they are created by the Parent, |
| // so we have to create the Parent first. |
| var childCheckout git.Checkout |
| if c.GetDepsLocalGerritParent() != nil { |
| parentCfg := c.GetDepsLocalGerritParent() |
| childPath := parentCfg.DepsLocal.ChildPath |
| if parentCfg.DepsLocal.ChildSubdir != "" { |
| childPath = filepath.Join(parentCfg.DepsLocal.ChildSubdir, childPath) |
| } |
| childFullPath := filepath.Join(workdir, childPath) |
| childCheckout = git.CheckoutDir(childFullPath) |
| parentRM, err = parent.NewDEPSLocalGerrit(ctx, parentCfg, reg, client, serverURL, workdir, rollerName, cr) |
| } else if c.GetDepsLocalGithubParent() != nil { |
| parentCfg := c.GetDepsLocalGithubParent() |
| childPath := parentCfg.DepsLocal.ChildPath |
| if parentCfg.DepsLocal.ChildSubdir != "" { |
| childPath = filepath.Join(parentCfg.DepsLocal.ChildSubdir, childPath) |
| } |
| childFullPath := filepath.Join(workdir, childPath) |
| childCheckout = git.CheckoutDir(childFullPath) |
| parentRM, err = parent.NewDEPSLocalGitHub(ctx, parentCfg, reg, client, serverURL, workdir, rollerName, cr) |
| } else if c.GetGitCheckoutGerritParent() != nil { |
| parentRM, err = parent.NewGitCheckoutGerrit(ctx, c.GetGitCheckoutGerritParent(), reg, client, serverURL, workdir, rollerName, cr) |
| } else if c.GetGitCheckoutGithubFileParent() != nil { |
| parentRM, err = parent.NewGitCheckoutGithubFile(ctx, c.GetGitCheckoutGithubFileParent(), reg, client, serverURL, workdir, rollerName, cr) |
| } else if c.GetGitilesParent() != nil { |
| parentRM, err = parent.NewGitilesFile(ctx, c.GetGitilesParent(), reg, client, serverURL) |
| } else if c.GetGoModGerritParent() != nil { |
| parentRM, err = parent.NewGoModGerritParent(ctx, c.GetGoModGerritParent(), reg, client, workdir, cr) |
| } |
| if err != nil { |
| return nil, skerr.Wrap(err) |
| } |
| |
| // Create the Child. |
| if c.GetCipdChild() != nil { |
| childRM, err = child.NewCIPD(ctx, c.GetCipdChild(), reg, client, workdir) |
| } else if c.GetFuchsiaSdkChild() != nil { |
| childRM, err = child.NewFuchsiaSDK(ctx, c.GetFuchsiaSdkChild(), client) |
| } else if c.GetGitilesChild() != nil { |
| childRM, err = child.NewGitiles(ctx, c.GetGitilesChild(), reg, client) |
| } else if c.GetGitCheckoutChild() != nil { |
| childRM, err = child.NewGitCheckout(ctx, c.GetGitCheckoutChild(), reg, workdir, cr, childCheckout) |
| } else if c.GetGitCheckoutGithubChild() != nil { |
| childRM, err = child.NewGitCheckoutGithub(ctx, c.GetGitCheckoutGithubChild(), reg, workdir, cr, childCheckout) |
| } else if c.GetSemverGcsChild() != nil { |
| childRM, err = child.NewSemVerGCS(ctx, c.GetSemverGcsChild(), reg, client) |
| } else if c.GetDockerChild() != nil { |
| childRM, err = child.NewDocker(ctx, c.GetDockerChild()) |
| } |
| if err != nil { |
| return nil, skerr.Wrap(err) |
| } |
| if childRM == nil { |
| return nil, skerr.Fmt("missing child") |
| } |
| |
| // Some Parent implementations require a Child to be passed in. |
| if c.GetCopyParent() != nil { |
| parentRM, err = parent.NewCopy(ctx, c.GetCopyParent(), reg, client, serverURL, workdir, cr.UserName(), cr.UserEmail(), childRM) |
| } |
| if err != nil { |
| return nil, skerr.Wrap(err) |
| } |
| if parentRM == nil { |
| return nil, skerr.Fmt("missing parent") |
| } |
| |
| // Revision filter. |
| var revFilters []revision_filter.RevisionFilter |
| for _, rfConfig := range c.GetBuildbucketRevisionFilter() { |
| revFilter, err := revision_filter.NewBuildbucketRevisionFilter(client, rfConfig) |
| if err != nil { |
| return nil, skerr.Wrap(err) |
| } |
| revFilters = append(revFilters, revFilter) |
| } |
| for _, rfConfig := range c.GetCipdRevisionFilter() { |
| revFilter, err := revision_filter.NewCIPDRevisionFilter(client, rfConfig, workdir) |
| if err != nil { |
| return nil, skerr.Wrap(err) |
| } |
| revFilters = append(revFilters, revFilter) |
| } |
| for _, rfConfig := range c.GetValidHttpRevisionFilter() { |
| revFilter, err := revision_filter.NewValidRevisionFromHTTPRevisionFilter(rfConfig, client) |
| if err != nil { |
| return nil, skerr.Wrap(err) |
| } |
| revFilters = append(revFilters, revFilter) |
| } |
| |
| return &parentChildRepoManager{ |
| Child: childRM, |
| Parent: parentRM, |
| revFilters: revFilters, |
| }, nil |
| } |
| |
| // See documentation for RepoManager interface. |
| func (rm *parentChildRepoManager) Update(ctx context.Context) (*revision.Revision, *revision.Revision, []*revision.Revision, error) { |
| lastRollRevId, err := rm.Parent.Update(ctx) |
| if err != nil { |
| return nil, nil, nil, skerr.Wrapf(err, "failed to update Parent") |
| } |
| lastRollRev, err := rm.Child.GetRevision(ctx, lastRollRevId) |
| if err != nil { |
| sklog.Errorf("Last roll rev %q not found. This is acceptable for some rollers which allow outside versions to be rolled manually (eg. AFDO roller). A human should verify that this is indeed caused by a manual roll. Attempting to continue with no last-rolled revision. The revisions listed in the commit message will be incorrect! Error: %s", lastRollRevId, err) |
| lastRollRev = &revision.Revision{ |
| Id: lastRollRevId, |
| InvalidReason: "Failed to retrieve revision.", |
| } |
| } |
| tipRev, notRolledRevs, err := rm.Child.Update(ctx, lastRollRev) |
| if err != nil { |
| return nil, nil, nil, skerr.Wrapf(err, "failed to get next revision to roll from Child") |
| } |
| |
| // Optionally filter not-rolled revisions. |
| if err := rm.revFilters.Update(ctx); err != nil { |
| return nil, nil, nil, skerr.Wrap(err) |
| } |
| if err := rm.revFilters.MaybeSetInvalid(ctx, tipRev); err != nil { |
| return nil, nil, nil, skerr.Wrap(err) |
| } |
| for _, notRolledRev := range notRolledRevs { |
| if err := rm.revFilters.MaybeSetInvalid(ctx, notRolledRev); err != nil { |
| return nil, nil, nil, skerr.Wrap(err) |
| } |
| } |
| return lastRollRev, tipRev, notRolledRevs, nil |
| } |
| |
| // See documentation for RepoManager interface. |
| func (rm *parentChildRepoManager) LogRevisions(ctx context.Context, from, to *revision.Revision) ([]*revision.Revision, error) { |
| return rm.Child.LogRevisions(ctx, from, to) |
| } |
| |
| // parentChildRepoManager implements RepoManager. |
| var _ RepoManager = &parentChildRepoManager{} |