Documentation ¶
Overview ¶
Package changelist implements operations on a single CL.
It is agnostic about the kind of a CL even though currently all CLs represent Gerrit changes.
Index ¶
- Constants
- Variables
- func Delete(ctx context.Context, id common.CLID) error
- func JoinExternalURLs(ids []ExternalID, sep string) string
- func LoadCLs(ctx context.Context, cls []*CL) error
- func Lookup(ctx context.Context, eids []ExternalID) ([]common.CLID, error)
- func QueryCLIDsUpdatedBefore(ctx context.Context, before time.Time) (common.CLIDs, error)
- func RemoveUnusedGerritInfo(ci *gerritpb.ChangeInfo)
- func Sort(cls []*CL)
- type Access
- type AccessKind
- type Access_Project
- func (*Access_Project) Descriptor() ([]byte, []int)deprecated
- func (x *Access_Project) GetNoAccess() bool
- func (x *Access_Project) GetNoAccessTime() *timestamppb.Timestamp
- func (x *Access_Project) GetUpdateTime() *timestamppb.Timestamp
- func (*Access_Project) ProtoMessage()
- func (x *Access_Project) ProtoReflect() protoreflect.Message
- func (x *Access_Project) Reset()
- func (x *Access_Project) String() string
- type ApplicableConfig
- func (*ApplicableConfig) Descriptor() ([]byte, []int)deprecated
- func (x *ApplicableConfig) GetProjects() []*ApplicableConfig_Project
- func (a *ApplicableConfig) HasOnlyProject(luciProject string) bool
- func (a *ApplicableConfig) HasProject(luciProject string) bool
- func (*ApplicableConfig) ProtoMessage()
- func (x *ApplicableConfig) ProtoReflect() protoreflect.Message
- func (x *ApplicableConfig) Reset()
- func (a *ApplicableConfig) SemanticallyEqual(b *ApplicableConfig) bool
- func (x *ApplicableConfig) String() string
- type ApplicableConfig_Project
- func (*ApplicableConfig_Project) Descriptor() ([]byte, []int)deprecated
- func (x *ApplicableConfig_Project) GetConfigGroupIds() []string
- func (x *ApplicableConfig_Project) GetName() string
- func (*ApplicableConfig_Project) ProtoMessage()
- func (x *ApplicableConfig_Project) ProtoReflect() protoreflect.Message
- func (x *ApplicableConfig_Project) Reset()
- func (x *ApplicableConfig_Project) String() string
- type BatchOnCLUpdatedTask
- func (*BatchOnCLUpdatedTask) Descriptor() ([]byte, []int)deprecated
- func (x *BatchOnCLUpdatedTask) GetProjects() map[string]*CLUpdatedEvents
- func (x *BatchOnCLUpdatedTask) GetRuns() map[string]*CLUpdatedEvents
- func (*BatchOnCLUpdatedTask) ProtoMessage()
- func (x *BatchOnCLUpdatedTask) ProtoReflect() protoreflect.Message
- func (x *BatchOnCLUpdatedTask) Reset()
- func (x *BatchOnCLUpdatedTask) String() string
- type BatchUpdateCLTask
- func (*BatchUpdateCLTask) Descriptor() ([]byte, []int)deprecated
- func (x *BatchUpdateCLTask) GetTasks() []*UpdateCLTask
- func (*BatchUpdateCLTask) ProtoMessage()
- func (x *BatchUpdateCLTask) ProtoReflect() protoreflect.Message
- func (x *BatchUpdateCLTask) Reset()
- func (x *BatchUpdateCLTask) String() string
- type CL
- func (cl *CL) AccessKind(ctx context.Context, luciProject string) AccessKind
- func (cl *CL) AccessKindFromCodeReviewSite(ctx context.Context, luciProject string) AccessKind
- func (cl *CL) AccessKindWithReason(ctx context.Context, luciProject string) (AccessKind, string)
- func (cl *CL) IsWatchedByThisAndOtherProjects(thisProject string) (*ApplicableConfig_Project, bool)
- func (cl *CL) ToUpdatedEvent() *CLUpdatedEvent
- func (cl *CL) URL() (string, error)
- func (cl *CL) UpdateRetentionKey()
- type CLError
- func (*CLError) Descriptor() ([]byte, []int)deprecated
- func (x *CLError) GetCommitBlocked() bool
- func (x *CLError) GetCorruptGerritMetadata() string
- func (x *CLError) GetDepRunFailed() int64
- func (x *CLError) GetInvalidDeps() *CLError_InvalidDeps
- func (m *CLError) GetKind() isCLError_Kind
- func (x *CLError) GetOwnerLacksEmail() bool
- func (x *CLError) GetReusedTrigger() *CLError_ReusedTrigger
- func (x *CLError) GetSelfCqDepend() bool
- func (x *CLError) GetTriggerDeps() *CLError_TriggerDeps
- func (x *CLError) GetUnsupportedMode() string
- func (x *CLError) GetWatchedByManyConfigGroups() *CLError_WatchedByManyConfigGroups
- func (x *CLError) GetWatchedByManyProjects() *CLError_WatchedByManyProjects
- func (*CLError) ProtoMessage()
- func (x *CLError) ProtoReflect() protoreflect.Message
- func (x *CLError) Reset()
- func (x *CLError) String() string
- type CLError_CommitBlocked
- type CLError_CorruptGerritMetadata
- type CLError_DepRunFailed
- type CLError_InvalidDeps
- func (*CLError_InvalidDeps) Descriptor() ([]byte, []int)deprecated
- func (x *CLError_InvalidDeps) GetCombinableMismatchedMode() []*Dep
- func (x *CLError_InvalidDeps) GetCombinableUntriggered() []*Dep
- func (x *CLError_InvalidDeps) GetSingleFullDeps() []*Dep
- func (x *CLError_InvalidDeps) GetTooMany() *CLError_InvalidDeps_TooMany
- func (x *CLError_InvalidDeps) GetUnwatched() []*Dep
- func (x *CLError_InvalidDeps) GetWrongConfigGroup() []*Dep
- func (*CLError_InvalidDeps) ProtoMessage()
- func (x *CLError_InvalidDeps) ProtoReflect() protoreflect.Message
- func (x *CLError_InvalidDeps) Reset()
- func (x *CLError_InvalidDeps) String() string
- type CLError_InvalidDeps_
- type CLError_InvalidDeps_TooMany
- func (*CLError_InvalidDeps_TooMany) Descriptor() ([]byte, []int)deprecated
- func (x *CLError_InvalidDeps_TooMany) GetActual() int32
- func (x *CLError_InvalidDeps_TooMany) GetMaxAllowed() int32
- func (*CLError_InvalidDeps_TooMany) ProtoMessage()
- func (x *CLError_InvalidDeps_TooMany) ProtoReflect() protoreflect.Message
- func (x *CLError_InvalidDeps_TooMany) Reset()
- func (x *CLError_InvalidDeps_TooMany) String() string
- type CLError_OwnerLacksEmail
- type CLError_ReusedTrigger
- func (*CLError_ReusedTrigger) Descriptor() ([]byte, []int)deprecated
- func (x *CLError_ReusedTrigger) GetRun() string
- func (*CLError_ReusedTrigger) ProtoMessage()
- func (x *CLError_ReusedTrigger) ProtoReflect() protoreflect.Message
- func (x *CLError_ReusedTrigger) Reset()
- func (x *CLError_ReusedTrigger) String() string
- type CLError_ReusedTrigger_
- type CLError_SelfCqDepend
- type CLError_TriggerDeps
- func (*CLError_TriggerDeps) Descriptor() ([]byte, []int)deprecated
- func (x *CLError_TriggerDeps) GetInternalGerritError() []int64
- func (x *CLError_TriggerDeps) GetNotFound() []int64
- func (x *CLError_TriggerDeps) GetPermissionDenied() []*CLError_TriggerDeps_PermissionDenied
- func (*CLError_TriggerDeps) ProtoMessage()
- func (x *CLError_TriggerDeps) ProtoReflect() protoreflect.Message
- func (x *CLError_TriggerDeps) Reset()
- func (x *CLError_TriggerDeps) String() string
- type CLError_TriggerDeps_
- type CLError_TriggerDeps_PermissionDenied
- func (*CLError_TriggerDeps_PermissionDenied) Descriptor() ([]byte, []int)deprecated
- func (x *CLError_TriggerDeps_PermissionDenied) GetClid() int64
- func (x *CLError_TriggerDeps_PermissionDenied) GetEmail() string
- func (*CLError_TriggerDeps_PermissionDenied) ProtoMessage()
- func (x *CLError_TriggerDeps_PermissionDenied) ProtoReflect() protoreflect.Message
- func (x *CLError_TriggerDeps_PermissionDenied) Reset()
- func (x *CLError_TriggerDeps_PermissionDenied) String() string
- type CLError_UnsupportedMode
- type CLError_WatchedByManyConfigGroups
- func (*CLError_WatchedByManyConfigGroups) Descriptor() ([]byte, []int)deprecated
- func (x *CLError_WatchedByManyConfigGroups) GetConfigGroups() []string
- func (*CLError_WatchedByManyConfigGroups) ProtoMessage()
- func (x *CLError_WatchedByManyConfigGroups) ProtoReflect() protoreflect.Message
- func (x *CLError_WatchedByManyConfigGroups) Reset()
- func (x *CLError_WatchedByManyConfigGroups) String() string
- type CLError_WatchedByManyConfigGroups_
- type CLError_WatchedByManyProjects
- func (*CLError_WatchedByManyProjects) Descriptor() ([]byte, []int)deprecated
- func (x *CLError_WatchedByManyProjects) GetProjects() []string
- func (*CLError_WatchedByManyProjects) ProtoMessage()
- func (x *CLError_WatchedByManyProjects) ProtoReflect() protoreflect.Message
- func (x *CLError_WatchedByManyProjects) Reset()
- func (x *CLError_WatchedByManyProjects) String() string
- type CLError_WatchedByManyProjects_
- type CLMutation
- type CLUpdatedEvent
- func (*CLUpdatedEvent) Descriptor() ([]byte, []int)deprecated
- func (x *CLUpdatedEvent) GetClid() int64
- func (x *CLUpdatedEvent) GetEversion() int64
- func (*CLUpdatedEvent) ProtoMessage()
- func (x *CLUpdatedEvent) ProtoReflect() protoreflect.Message
- func (x *CLUpdatedEvent) Reset()
- func (x *CLUpdatedEvent) String() string
- type CLUpdatedEvents
- type Dep
- type DepKind
- type ExternalID
- type FetchInput
- type Gerrit
- func (*Gerrit) Descriptor() ([]byte, []int)deprecated
- func (x *Gerrit) GetFiles() []string
- func (x *Gerrit) GetGitDeps() []*GerritGitDep
- func (x *Gerrit) GetHost() string
- func (x *Gerrit) GetInfo() *gerrit.ChangeInfo
- func (x *Gerrit) GetSoftDeps() []*GerritSoftDep
- func (*Gerrit) ProtoMessage()
- func (x *Gerrit) ProtoReflect() protoreflect.Message
- func (x *Gerrit) Reset()
- func (x *Gerrit) String() string
- type GerritGitDep
- func (*GerritGitDep) Descriptor() ([]byte, []int)deprecated
- func (x *GerritGitDep) GetChange() int64
- func (x *GerritGitDep) GetImmediate() bool
- func (*GerritGitDep) ProtoMessage()
- func (x *GerritGitDep) ProtoReflect() protoreflect.Message
- func (x *GerritGitDep) Reset()
- func (x *GerritGitDep) String() string
- type GerritSoftDep
- func (*GerritSoftDep) Descriptor() ([]byte, []int)deprecated
- func (x *GerritSoftDep) GetChange() int64
- func (x *GerritSoftDep) GetHost() string
- func (*GerritSoftDep) ProtoMessage()
- func (x *GerritSoftDep) ProtoReflect() protoreflect.Message
- func (x *GerritSoftDep) Reset()
- func (x *GerritSoftDep) String() string
- type MutateCallback
- type Mutator
- func (m *Mutator) Adopt(ctx context.Context, project string, cl *CL) *CLMutation
- func (m *Mutator) Begin(ctx context.Context, project string, id common.CLID) (*CLMutation, error)
- func (m *Mutator) BeginBatch(ctx context.Context, project string, ids common.CLIDs) ([]*CLMutation, error)
- func (m *Mutator) FinalizeBatch(ctx context.Context, muts []*CLMutation) ([]*CL, error)
- func (m *Mutator) Update(ctx context.Context, project string, id common.CLID, clbk MutateCallback) (*CL, error)
- func (m *Mutator) Upsert(ctx context.Context, project string, eid ExternalID, clbk MutateCallback) (*CL, error)
- type Snapshot
- func (*Snapshot) Descriptor() ([]byte, []int)deprecated
- func (x *Snapshot) GetDeps() []*Dep
- func (x *Snapshot) GetErrors() []*CLError
- func (x *Snapshot) GetExternalUpdateTime() *timestamppb.Timestamp
- func (x *Snapshot) GetGerrit() *Gerrit
- func (m *Snapshot) GetKind() isSnapshot_Kind
- func (x *Snapshot) GetLuciProject() string
- func (x *Snapshot) GetMetadata() []*StringPair
- func (x *Snapshot) GetMinEquivalentPatchset() int32
- func (x *Snapshot) GetOutdated() *Snapshot_Outdated
- func (x *Snapshot) GetPatchset() int32
- func (s *Snapshot) IsSubmittable() (bool, error)
- func (s *Snapshot) IsSubmitted() (bool, error)
- func (s *Snapshot) OwnerIdentity() (identity.Identity, error)
- func (s *Snapshot) PanicIfNotValid()
- func (*Snapshot) ProtoMessage()
- func (x *Snapshot) ProtoReflect() protoreflect.Message
- func (x *Snapshot) Reset()
- func (x *Snapshot) String() string
- type Snapshot_Gerrit
- type Snapshot_Outdated
- type StringPair
- type UpdateCLTask
- func (*UpdateCLTask) Descriptor() ([]byte, []int)deprecated
- func (x *UpdateCLTask) GetExternalId() string
- func (x *UpdateCLTask) GetHint() *UpdateCLTask_Hint
- func (x *UpdateCLTask) GetId() int64
- func (x *UpdateCLTask) GetIsForDep() bool
- func (x *UpdateCLTask) GetLuciProject() string
- func (x *UpdateCLTask) GetRequester() UpdateCLTask_Requester
- func (*UpdateCLTask) ProtoMessage()
- func (x *UpdateCLTask) ProtoReflect() protoreflect.Message
- func (x *UpdateCLTask) Reset()
- func (x *UpdateCLTask) String() string
- type UpdateCLTask_Hint
- func (*UpdateCLTask_Hint) Descriptor() ([]byte, []int)deprecated
- func (x *UpdateCLTask_Hint) GetExternalUpdateTime() *timestamppb.Timestamp
- func (x *UpdateCLTask_Hint) GetMetaRevId() string
- func (*UpdateCLTask_Hint) ProtoMessage()
- func (x *UpdateCLTask_Hint) ProtoReflect() protoreflect.Message
- func (x *UpdateCLTask_Hint) Reset()
- func (x *UpdateCLTask_Hint) String() string
- type UpdateCLTask_Requester
- func (UpdateCLTask_Requester) Descriptor() protoreflect.EnumDescriptor
- func (x UpdateCLTask_Requester) Enum() *UpdateCLTask_Requester
- func (UpdateCLTask_Requester) EnumDescriptor() ([]byte, []int)deprecated
- func (x UpdateCLTask_Requester) Number() protoreflect.EnumNumber
- func (x UpdateCLTask_Requester) String() string
- func (UpdateCLTask_Requester) Type() protoreflect.EnumType
- type UpdateFields
- type Updater
- func (u *Updater) RegisterBackend(b UpdaterBackend)
- func (u *Updater) ResolveAndScheduleDepsUpdate(ctx context.Context, luciProject string, deps map[ExternalID]DepKind, ...) ([]*Dep, error)
- func (u *Updater) Schedule(ctx context.Context, payload *UpdateCLTask) error
- func (u *Updater) ScheduleBatch(ctx context.Context, luciProject string, cls []*CL, ...) error
- func (u *Updater) ScheduleDelayed(ctx context.Context, payload *UpdateCLTask, delay time.Duration) error
- func (u *Updater) TestingForceUpdate(ctx context.Context, task *UpdateCLTask) error
- type UpdaterBackend
Constants ¶
const ( // BatchUpdateCLTaskClass is the Task Class ID of the BatchUpdateCLTask, // which is enqueued only during a transaction. BatchUpdateCLTaskClass = "batch-update-cl" // UpdateCLTaskClass is the Task Class ID of the UpdateCLTask. UpdateCLTaskClass = "update-cl" )
const BatchOnCLUpdatedTaskClass = "batch-notify-on-cl-updated"
BatchOnCLUpdatedTaskClass is the Task Class ID of the BatchOnCLUpdatedTask, which is enqueued during CL mutations.
Variables ¶
var ( DepKind_name = map[int32]string{ 0: "DEP_KIND_UNSPECIFIED", 1: "HARD", 2: "SOFT", } DepKind_value = map[string]int32{ "DEP_KIND_UNSPECIFIED": 0, "HARD": 1, "SOFT": 2, } )
Enum value maps for DepKind.
var ( UpdateCLTask_Requester_name = map[int32]string{ 0: "REQUESTER_CLASS_UNSPECIFIED", 1: "INCR_POLL_MATCHED", 2: "FULL_POLL_MATCHED", 3: "FULL_POLL_UNMATCHED", 4: "PUBSUB_POLL", 5: "CL_PURGER", 12: "DEP_CL_TRIGGERER", 6: "RPC_ADMIN", 7: "RUN_POKE", 8: "RUN_REMOVAL", 11: "RESET_CL_TRIGGER", 10: "UPDATE_CONFIG", } UpdateCLTask_Requester_value = map[string]int32{ "REQUESTER_CLASS_UNSPECIFIED": 0, "INCR_POLL_MATCHED": 1, "FULL_POLL_MATCHED": 2, "FULL_POLL_UNMATCHED": 3, "PUBSUB_POLL": 4, "CL_PURGER": 5, "DEP_CL_TRIGGERER": 12, "RPC_ADMIN": 6, "RUN_POKE": 7, "RUN_REMOVAL": 8, "RESET_CL_TRIGGER": 11, "UPDATE_CONFIG": 10, } )
Enum value maps for UpdateCLTask_Requester.
var ErrStopMutation = errors.New("stop CL mutation")
ErrStopMutation is a special error used by MutateCallback to signal that no mutation is necessary.
This is very useful because the datastore.RunInTransaction(ctx, f, ...) does retries by default which combined with submarine writes (transaction actually succeeded, but the client didn't get to know, e.g. due to network flake) means an idempotent MutateCallback can avoid noop updates yet still keep the code clean and readable. For example,
```
cl, err := mu.Update(ctx, project, clid, func (cl *changelist.CL) error { if cl.Snapshot == nil { return ErrStopMutation // noop } cl.Snapshot = nil return nil }) if err != nil { return errors.Annotate(err, "failed to reset Snapshot").Err() }
doSomething(ctx, cl) ```
var File_go_chromium_org_luci_cv_internal_changelist_storage_proto protoreflect.FileDescriptor
var File_go_chromium_org_luci_cv_internal_changelist_task_proto protoreflect.FileDescriptor
Functions ¶
func Delete ¶
Delete deletes CL and its CLMap entities transactionally.
Thus, deletion and insertion (part of ExternalID.getOrInsert) are atomic with respect to one another.
However, ExternalID.get and fast path of ExternalID.getOrInsert if called concurrently with Delete may return a temporary error, but on retry they would return ErrNoSuchEntity.
func JoinExternalURLs ¶
func JoinExternalURLs(ids []ExternalID, sep string) string
JoinExternalURLs the URL of given ExternalIDs.
Panics if any of the ExternalIDs is invalid.
func Lookup ¶
Lookup loads CLID for each given ExternalID.
CLID is 0 if ExternalID is not yet known. Returns a single error (not MultiError) if there were multiple errors.
func QueryCLIDsUpdatedBefore ¶
QueryCLIDsUpdatedBefore queries all CLIDs updated before the given timestamp.
This is mainly used for data retention purpose. Result CLIDs are sorted.
func RemoveUnusedGerritInfo ¶
func RemoveUnusedGerritInfo(ci *gerritpb.ChangeInfo)
RemoveUnusedGerritInfo mutates given ChangeInfo to remove what CV definitely doesn't need to reduce bytes shuffled to/from Datastore.
Doesn't complain if anything is missing.
NOTE: keep this function actions in sync with storage.proto doc for Gerrit.info field.
Types ¶
type Access ¶
type Access struct { ByProject map[string]*Access_Project `` // TODO(tandrii): per-project ApplicableConfig here. /* 176-byte string literal not displayed */ // contains filtered or unexported fields }
Access records which LUCI project can or can't see a CL.
If a LUCI project has Access, it means both:
(1) the project can read details of the CL (via Git/Gerrit ACLs); (2) the project is the only LUCI project watching this CL in CV (via the CV config). Note: there can still be several applicable ConfigGroups of the same project (see ApplicableConfig).
In practice, .Access is set in 4 cases:
(a) `CQ-Depend: host:number` Gerrit CL footers allow users to specify
arbitrary dependencies, which typically happens due to typos, but malicious actors can try to get CL details of restricted projects. Either way, CV must not be a confused deputy here and must keep track which project can see what.
(b) due to recent re-configuration of one or more LUCI projects, either
in CV config and/or in Gerrit ACLs, the previously watched & readable CL becomes unwatched and/or unreadable.
(c) a previously existing CL was deleted (e.g. by its owner or Gerrit
administrators).
(d) eventual consistency of Gerrit masquerading as HTTP 404 on stale replica,
while quorum of replicas think CL actually exists and specific LUCI project having access to it.
Unfortunately, (d) isn't easy to distinguish from (b) and (c), so CV resorts to tracking time since CL became invisible -- the longer, the more likely it is (b) or (c).
Furthermore, in case of (a), iff CV knows nothing about specific Gerrit CL identified as `CQ-Depend: host:change`, CV in general can't determine which LUCI project is allowed to watch this CL *before* fetching Gerrit project (repo) and target ref.
NOTE on CV as confused deputy.
CV works with multiple LUCI projects. As of this writing (June 2021), unfortunately, CV doesn't verify that Gerrit repos watched by a LUCI project are in fact owned by that LUCI project. Thus, nothing prevents one LUCI project from starting to watch repos de-facto owned by another LUCI project. This in turn brings 2 problems:
(1) Denial of service: unsolved.
Mitigation: CV will refuse to work with CLs which are watched by more than 1 project. Since CV will communicate by posting message to affected CL, this should be noticed and fixed quickly.
(2) Information leaks: solved.
Each LUCI project MUST use project-scoped service account (PSSA) (migration is under way, see https://crbug.com/824492). CV uses this account for all interaction with Gerrit on behalf a specific LUCI project. Corresponding Gerrit repos: * SHOULD limit read access to its own PSSA + developers, * MUST limit Submit rights to its own PSSA and possibly developers.
For example,
- `infra` project has all its Gerrit CLs public and doesn't care about information leaks. All other LUCI projects can read its CLs, as well as the whole Internet.
- `infra-internal` project protects its Gerrit CLs, making them visible to `infra-internal-scoped@...` account only. When CV queries Gerrit on `infra-internal` behalf, CV uses `infra-internal-scoped` account and can fetch the data.
- Suppose malicious actor compromised `infra` repo, and placed a new CV config there to start watching CLs of the `infra-internal` project as well as super/secret/repo, which wasn't watched by any CV before.
- Unfortunately, CV can't currently object to the new config.
- However, when querying Gerrit on `infra` behalf, CV uses `infra-scoped@...` account, which presumably won't be configured with read access to neither infra-internal nor super/secret/repo.
- So, corresponding CLs will have .Access entry recording that `infra` has no access to them.
- NOTE: CLs of infra-internal will also have .ApplicableConfig with two projects there, which will prevent normal operation of `infra-internal` CV but will not cause any leaks.
func (*Access) Descriptor
deprecated
func (*Access) GetByProject ¶
func (x *Access) GetByProject() map[string]*Access_Project
func (*Access) ProtoMessage ¶
func (*Access) ProtoMessage()
func (*Access) ProtoReflect ¶
func (x *Access) ProtoReflect() protoreflect.Message
type AccessKind ¶
type AccessKind int
AccessKind is the level of access a LUCI project has to a CL.
const ( // AccessUnknown means a CL needs refreshing in the context of this project // in order to ascertain the AccessKind. AccessUnknown AccessKind = iota // AccessGranted means this LUCI project has exclusive access to the CL. // // * this LUCI project is configured to watch this config, // * and no other project is; // * this LUCI project has access to the CL in code review (e.g., Gerrit); AccessGranted // AccessDeniedProbably means there is early evidence that LUCI project lacks // access to the project. // // This is a mitigation to Gerrit eventual consistency, which may result in // HTTP 404 returned for a CL that has just been created. AccessDeniedProbably // AccessDenied means the LUCI project has no access to this CL. // // Can be either due to project config not being the only watcher of the CL, // or due to the inability to fetch CL from code review (e.g. Gerrit). AccessDenied )
type Access_Project ¶
type Access_Project struct { // Deprecated. Use no_access_time instead. NoAccess bool `protobuf:"varint,1,opt,name=no_access,json=noAccess,proto3" json:"no_access,omitempty"` // The time when this was last re-confirmed. UpdateTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"` // The time after which CV should consider lack of access stable. // // TODO(crbug/1216630): may be unset until backfil is done, // in which case use `no_access` field. NoAccessTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=no_access_time,json=noAccessTime,proto3" json:"no_access_time,omitempty"` // contains filtered or unexported fields }
func (*Access_Project) Descriptor
deprecated
func (*Access_Project) Descriptor() ([]byte, []int)
Deprecated: Use Access_Project.ProtoReflect.Descriptor instead.
func (*Access_Project) GetNoAccess ¶
func (x *Access_Project) GetNoAccess() bool
func (*Access_Project) GetNoAccessTime ¶
func (x *Access_Project) GetNoAccessTime() *timestamppb.Timestamp
func (*Access_Project) GetUpdateTime ¶
func (x *Access_Project) GetUpdateTime() *timestamppb.Timestamp
func (*Access_Project) ProtoMessage ¶
func (*Access_Project) ProtoMessage()
func (*Access_Project) ProtoReflect ¶
func (x *Access_Project) ProtoReflect() protoreflect.Message
func (*Access_Project) Reset ¶
func (x *Access_Project) Reset()
func (*Access_Project) String ¶
func (x *Access_Project) String() string
type ApplicableConfig ¶
type ApplicableConfig struct { Projects []*ApplicableConfig_Project `protobuf:"bytes,2,rep,name=projects,proto3" json:"projects,omitempty"` // contains filtered or unexported fields }
ApplicableConfig keeps track of configs applicable to a CL.
This is computed based on known set of LUCI project configs, versions of which are updated by CV independently, so the ApplicableConfig are also eventually consistent.
Normally, there is 1 applicable configs = exactly 1 project with 1 config group. If CL is no longer watched by CV, there will be 0 applicable configs.
Sometimes, there can be 2+ applicable configs. This happens if either:
- eventual consistency: responsibility for CL is moved from one LUCI project to another. Three is no way to make this atomically, so CL may temporarily end up with 0 or 2 projects watching it, before settling on just 1.
- misconfiguration: two projects or 2 different ConfigGroups within the same project watch the same CL.
In either case, CV refuses to guess and will abstain from processing such CLs, but storing the list is very useful for CV debugging and potentially for better diagnostic messages to CV users and LUCI project owners.
func (*ApplicableConfig) Descriptor
deprecated
func (*ApplicableConfig) Descriptor() ([]byte, []int)
Deprecated: Use ApplicableConfig.ProtoReflect.Descriptor instead.
func (*ApplicableConfig) GetProjects ¶
func (x *ApplicableConfig) GetProjects() []*ApplicableConfig_Project
func (*ApplicableConfig) HasOnlyProject ¶
func (a *ApplicableConfig) HasOnlyProject(luciProject string) bool
HasOnlyProject returns true iff ApplicableConfig contains only the given project, regardless of the number of applicable config groups it may contain.
func (*ApplicableConfig) HasProject ¶
func (a *ApplicableConfig) HasProject(luciProject string) bool
HasProject returns true whether ApplicableConfig contains the given project, possibly among other projects.
func (*ApplicableConfig) ProtoMessage ¶
func (*ApplicableConfig) ProtoMessage()
func (*ApplicableConfig) ProtoReflect ¶
func (x *ApplicableConfig) ProtoReflect() protoreflect.Message
func (*ApplicableConfig) Reset ¶
func (x *ApplicableConfig) Reset()
func (*ApplicableConfig) SemanticallyEqual ¶
func (a *ApplicableConfig) SemanticallyEqual(b *ApplicableConfig) bool
SemanticallyEqual checks if ApplicableConfig configs are the same.
func (*ApplicableConfig) String ¶
func (x *ApplicableConfig) String() string
type ApplicableConfig_Project ¶
type ApplicableConfig_Project struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // ID of the specific ConfigGroup. See cv/internal/config.ConfigGroupID. // // The referenced version may no longer be available to datastore, // commonly happening if CL wasn't active for a long time. ConfigGroupIds []string `protobuf:"bytes,2,rep,name=config_group_ids,json=configGroupIds,proto3" json:"config_group_ids,omitempty"` // contains filtered or unexported fields }
func (*ApplicableConfig_Project) Descriptor
deprecated
func (*ApplicableConfig_Project) Descriptor() ([]byte, []int)
Deprecated: Use ApplicableConfig_Project.ProtoReflect.Descriptor instead.
func (*ApplicableConfig_Project) GetConfigGroupIds ¶
func (x *ApplicableConfig_Project) GetConfigGroupIds() []string
func (*ApplicableConfig_Project) GetName ¶
func (x *ApplicableConfig_Project) GetName() string
func (*ApplicableConfig_Project) ProtoMessage ¶
func (*ApplicableConfig_Project) ProtoMessage()
func (*ApplicableConfig_Project) ProtoReflect ¶
func (x *ApplicableConfig_Project) ProtoReflect() protoreflect.Message
func (*ApplicableConfig_Project) Reset ¶
func (x *ApplicableConfig_Project) Reset()
func (*ApplicableConfig_Project) String ¶
func (x *ApplicableConfig_Project) String() string
type BatchOnCLUpdatedTask ¶
type BatchOnCLUpdatedTask struct { Projects map[string]*CLUpdatedEvents `` /* 157-byte string literal not displayed */ Runs map[string]*CLUpdatedEvents `` /* 149-byte string literal not displayed */ // contains filtered or unexported fields }
BatchOnCLUpdatedTask notifies many Projects and Runs about updated CLs.
Queue: "notify-on-cl-updated".
func (*BatchOnCLUpdatedTask) Descriptor
deprecated
func (*BatchOnCLUpdatedTask) Descriptor() ([]byte, []int)
Deprecated: Use BatchOnCLUpdatedTask.ProtoReflect.Descriptor instead.
func (*BatchOnCLUpdatedTask) GetProjects ¶
func (x *BatchOnCLUpdatedTask) GetProjects() map[string]*CLUpdatedEvents
func (*BatchOnCLUpdatedTask) GetRuns ¶
func (x *BatchOnCLUpdatedTask) GetRuns() map[string]*CLUpdatedEvents
func (*BatchOnCLUpdatedTask) ProtoMessage ¶
func (*BatchOnCLUpdatedTask) ProtoMessage()
func (*BatchOnCLUpdatedTask) ProtoReflect ¶
func (x *BatchOnCLUpdatedTask) ProtoReflect() protoreflect.Message
func (*BatchOnCLUpdatedTask) Reset ¶
func (x *BatchOnCLUpdatedTask) Reset()
func (*BatchOnCLUpdatedTask) String ¶
func (x *BatchOnCLUpdatedTask) String() string
type BatchUpdateCLTask ¶
type BatchUpdateCLTask struct { Tasks []*UpdateCLTask `protobuf:"bytes,1,rep,name=tasks,proto3" json:"tasks,omitempty"` // contains filtered or unexported fields }
BatchUpdateCLTask is for updating many CLs.
When executed, it just enqueues its tasks as individual UpdateCLTask TQ for independent execution.
Queue: "update-cl".
func (*BatchUpdateCLTask) Descriptor
deprecated
func (*BatchUpdateCLTask) Descriptor() ([]byte, []int)
Deprecated: Use BatchUpdateCLTask.ProtoReflect.Descriptor instead.
func (*BatchUpdateCLTask) GetTasks ¶
func (x *BatchUpdateCLTask) GetTasks() []*UpdateCLTask
func (*BatchUpdateCLTask) ProtoMessage ¶
func (*BatchUpdateCLTask) ProtoMessage()
func (*BatchUpdateCLTask) ProtoReflect ¶
func (x *BatchUpdateCLTask) ProtoReflect() protoreflect.Message
func (*BatchUpdateCLTask) Reset ¶
func (x *BatchUpdateCLTask) Reset()
func (*BatchUpdateCLTask) String ¶
func (x *BatchUpdateCLTask) String() string
type CL ¶
type CL struct { // ID is auto-generated by Datastore. ID common.CLID `gae:"$id"` // int64 // ExternalID must not be modified once entity is created. ExternalID ExternalID `gae:",noindex"` // string. Indexed in CLMap entities. // EVersion is entity version. Every update should increment it by 1. // See Update() function. EVersion int64 `gae:",noindex"` // UpdateTime is exact time of when this entity was last updated. // // It's not indexed to avoid hot areas in the index. UpdateTime time.Time `gae:",noindex"` // RetentionKey is for data retention purpose. // // It is indexed and tries to avoid hot areas in the index. The format is // `{shard_key}/{unix_time_of_UpdateTime}`. Shard key is the last 2 // digit of CLID with left padded zero. Unix timestamp is a 10 digit integer // with left padded zero if necessary. RetentionKey string // Snapshot is the latest known state of a CL. It may be and often is // behind the source of truth, which is the code review site (e.g. Gerrit). Snapshot *Snapshot // ApplicableConfig keeps track of configs applicable to the CL. // // TODO(tandrii): merge into .Access. ApplicableConfig *ApplicableConfig // Access records per-LUCI project visibility of a CL. // // See description in protobuf type with the same name. // // TODO(tandrii): rename GAE field to `Access`. Access *Access `gae:"DependentMeta"` // IncompleteRuns tracks not yet finalized Runs working on this CL. Sorted. // // It's updated transactionally with the Run being modified. IncompleteRuns common.RunIDs `gae:",noindex"` // TriggerNewPatchsetRunAfterPS indicates the patchset number after which // new patchset runs can be triggered. // // E.g. if this value is set to 2, do not trigger new patchset runs for // patchsets 1 or 2. Presumably this is because those runs were already // completed/failed/otherwise purged. // // This is needed because unlike label votes which CV can remove, triggering // new patchset upload runs relies on the presence of the patchset in the CL // snapshot, which cannot be removed. TriggerNewPatchsetRunAfterPS int32 `gae:",noindex"` // contains filtered or unexported fields }
CL is a CL entity in Datastore.
func LoadCLsByIDs ¶
LoadCLsByIDs loads `CL` entities of the provided list of clids.
func LoadCLsMap ¶
LoadCLsMap loads `CL` entities which are values in the provided map.
Updates `CL` entities *in place*, but also returns them as a slice.
func (*CL) AccessKind ¶
func (cl *CL) AccessKind(ctx context.Context, luciProject string) AccessKind
AccessKind returns AccessKind of a CL.
func (*CL) AccessKindFromCodeReviewSite ¶
func (cl *CL) AccessKindFromCodeReviewSite(ctx context.Context, luciProject string) AccessKind
AccessKind returns AccessKind of a CL from code review site.
func (*CL) AccessKindWithReason ¶
AccessKindWithReason returns AccessKind of a CL and a reason for it.
func (*CL) IsWatchedByThisAndOtherProjects ¶
func (cl *CL) IsWatchedByThisAndOtherProjects(thisProject string) (*ApplicableConfig_Project, bool)
IsWatchedByThisAndOtherProjects checks if CL is watched by several projects, one of which is given. If so, returns the config applicable to the given project and true. Else, returns nil, false.
func (*CL) ToUpdatedEvent ¶
func (cl *CL) ToUpdatedEvent() *CLUpdatedEvent
ToUpdatedEvent returns CLUpdatedEvent corresponding to the current CL version.
func (*CL) UpdateRetentionKey ¶
func (cl *CL) UpdateRetentionKey()
UpdateRetentionKey updates the RetentionKey of the CL.
Panics if the CL.ID and/or CL.UpdateTime is absent.
type CLError ¶
type CLError struct { // Next tag is 12. // // Types that are assignable to Kind: // // *CLError_OwnerLacksEmail // *CLError_WatchedByManyConfigGroups_ // *CLError_WatchedByManyProjects_ // *CLError_InvalidDeps_ // *CLError_UnsupportedMode // *CLError_SelfCqDepend // *CLError_CorruptGerritMetadata // *CLError_ReusedTrigger_ // *CLError_CommitBlocked // *CLError_TriggerDeps_ // *CLError_DepRunFailed Kind isCLError_Kind `protobuf_oneof:"kind"` // contains filtered or unexported fields }
CLError encapsulates all kinds of CL errors, which ultimately result in purging of the CL while communicating the reason to the relevant users.
The primary goal of the CLError is to transport via CV guts sufficient information to generate a clear user-friendly error message.
func (*CLError) Descriptor
deprecated
func (*CLError) GetCommitBlocked ¶
func (*CLError) GetCorruptGerritMetadata ¶
func (*CLError) GetDepRunFailed ¶
func (*CLError) GetInvalidDeps ¶
func (x *CLError) GetInvalidDeps() *CLError_InvalidDeps
func (*CLError) GetOwnerLacksEmail ¶
func (*CLError) GetReusedTrigger ¶
func (x *CLError) GetReusedTrigger() *CLError_ReusedTrigger
func (*CLError) GetSelfCqDepend ¶
func (*CLError) GetTriggerDeps ¶
func (x *CLError) GetTriggerDeps() *CLError_TriggerDeps
func (*CLError) GetUnsupportedMode ¶
func (*CLError) GetWatchedByManyConfigGroups ¶
func (x *CLError) GetWatchedByManyConfigGroups() *CLError_WatchedByManyConfigGroups
func (*CLError) GetWatchedByManyProjects ¶
func (x *CLError) GetWatchedByManyProjects() *CLError_WatchedByManyProjects
func (*CLError) ProtoMessage ¶
func (*CLError) ProtoMessage()
func (*CLError) ProtoReflect ¶
func (x *CLError) ProtoReflect() protoreflect.Message
type CLError_CommitBlocked ¶
type CLError_CommitBlocked struct { // Set to true when the footer "Commit: false" is present. CommitBlocked bool `protobuf:"varint,9,opt,name=commit_blocked,json=commitBlocked,proto3,oneof"` }
type CLError_CorruptGerritMetadata ¶
type CLError_CorruptGerritMetadata struct {
CorruptGerritMetadata string `protobuf:"bytes,6,opt,name=corrupt_gerrit_metadata,json=corruptGerritMetadata,proto3,oneof"`
}
type CLError_DepRunFailed ¶
type CLError_DepRunFailed struct { // Set with the CL ID of a failed Run, if the purge-requested-CL depends on // the CL. DepRunFailed int64 `protobuf:"varint,11,opt,name=dep_run_failed,json=depRunFailed,proto3,oneof"` }
type CLError_InvalidDeps ¶
type CLError_InvalidDeps struct { // Deps not watched by the same LUCI project as the dependent. Unwatched []*Dep `protobuf:"bytes,1,rep,name=unwatched,proto3" json:"unwatched,omitempty"` // Deps watched by the same LUCI project but different config group. WrongConfigGroup []*Dep `protobuf:"bytes,2,rep,name=wrong_config_group,json=wrongConfigGroup,proto3" json:"wrong_config_group,omitempty"` // Not yet submitted deps of a full run in non-combinable mode. SingleFullDeps []*Dep `protobuf:"bytes,3,rep,name=single_full_deps,json=singleFullDeps,proto3" json:"single_full_deps,omitempty"` // Not yet CQ-ed deps of a Run in combinable mode. CombinableUntriggered []*Dep `protobuf:"bytes,4,rep,name=combinable_untriggered,json=combinableUntriggered,proto3" json:"combinable_untriggered,omitempty"` // CQ-ed deps of a different mode. CombinableMismatchedMode []*Dep `` /* 135-byte string literal not displayed */ // There are more non-submitted deps than is supported by CV. TooMany *CLError_InvalidDeps_TooMany `protobuf:"bytes,6,opt,name=too_many,json=tooMany,proto3" json:"too_many,omitempty"` // contains filtered or unexported fields }
func (*CLError_InvalidDeps) Descriptor
deprecated
func (*CLError_InvalidDeps) Descriptor() ([]byte, []int)
Deprecated: Use CLError_InvalidDeps.ProtoReflect.Descriptor instead.
func (*CLError_InvalidDeps) GetCombinableMismatchedMode ¶
func (x *CLError_InvalidDeps) GetCombinableMismatchedMode() []*Dep
func (*CLError_InvalidDeps) GetCombinableUntriggered ¶
func (x *CLError_InvalidDeps) GetCombinableUntriggered() []*Dep
func (*CLError_InvalidDeps) GetSingleFullDeps ¶
func (x *CLError_InvalidDeps) GetSingleFullDeps() []*Dep
func (*CLError_InvalidDeps) GetTooMany ¶
func (x *CLError_InvalidDeps) GetTooMany() *CLError_InvalidDeps_TooMany
func (*CLError_InvalidDeps) GetUnwatched ¶
func (x *CLError_InvalidDeps) GetUnwatched() []*Dep
func (*CLError_InvalidDeps) GetWrongConfigGroup ¶
func (x *CLError_InvalidDeps) GetWrongConfigGroup() []*Dep
func (*CLError_InvalidDeps) ProtoMessage ¶
func (*CLError_InvalidDeps) ProtoMessage()
func (*CLError_InvalidDeps) ProtoReflect ¶
func (x *CLError_InvalidDeps) ProtoReflect() protoreflect.Message
func (*CLError_InvalidDeps) Reset ¶
func (x *CLError_InvalidDeps) Reset()
func (*CLError_InvalidDeps) String ¶
func (x *CLError_InvalidDeps) String() string
type CLError_InvalidDeps_ ¶
type CLError_InvalidDeps_ struct {
InvalidDeps *CLError_InvalidDeps `protobuf:"bytes,3,opt,name=invalid_deps,json=invalidDeps,proto3,oneof"`
}
type CLError_InvalidDeps_TooMany ¶
type CLError_InvalidDeps_TooMany struct { Actual int32 `protobuf:"varint,1,opt,name=actual,proto3" json:"actual,omitempty"` MaxAllowed int32 `protobuf:"varint,2,opt,name=max_allowed,json=maxAllowed,proto3" json:"max_allowed,omitempty"` // contains filtered or unexported fields }
func (*CLError_InvalidDeps_TooMany) Descriptor
deprecated
func (*CLError_InvalidDeps_TooMany) Descriptor() ([]byte, []int)
Deprecated: Use CLError_InvalidDeps_TooMany.ProtoReflect.Descriptor instead.
func (*CLError_InvalidDeps_TooMany) GetActual ¶
func (x *CLError_InvalidDeps_TooMany) GetActual() int32
func (*CLError_InvalidDeps_TooMany) GetMaxAllowed ¶
func (x *CLError_InvalidDeps_TooMany) GetMaxAllowed() int32
func (*CLError_InvalidDeps_TooMany) ProtoMessage ¶
func (*CLError_InvalidDeps_TooMany) ProtoMessage()
func (*CLError_InvalidDeps_TooMany) ProtoReflect ¶
func (x *CLError_InvalidDeps_TooMany) ProtoReflect() protoreflect.Message
func (*CLError_InvalidDeps_TooMany) Reset ¶
func (x *CLError_InvalidDeps_TooMany) Reset()
func (*CLError_InvalidDeps_TooMany) String ¶
func (x *CLError_InvalidDeps_TooMany) String() string
type CLError_OwnerLacksEmail ¶
type CLError_OwnerLacksEmail struct {
OwnerLacksEmail bool `protobuf:"varint,1,opt,name=owner_lacks_email,json=ownerLacksEmail,proto3,oneof"`
}
type CLError_ReusedTrigger ¶
type CLError_ReusedTrigger struct { // ID of the finalized Run. Run string `protobuf:"bytes,1,opt,name=run,proto3" json:"run,omitempty"` // contains filtered or unexported fields }
ReusedTrigger means a CL trigger (e.g. CQ+1 vote) has already resulted in a CQ Run which was finalized.
Two known cases when this happens with a Gerrit CL:
- A user uploads a CL on ref A, then votes CQ+1. Before the Dry Run completes, the CL is moved to ref B, while preserving the CQ+1 vote. The old Run is finalized, but the new Run has the exact same trigger, which in CQDaemon-compatible mode means the new Run's ID is exactly the same as the old one, so CV can't create a new Run. TODO(crbug/1223349): after CQDaemon is deleted, the Run ID generation scheme can take into account the ref of a CL, and this use case can be allowed.
- The same as above but instead of moving CL between refs, abandon and restore the CL.
func (*CLError_ReusedTrigger) Descriptor
deprecated
func (*CLError_ReusedTrigger) Descriptor() ([]byte, []int)
Deprecated: Use CLError_ReusedTrigger.ProtoReflect.Descriptor instead.
func (*CLError_ReusedTrigger) GetRun ¶
func (x *CLError_ReusedTrigger) GetRun() string
func (*CLError_ReusedTrigger) ProtoMessage ¶
func (*CLError_ReusedTrigger) ProtoMessage()
func (*CLError_ReusedTrigger) ProtoReflect ¶
func (x *CLError_ReusedTrigger) ProtoReflect() protoreflect.Message
func (*CLError_ReusedTrigger) Reset ¶
func (x *CLError_ReusedTrigger) Reset()
func (*CLError_ReusedTrigger) String ¶
func (x *CLError_ReusedTrigger) String() string
type CLError_ReusedTrigger_ ¶
type CLError_ReusedTrigger_ struct {
ReusedTrigger *CLError_ReusedTrigger `protobuf:"bytes,7,opt,name=reused_trigger,json=reusedTrigger,proto3,oneof"`
}
type CLError_SelfCqDepend ¶
type CLError_SelfCqDepend struct {
SelfCqDepend bool `protobuf:"varint,5,opt,name=self_cq_depend,json=selfCqDepend,proto3,oneof"`
}
type CLError_TriggerDeps ¶
type CLError_TriggerDeps struct { // IDs of CLs for which trigger attempts failed due to permission denied. PermissionDenied []*CLError_TriggerDeps_PermissionDenied `protobuf:"bytes,1,rep,name=permission_denied,json=permissionDenied,proto3" json:"permission_denied,omitempty"` // IDs of CLs for which trigger attempts failed because they were not found // in Gerrit. NotFound []int64 `protobuf:"varint,2,rep,packed,name=not_found,json=notFound,proto3" json:"not_found,omitempty"` // IDs of CLs for which trigger attempts failed due to internal Gerrit // error. InternalGerritError []int64 `` /* 128-byte string literal not displayed */ // contains filtered or unexported fields }
TriggerDeps indicates failures for triggering deps.
func (*CLError_TriggerDeps) Descriptor
deprecated
func (*CLError_TriggerDeps) Descriptor() ([]byte, []int)
Deprecated: Use CLError_TriggerDeps.ProtoReflect.Descriptor instead.
func (*CLError_TriggerDeps) GetInternalGerritError ¶
func (x *CLError_TriggerDeps) GetInternalGerritError() []int64
func (*CLError_TriggerDeps) GetNotFound ¶
func (x *CLError_TriggerDeps) GetNotFound() []int64
func (*CLError_TriggerDeps) GetPermissionDenied ¶
func (x *CLError_TriggerDeps) GetPermissionDenied() []*CLError_TriggerDeps_PermissionDenied
func (*CLError_TriggerDeps) ProtoMessage ¶
func (*CLError_TriggerDeps) ProtoMessage()
func (*CLError_TriggerDeps) ProtoReflect ¶
func (x *CLError_TriggerDeps) ProtoReflect() protoreflect.Message
func (*CLError_TriggerDeps) Reset ¶
func (x *CLError_TriggerDeps) Reset()
func (*CLError_TriggerDeps) String ¶
func (x *CLError_TriggerDeps) String() string
type CLError_TriggerDeps_ ¶
type CLError_TriggerDeps_ struct {
TriggerDeps *CLError_TriggerDeps `protobuf:"bytes,10,opt,name=trigger_deps,json=triggerDeps,proto3,oneof"`
}
type CLError_TriggerDeps_PermissionDenied ¶
type CLError_TriggerDeps_PermissionDenied struct { Clid int64 `protobuf:"varint,1,opt,name=clid,proto3" json:"clid,omitempty"` // If set, the vote was attempted on behalf of the Gerrit user. Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` // contains filtered or unexported fields }
func (*CLError_TriggerDeps_PermissionDenied) Descriptor
deprecated
func (*CLError_TriggerDeps_PermissionDenied) Descriptor() ([]byte, []int)
Deprecated: Use CLError_TriggerDeps_PermissionDenied.ProtoReflect.Descriptor instead.
func (*CLError_TriggerDeps_PermissionDenied) GetClid ¶
func (x *CLError_TriggerDeps_PermissionDenied) GetClid() int64
func (*CLError_TriggerDeps_PermissionDenied) GetEmail ¶
func (x *CLError_TriggerDeps_PermissionDenied) GetEmail() string
func (*CLError_TriggerDeps_PermissionDenied) ProtoMessage ¶
func (*CLError_TriggerDeps_PermissionDenied) ProtoMessage()
func (*CLError_TriggerDeps_PermissionDenied) ProtoReflect ¶
func (x *CLError_TriggerDeps_PermissionDenied) ProtoReflect() protoreflect.Message
func (*CLError_TriggerDeps_PermissionDenied) Reset ¶
func (x *CLError_TriggerDeps_PermissionDenied) Reset()
func (*CLError_TriggerDeps_PermissionDenied) String ¶
func (x *CLError_TriggerDeps_PermissionDenied) String() string
type CLError_UnsupportedMode ¶
type CLError_UnsupportedMode struct {
UnsupportedMode string `protobuf:"bytes,4,opt,name=unsupported_mode,json=unsupportedMode,proto3,oneof"`
}
type CLError_WatchedByManyConfigGroups ¶
type CLError_WatchedByManyConfigGroups struct { // Config group names without LUCI project prefix. ConfigGroups []string `protobuf:"bytes,1,rep,name=config_groups,json=configGroups,proto3" json:"config_groups,omitempty"` // contains filtered or unexported fields }
func (*CLError_WatchedByManyConfigGroups) Descriptor
deprecated
func (*CLError_WatchedByManyConfigGroups) Descriptor() ([]byte, []int)
Deprecated: Use CLError_WatchedByManyConfigGroups.ProtoReflect.Descriptor instead.
func (*CLError_WatchedByManyConfigGroups) GetConfigGroups ¶
func (x *CLError_WatchedByManyConfigGroups) GetConfigGroups() []string
func (*CLError_WatchedByManyConfigGroups) ProtoMessage ¶
func (*CLError_WatchedByManyConfigGroups) ProtoMessage()
func (*CLError_WatchedByManyConfigGroups) ProtoReflect ¶
func (x *CLError_WatchedByManyConfigGroups) ProtoReflect() protoreflect.Message
func (*CLError_WatchedByManyConfigGroups) Reset ¶
func (x *CLError_WatchedByManyConfigGroups) Reset()
func (*CLError_WatchedByManyConfigGroups) String ¶
func (x *CLError_WatchedByManyConfigGroups) String() string
type CLError_WatchedByManyConfigGroups_ ¶
type CLError_WatchedByManyConfigGroups_ struct {
WatchedByManyConfigGroups *CLError_WatchedByManyConfigGroups `protobuf:"bytes,2,opt,name=watched_by_many_config_groups,json=watchedByManyConfigGroups,proto3,oneof"`
}
type CLError_WatchedByManyProjects ¶
type CLError_WatchedByManyProjects struct { Projects []string `protobuf:"bytes,1,rep,name=projects,proto3" json:"projects,omitempty"` // contains filtered or unexported fields }
func (*CLError_WatchedByManyProjects) Descriptor
deprecated
func (*CLError_WatchedByManyProjects) Descriptor() ([]byte, []int)
Deprecated: Use CLError_WatchedByManyProjects.ProtoReflect.Descriptor instead.
func (*CLError_WatchedByManyProjects) GetProjects ¶
func (x *CLError_WatchedByManyProjects) GetProjects() []string
func (*CLError_WatchedByManyProjects) ProtoMessage ¶
func (*CLError_WatchedByManyProjects) ProtoMessage()
func (*CLError_WatchedByManyProjects) ProtoReflect ¶
func (x *CLError_WatchedByManyProjects) ProtoReflect() protoreflect.Message
func (*CLError_WatchedByManyProjects) Reset ¶
func (x *CLError_WatchedByManyProjects) Reset()
func (*CLError_WatchedByManyProjects) String ¶
func (x *CLError_WatchedByManyProjects) String() string
type CLError_WatchedByManyProjects_ ¶
type CLError_WatchedByManyProjects_ struct {
WatchedByManyProjects *CLError_WatchedByManyProjects `protobuf:"bytes,8,opt,name=watched_by_many_projects,json=watchedByManyProjects,proto3,oneof"`
}
type CLMutation ¶
type CLMutation struct { // CL can be modified except the following fields: // * ID // * ExternalID // * EVersion // * UpdateTime CL *CL // contains filtered or unexported fields }
CLMutation encapsulates one CL mutation.
type CLUpdatedEvent ¶
type CLUpdatedEvent struct { Clid int64 `protobuf:"varint,1,opt,name=clid,proto3" json:"clid,omitempty"` Eversion int64 `protobuf:"varint,2,opt,name=eversion,proto3" json:"eversion,omitempty"` // contains filtered or unexported fields }
CLUpdatedEvent is just a CL ID pinned to its latest known EVersion.
func (*CLUpdatedEvent) Descriptor
deprecated
func (*CLUpdatedEvent) Descriptor() ([]byte, []int)
Deprecated: Use CLUpdatedEvent.ProtoReflect.Descriptor instead.
func (*CLUpdatedEvent) GetClid ¶
func (x *CLUpdatedEvent) GetClid() int64
func (*CLUpdatedEvent) GetEversion ¶
func (x *CLUpdatedEvent) GetEversion() int64
func (*CLUpdatedEvent) ProtoMessage ¶
func (*CLUpdatedEvent) ProtoMessage()
func (*CLUpdatedEvent) ProtoReflect ¶
func (x *CLUpdatedEvent) ProtoReflect() protoreflect.Message
func (*CLUpdatedEvent) Reset ¶
func (x *CLUpdatedEvent) Reset()
func (*CLUpdatedEvent) String ¶
func (x *CLUpdatedEvent) String() string
type CLUpdatedEvents ¶
type CLUpdatedEvents struct { Events []*CLUpdatedEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` // contains filtered or unexported fields }
CLUpdatedEvents is a batch of CLUpdatedEvents.
func ToUpdatedEvents ¶
func ToUpdatedEvents(cls ...*CL) *CLUpdatedEvents
ToUpdatedEvents returns CLUpdatedEvents from a slice of CLs.
func (*CLUpdatedEvents) Descriptor
deprecated
func (*CLUpdatedEvents) Descriptor() ([]byte, []int)
Deprecated: Use CLUpdatedEvents.ProtoReflect.Descriptor instead.
func (*CLUpdatedEvents) GetEvents ¶
func (x *CLUpdatedEvents) GetEvents() []*CLUpdatedEvent
func (*CLUpdatedEvents) ProtoMessage ¶
func (*CLUpdatedEvents) ProtoMessage()
func (*CLUpdatedEvents) ProtoReflect ¶
func (x *CLUpdatedEvents) ProtoReflect() protoreflect.Message
func (*CLUpdatedEvents) Reset ¶
func (x *CLUpdatedEvents) Reset()
func (*CLUpdatedEvents) String ¶
func (x *CLUpdatedEvents) String() string
type Dep ¶
type Dep struct { // CLID is internal CV ID of a CL which is the dependency. Clid int64 `protobuf:"varint,1,opt,name=clid,proto3" json:"clid,omitempty"` Kind DepKind `protobuf:"varint,2,opt,name=kind,proto3,enum=cv.internal.changelist.DepKind" json:"kind,omitempty"` // contains filtered or unexported fields }
func (*Dep) Descriptor
deprecated
func (*Dep) ProtoMessage ¶
func (*Dep) ProtoMessage()
func (*Dep) ProtoReflect ¶
func (x *Dep) ProtoReflect() protoreflect.Message
type DepKind ¶
type DepKind int32
func (DepKind) Descriptor ¶
func (DepKind) Descriptor() protoreflect.EnumDescriptor
func (DepKind) EnumDescriptor
deprecated
func (DepKind) Number ¶
func (x DepKind) Number() protoreflect.EnumNumber
func (DepKind) Type ¶
func (DepKind) Type() protoreflect.EnumType
type ExternalID ¶
type ExternalID string
ExternalID is a unique CL ID deterministically constructed based on CL data.
Currently, only Gerrit is supported.
func GobID ¶
func GobID(host string, change int64) (ExternalID, error)
GobID makes an ExternalID for a Gerrit CL.
Host is typically "something-review.googlesource.com". Change is a number, e.g. 2515619 for https://chromium-review.googlesource.com/c/infra/luci/luci-go/+/2515619
func MustGobID ¶
func MustGobID(host string, change int64) ExternalID
MustGobID is like GobID but panics on error.
func (ExternalID) Load ¶
func (eid ExternalID) Load(ctx context.Context) (*CL, error)
Load reads a CL from Datastore.
Returns nil, nil if it doesn't exist.
func (ExternalID) MustCreateIfNotExists ¶
func (eid ExternalID) MustCreateIfNotExists(ctx context.Context) *CL
MustCreateIfNotExists is for use in tests to ensure CL exists.
Panicks on errors.
func (ExternalID) MustURL ¶
func (eid ExternalID) MustURL() string
MustURL is like `URL()` but panic on err.
func (ExternalID) ParseGobID ¶
func (eid ExternalID) ParseGobID() (host string, change int64, err error)
ParseGobID returns Gerrit host and change if this is a GobID.
type FetchInput ¶
type FetchInput struct { // CL of the ChangeList to fetch a snapshot of. // // If CL.ID in the input is 0, it means the CL entity doesn't exist in // Datastore. The cl.ExternalID is always set. CL *CL // Project is the LUCI project to use the scoped account of for the fetch // operation to be performed. Project string // UpdatedHint, if not zero time, is the backend-originating timestamp of // the most recent CL update time. It's sourced by CV by e.g. polling or // PubSub subscription. It is useful to detect and work around backend's // eventual consistency. UpdatedHint time.Time // Requester identifies various scenarios that issued the Fetch invocation. Requester UpdateCLTask_Requester Hint *UpdateCLTask_Hint }
FetchInput an input for UpdaterBackend.Fetch.
It contains fields for what to fetch with meta information.
func NewFetchInput ¶
func NewFetchInput(cl *CL, task *UpdateCLTask) *FetchInput
NewFetchInput returns FetchInput for a given CL and UpdateCLTask.
type Gerrit ¶
type Gerrit struct { // Gerrit host. Host string `protobuf:"bytes,5,opt,name=host,proto3" json:"host,omitempty"` // Info contains subset of ChangeInfo listed below. // // NOTE: keep this list in sync with RemoveUnusedGerritInfo() function. // - number // - owner // - id // - email (may be not set) // - project // - ref // - status // - current_revision // - revisions // - kind // - number // - ref // - created // - commit // - id // - parents // - labels // - optional // - all (only if vote != 0) // - user // - id // - email (may be not set) // - value // - messages // - id // - date // - message // - author // - id // - realauthor // - id // - updated // - created Info *gerrit.ChangeInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` // Files are filenames touched in the current revision. // // It's derived from gerrit.ListFilesResponse, see // https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-files. Files []string `protobuf:"bytes,2,rep,name=files,proto3" json:"files,omitempty"` // Git dependencies of the current revision. GitDeps []*GerritGitDep `protobuf:"bytes,3,rep,name=git_deps,json=gitDeps,proto3" json:"git_deps,omitempty"` // Free-form dependencies. Currently, sourced from CQ-Depend footers. // In the future, this may be derived from Gerrit hashtags, topics, or other // mechanisms. SoftDeps []*GerritSoftDep `protobuf:"bytes,4,rep,name=soft_deps,json=softDeps,proto3" json:"soft_deps,omitempty"` // contains filtered or unexported fields }
func (*Gerrit) Descriptor
deprecated
func (*Gerrit) GetGitDeps ¶
func (x *Gerrit) GetGitDeps() []*GerritGitDep
func (*Gerrit) GetInfo ¶
func (x *Gerrit) GetInfo() *gerrit.ChangeInfo
func (*Gerrit) GetSoftDeps ¶
func (x *Gerrit) GetSoftDeps() []*GerritSoftDep
func (*Gerrit) ProtoMessage ¶
func (*Gerrit) ProtoMessage()
func (*Gerrit) ProtoReflect ¶
func (x *Gerrit) ProtoReflect() protoreflect.Message
type GerritGitDep ¶
type GerritGitDep struct { // Gerrit Change number. Change int64 `protobuf:"varint,1,opt,name=change,proto3" json:"change,omitempty"` // Immediate is set iff this dep is an immediate parent of the Gerrit CL. // // Immediate dep must be submitted before its child. // Non-immediate CLs don't necessarily have to be submitted before: // // for example, for a chain <base> <- A1 <- B1 <- C1 <- D1 // D1's deps are [A,B,C] but only C is immediate, and 1 stands for patchset. // Developer may then swap B,C without re-uploading D (say, to avoid // patchset churn), resulting in a new logical chain: // <base> <- A1 <- C2 <- B2 // \ // <- B1 <- C1 <- D1 // // In this case, Gerrit's related changes for D1 will still return A1,B1,C1, // which CV interprets as C must be landed before D, while B and A should // be landed before D. Immediate bool `protobuf:"varint,2,opt,name=immediate,proto3" json:"immediate,omitempty"` // contains filtered or unexported fields }
GerritGitDep is a dependency discovered via Git child->parent chain for one Gerrit CL.
func (*GerritGitDep) Descriptor
deprecated
func (*GerritGitDep) Descriptor() ([]byte, []int)
Deprecated: Use GerritGitDep.ProtoReflect.Descriptor instead.
func (*GerritGitDep) GetChange ¶
func (x *GerritGitDep) GetChange() int64
func (*GerritGitDep) GetImmediate ¶
func (x *GerritGitDep) GetImmediate() bool
func (*GerritGitDep) ProtoMessage ¶
func (*GerritGitDep) ProtoMessage()
func (*GerritGitDep) ProtoReflect ¶
func (x *GerritGitDep) ProtoReflect() protoreflect.Message
func (*GerritGitDep) Reset ¶
func (x *GerritGitDep) Reset()
func (*GerritGitDep) String ¶
func (x *GerritGitDep) String() string
type GerritSoftDep ¶
type GerritSoftDep struct { // Gerrit host. Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` // Gerrit change number. Change int64 `protobuf:"varint,2,opt,name=change,proto3" json:"change,omitempty"` // contains filtered or unexported fields }
func (*GerritSoftDep) Descriptor
deprecated
func (*GerritSoftDep) Descriptor() ([]byte, []int)
Deprecated: Use GerritSoftDep.ProtoReflect.Descriptor instead.
func (*GerritSoftDep) GetChange ¶
func (x *GerritSoftDep) GetChange() int64
func (*GerritSoftDep) GetHost ¶
func (x *GerritSoftDep) GetHost() string
func (*GerritSoftDep) ProtoMessage ¶
func (*GerritSoftDep) ProtoMessage()
func (*GerritSoftDep) ProtoReflect ¶
func (x *GerritSoftDep) ProtoReflect() protoreflect.Message
func (*GerritSoftDep) Reset ¶
func (x *GerritSoftDep) Reset()
func (*GerritSoftDep) String ¶
func (x *GerritSoftDep) String() string
type MutateCallback ¶
MutateCallback is called by Mutator to mutate the CL inside a transaction.
The function should be idempotent.
If no error is returned, Mutator proceeds saving the CL.
If special ErrStopMutation is returned, Mutator aborts the transaction and returns existing CL read from Datastore and no error. In the special case of Upsert(), the returned CL may actually be nil if CL didn't exist.
If any error is returned other than ErrStopMutation, Mutator aborts the transaction and returns nil CL and the exact same error.
type Mutator ¶
type Mutator struct {
// contains filtered or unexported fields
}
Mutator modifies CLs and guarantees at least once notification of relevant CV components.
All CL entities in production code must be modified via the Mutator.
Mutator notifies 2 CV components: Run and Project managers. In the future, it'll also notify Tryjob Manager.
Run Manager is notified for each IncompleteRuns in the **new** CL version.
Project manager is notified in following cases:
- On the project in the context of which the CL is being modified.
- On the project which owns the Snapshot of the *prior* CL version (if it had any Snapshot).
When the number of notifications is large, Mutator may chose to transactionally enqueue a TQ task, which will send notifications in turn.
func NewMutator ¶
func NewMutator(tqd *tq.Dispatcher, pm pmNotifier, rm rmNotifier, tj tjNotifier) *Mutator
func (*Mutator) Adopt ¶
Adopt starts a mutation of a given CL which was just read from Datastore.
CL must have been loaded in the same Datastore transaction. CL must have been kept read-only after loading. It's OK to modify it after CLMutation is returned.
Adopt exists when there is substantial advantage in batching loading of CL and non-CL entities in a single Datastore RPC. Prefer to use Begin unless performance consideration is critical.
func (*Mutator) Begin ¶
Begin starts mutation of one CL inside an existing transaction in the context of the given LUCI project.
func (*Mutator) BeginBatch ¶
func (m *Mutator) BeginBatch(ctx context.Context, project string, ids common.CLIDs) ([]*CLMutation, error)
BeginBatch starts a batch of CL mutations within the same Datastore transaction.
func (*Mutator) FinalizeBatch ¶
FinalizeBatch finishes a batch of CL mutations within the same Datastore transaction.
The given mutations can originate from either Begin or BeginBatch calls. The only requirement is that they must all originate within the current Datastore transaction.
It also transactionally schedules tasks to cancel stale tryjobs for any CLs in the batch whose minEquivPatchset has changed.
func (*Mutator) Update ¶
func (m *Mutator) Update(ctx context.Context, project string, id common.CLID, clbk MutateCallback) (*CL, error)
Update mutates one CL via a dedicated transaction in the context of the given LUCI project.
If the callback returns ErrStopMutation, then Update returns the read CL entity and nil error.
func (*Mutator) Upsert ¶
func (m *Mutator) Upsert(ctx context.Context, project string, eid ExternalID, clbk MutateCallback) (*CL, error)
Upsert creates new or updates existing CL via a dedicated transaction in the context of the given LUCI project.
Prefer to use Update if CL ID is known.
If CL didn't exist before, the callback is provided a CL with temporarily reserved ID. Until Upsert returns with success, this ID is not final, but it's fine to use it in other entities saved within the same transaction.
If CL didn't exist before and the callback returns ErrStopMutation, then Upsert returns (nil, nil).
type Snapshot ¶
type Snapshot struct { // The timestamp from external system. // Used to determine if re-querying external system is needed. ExternalUpdateTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=external_update_time,json=externalUpdateTime,proto3" json:"external_update_time,omitempty"` // LUCI project in the context of which this snapshot was saved. // // Since a CL isn't a resource of CV, CV can't infer whether specific LUCI // project has access to a CL w/o re-querying Gerrit and effectively // recomputing the snapshot. LuciProject string `protobuf:"bytes,2,opt,name=luci_project,json=luciProject,proto3" json:"luci_project,omitempty"` // Resolved dependencies of a CL. Deps []*Dep `protobuf:"bytes,3,rep,name=deps,proto3" json:"deps,omitempty"` // Patchset is incremental number of the latest patchset (aka revision). Patchset int32 `protobuf:"varint,4,opt,name=patchset,proto3" json:"patchset,omitempty"` // MinEquivalentPatchset is the smallest and hence the earliest patchset // which is code-wise equivalent to the latest one. // // See gerrit.EquivalentPatchsetRange function for details. // // CV tracks this to determine which prior tryjobs can be re-used and which // can be canceled. MinEquivalentPatchset int32 `` /* 127-byte string literal not displayed */ // If set, indicates problems while ingesting CL into CV, which ought to be // communicated back to user. Errors []*CLError `protobuf:"bytes,6,rep,name=errors,proto3" json:"errors,omitempty"` // Outdated if set means Snapshot must be considered likely outdated due to // recent CV mutations. // // In particular, Project Manager does not act on the CLs with .Outdated set. Outdated *Snapshot_Outdated `protobuf:"bytes,7,opt,name=outdated,proto3" json:"outdated,omitempty"` // Metadata is an ordered list of key-value pairs, which may later be // interpreted by CV guts. // // For example, // // [("No-Tree-Checks", "True"), ("NOTRY", "TRUE")]. // // In case of Gerrit CLs, these are extracted from CL descriptions, // The Git-Footer-Style keys are normalized. // The values are stripped from beginning and trailing whitespace. Metadata []*StringPair `protobuf:"bytes,8,rep,name=metadata,proto3" json:"metadata,omitempty"` // CL-kind specific data. // // Types that are assignable to Kind: // // *Snapshot_Gerrit Kind isSnapshot_Kind `protobuf_oneof:"kind"` // contains filtered or unexported fields }
Snapshot stores a snapshot of CL info as seen by CV at a certain time.
When stored in CL entity, represents latest known Gerrit data. When stored in RunCL entity, represents data pertaining to a fixed patchset.
func (*Snapshot) Descriptor
deprecated
func (*Snapshot) GetExternalUpdateTime ¶
func (x *Snapshot) GetExternalUpdateTime() *timestamppb.Timestamp
func (*Snapshot) GetLuciProject ¶
func (*Snapshot) GetMetadata ¶
func (x *Snapshot) GetMetadata() []*StringPair
func (*Snapshot) GetMinEquivalentPatchset ¶
func (*Snapshot) GetOutdated ¶
func (x *Snapshot) GetOutdated() *Snapshot_Outdated
func (*Snapshot) GetPatchset ¶
func (*Snapshot) IsSubmittable ¶
IsSubmittable returns whether the change has been approved by the project submit rules.
func (*Snapshot) IsSubmitted ¶
IsSubmitted returns whether the change has been submitted.
func (*Snapshot) OwnerIdentity ¶
OwnerIdentity is the identity of a user owning this CL.
Snapshot must not be nil.
func (*Snapshot) PanicIfNotValid ¶
func (s *Snapshot) PanicIfNotValid()
PanicIfNotValid checks that Snapshot stored has required fields set.
func (*Snapshot) ProtoMessage ¶
func (*Snapshot) ProtoMessage()
func (*Snapshot) ProtoReflect ¶
func (x *Snapshot) ProtoReflect() protoreflect.Message
type Snapshot_Gerrit ¶
type Snapshot_Gerrit struct {
Gerrit *Gerrit `protobuf:"bytes,11,opt,name=gerrit,proto3,oneof"`
}
type Snapshot_Outdated ¶
type Snapshot_Outdated struct {
// contains filtered or unexported fields
}
Outdated establishes conditions for refreshing Snapshot after CV mutations.
func (*Snapshot_Outdated) Descriptor
deprecated
func (*Snapshot_Outdated) Descriptor() ([]byte, []int)
Deprecated: Use Snapshot_Outdated.ProtoReflect.Descriptor instead.
func (*Snapshot_Outdated) ProtoMessage ¶
func (*Snapshot_Outdated) ProtoMessage()
func (*Snapshot_Outdated) ProtoReflect ¶
func (x *Snapshot_Outdated) ProtoReflect() protoreflect.Message
func (*Snapshot_Outdated) Reset ¶
func (x *Snapshot_Outdated) Reset()
func (*Snapshot_Outdated) String ¶
func (x *Snapshot_Outdated) String() string
type StringPair ¶
type StringPair struct { Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` // contains filtered or unexported fields }
A string key-value pair.
func (*StringPair) Descriptor
deprecated
func (*StringPair) Descriptor() ([]byte, []int)
Deprecated: Use StringPair.ProtoReflect.Descriptor instead.
func (*StringPair) GetKey ¶
func (x *StringPair) GetKey() string
func (*StringPair) GetValue ¶
func (x *StringPair) GetValue() string
func (*StringPair) ProtoMessage ¶
func (*StringPair) ProtoMessage()
func (*StringPair) ProtoReflect ¶
func (x *StringPair) ProtoReflect() protoreflect.Message
func (*StringPair) Reset ¶
func (x *StringPair) Reset()
func (*StringPair) String ¶
func (x *StringPair) String() string
type UpdateCLTask ¶
type UpdateCLTask struct { LuciProject string `protobuf:"bytes,1,opt,name=luci_project,json=luciProject,proto3" json:"luci_project,omitempty"` // At least one of internal or external ID must be given. Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"` // internal CLID ExternalId string `protobuf:"bytes,3,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"` // Requester identifies various scenarios that enqueue UpdateCLTask(s). // // This is used to track UpdateCLTask(s) by the requester for monitoring // purposes. Requester UpdateCLTask_Requester `protobuf:"varint,5,opt,name=requester,proto3,enum=cv.internal.changelist.UpdateCLTask_Requester" json:"requester,omitempty"` // True if the UpdateCLTask was enqueued to resolve a dependency. IsForDep bool `protobuf:"varint,6,opt,name=is_for_dep,json=isForDep,proto3" json:"is_for_dep,omitempty"` // Hint provides various hints for the snapshot to be fetched. Hint *UpdateCLTask_Hint `protobuf:"bytes,7,opt,name=hint,proto3" json:"hint,omitempty"` // contains filtered or unexported fields }
UpdateCLTask is for updating a single CL.
Queue: "update-cl".
func (*UpdateCLTask) Descriptor
deprecated
func (*UpdateCLTask) Descriptor() ([]byte, []int)
Deprecated: Use UpdateCLTask.ProtoReflect.Descriptor instead.
func (*UpdateCLTask) GetExternalId ¶
func (x *UpdateCLTask) GetExternalId() string
func (*UpdateCLTask) GetHint ¶
func (x *UpdateCLTask) GetHint() *UpdateCLTask_Hint
func (*UpdateCLTask) GetId ¶
func (x *UpdateCLTask) GetId() int64
func (*UpdateCLTask) GetIsForDep ¶
func (x *UpdateCLTask) GetIsForDep() bool
func (*UpdateCLTask) GetLuciProject ¶
func (x *UpdateCLTask) GetLuciProject() string
func (*UpdateCLTask) GetRequester ¶
func (x *UpdateCLTask) GetRequester() UpdateCLTask_Requester
func (*UpdateCLTask) ProtoMessage ¶
func (*UpdateCLTask) ProtoMessage()
func (*UpdateCLTask) ProtoReflect ¶
func (x *UpdateCLTask) ProtoReflect() protoreflect.Message
func (*UpdateCLTask) Reset ¶
func (x *UpdateCLTask) Reset()
func (*UpdateCLTask) String ¶
func (x *UpdateCLTask) String() string
type UpdateCLTask_Hint ¶
type UpdateCLTask_Hint struct { // The external update time of the Snapshot to fetch. ExternalUpdateTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=external_update_time,json=externalUpdateTime,proto3" json:"external_update_time,omitempty"` // The meta rev ID of the Snapshot to fetch. MetaRevId string `protobuf:"bytes,2,opt,name=meta_rev_id,json=metaRevId,proto3" json:"meta_rev_id,omitempty"` // contains filtered or unexported fields }
func (*UpdateCLTask_Hint) Descriptor
deprecated
func (*UpdateCLTask_Hint) Descriptor() ([]byte, []int)
Deprecated: Use UpdateCLTask_Hint.ProtoReflect.Descriptor instead.
func (*UpdateCLTask_Hint) GetExternalUpdateTime ¶
func (x *UpdateCLTask_Hint) GetExternalUpdateTime() *timestamppb.Timestamp
func (*UpdateCLTask_Hint) GetMetaRevId ¶
func (x *UpdateCLTask_Hint) GetMetaRevId() string
func (*UpdateCLTask_Hint) ProtoMessage ¶
func (*UpdateCLTask_Hint) ProtoMessage()
func (*UpdateCLTask_Hint) ProtoReflect ¶
func (x *UpdateCLTask_Hint) ProtoReflect() protoreflect.Message
func (*UpdateCLTask_Hint) Reset ¶
func (x *UpdateCLTask_Hint) Reset()
func (*UpdateCLTask_Hint) String ¶
func (x *UpdateCLTask_Hint) String() string
type UpdateCLTask_Requester ¶
type UpdateCLTask_Requester int32
const ( UpdateCLTask_REQUESTER_CLASS_UNSPECIFIED UpdateCLTask_Requester = 0 UpdateCLTask_INCR_POLL_MATCHED UpdateCLTask_Requester = 1 UpdateCLTask_FULL_POLL_MATCHED UpdateCLTask_Requester = 2 UpdateCLTask_FULL_POLL_UNMATCHED UpdateCLTask_Requester = 3 UpdateCLTask_PUBSUB_POLL UpdateCLTask_Requester = 4 UpdateCLTask_CL_PURGER UpdateCLTask_Requester = 5 UpdateCLTask_DEP_CL_TRIGGERER UpdateCLTask_Requester = 12 UpdateCLTask_RPC_ADMIN UpdateCLTask_Requester = 6 UpdateCLTask_RUN_POKE UpdateCLTask_Requester = 7 UpdateCLTask_RUN_REMOVAL UpdateCLTask_Requester = 8 UpdateCLTask_RESET_CL_TRIGGER UpdateCLTask_Requester = 11 UpdateCLTask_UPDATE_CONFIG UpdateCLTask_Requester = 10 )
func (UpdateCLTask_Requester) Descriptor ¶
func (UpdateCLTask_Requester) Descriptor() protoreflect.EnumDescriptor
func (UpdateCLTask_Requester) Enum ¶
func (x UpdateCLTask_Requester) Enum() *UpdateCLTask_Requester
func (UpdateCLTask_Requester) EnumDescriptor
deprecated
func (UpdateCLTask_Requester) EnumDescriptor() ([]byte, []int)
Deprecated: Use UpdateCLTask_Requester.Descriptor instead.
func (UpdateCLTask_Requester) Number ¶
func (x UpdateCLTask_Requester) Number() protoreflect.EnumNumber
func (UpdateCLTask_Requester) String ¶
func (x UpdateCLTask_Requester) String() string
func (UpdateCLTask_Requester) Type ¶
func (UpdateCLTask_Requester) Type() protoreflect.EnumType
type UpdateFields ¶
type UpdateFields struct { // Snapshot overwrites existing CL snapshot if newer according to its // .ExternalUpdateTime. Snapshot *Snapshot // ApplicableConfig overwrites existing CL ApplicableConfig if semantically // different from existing one. ApplicableConfig *ApplicableConfig // AddDependentMeta adds or overwrites metadata per LUCI project in CL AsDepMeta. // Doesn't affect metadata stored for projects not referenced here. AddDependentMeta *Access // DelAccess deletes Access records for the given projects. DelAccess []string }
UpdateFields defines what parts of CL to update.
At least one field must be specified.
func (UpdateFields) Apply ¶
func (u UpdateFields) Apply(cl *CL, backend UpdaterBackend) (changed, changedSnapshot bool)
Apply applies the UpdatedFields to a given CL.
func (UpdateFields) IsEmpty ¶
func (u UpdateFields) IsEmpty() bool
IsEmpty returns true if no updates are necessary.
type Updater ¶
type Updater struct {
// contains filtered or unexported fields
}
Updater knows how to update CLs from relevant backend (e.g. Gerrit), notifying other CV parts as needed.
func NewUpdater ¶
func NewUpdater(tqd *tq.Dispatcher, m *Mutator) *Updater
NewUpdater creates a new Updater.
Starts without backends, but they ought to be added via RegisterBackend().
func (*Updater) RegisterBackend ¶
func (u *Updater) RegisterBackend(b UpdaterBackend)
RegisterBackend registers a backend.
Panics if backend for the same kind is already registered.
func (*Updater) ResolveAndScheduleDepsUpdate ¶
func (u *Updater) ResolveAndScheduleDepsUpdate(ctx context.Context, luciProject string, deps map[ExternalID]DepKind, requester UpdateCLTask_Requester) ([]*Dep, error)
ResolveAndScheduleDepsUpdate resolves deps, creating new CL entities as necessary, and schedules an update task for each dep which needs an update.
It's meant to be used by the Updater backends.
Returns a sorted slice of Deps by their CL ID, ready to be stored as CL.Snapshot.Deps.
func (*Updater) Schedule ¶
func (u *Updater) Schedule(ctx context.Context, payload *UpdateCLTask) error
Schedule dispatches a TQ task. It should be used instead of the direct tq.AddTask to allow for consistent de-duplication.
func (*Updater) ScheduleBatch ¶
func (u *Updater) ScheduleBatch(ctx context.Context, luciProject string, cls []*CL, requester UpdateCLTask_Requester) error
ScheduleBatch schedules update of several CLs.
If called in a transaction, enqueues exactly one TQ task transactionally. This allows to write 1 Datastore entity during a transaction instead of N entities if Schedule() was used for each CL.
Otherwise, enqueues 1 TQ task per CL non-transactionally and in parallel.
func (*Updater) ScheduleDelayed ¶
func (u *Updater) ScheduleDelayed(ctx context.Context, payload *UpdateCLTask, delay time.Duration) error
ScheduleDelayed is the same as Schedule but with a delay.
func (*Updater) TestingForceUpdate ¶
func (u *Updater) TestingForceUpdate(ctx context.Context, task *UpdateCLTask) error
TestingForceUpdate runs the CL Updater synchronously.
For use in tests only. Production code should use Schedule() to benefit from task de-duplication.
TODO(crbug/1284393): revisit the usefulness of the sync refresh after consistency-on-demand is provided by Gerrit.
type UpdaterBackend ¶
type UpdaterBackend interface { // Kind identifies the backend. // // It's also the first part of the CL's ExternalID, e.g. "gerrit". // Must not contain a slash. Kind() string // LookupApplicableConfig returns the latest ApplicableConfig for the previously // saved CL. // // See CL.ApplicableConfig field doc for more details. Roughly, it finds which // LUCI projects are configured to watch this CL. // // Updater calls LookupApplicableConfig() before Fetch() in order to avoid // the unnecessary Fetch() call entirely, e.g. if the CL is up to date or if // the CL is definitely not watched by a specific LUCI project. // // Returns non-nil ApplicableConfig normally. // Returns nil ApplicableConfig if the previously saved CL state isn't // sufficient to confidently determine the ApplicableConfig. LookupApplicableConfig(ctx context.Context, saved *CL) (*ApplicableConfig, error) // Fetch fetches the CL in the context of a given project. Fetch(ctx context.Context, input *FetchInput) (UpdateFields, error) // HasChanged decides whether the CL in the backend has changed from existing // snapshot in LUCI CV. HasChanged(cvCurrent, backendCurrent *Snapshot) bool // TQErrorSpec allows customizing logging and error TQ-specific handling. // // For example, Gerrit backend may wish to retry out of quota errors without // logging detailed stacktrace. TQErrorSpec() common.TQIfy }
UpdaterBackend abstracts out fetching CL details from code review backend.