// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using EpicGames.Horde.Commits; using EpicGames.Horde.Jobs; using EpicGames.Horde.Jobs.Templates; using EpicGames.Horde.Logs; using EpicGames.Horde.Streams; using EpicGames.Horde.Users; #pragma warning disable CA2227 // Change collections to be read-only namespace EpicGames.Horde.Issues { /// /// The severity of an issue /// public enum IssueSeverity { /// /// Unspecified severity /// Unspecified, /// /// This error represents a warning /// Warning, /// /// This issue represents an error /// Error, } /// /// Identifies a particular changelist and job /// public class GetIssueStepResponse { /// /// The changelist number /// [Obsolete("Use Commit instead")] public int Change { get => _change ?? _commitId?.TryGetPerforceChange() ?? -1; set => _change = value; } int? _change; /// /// The commit for this step /// public CommitIdWithOrder CommitId { get => _commitId ?? CommitIdWithOrder.FromPerforceChange(_change) ?? CommitIdWithOrder.Empty; set => _commitId = value; } CommitIdWithOrder? _commitId; /// /// Severity of the issue in this step /// public IssueSeverity Severity { get; set; } /// /// Name of the job containing this step /// public string JobName { get; set; } = String.Empty; /// /// The unique job id /// public JobId JobId { get; set; } /// /// The unique batch id /// public JobStepBatchId BatchId { get; set; } /// /// The unique step id /// public JobStepId StepId { get; set; } /// /// Time at which the step ran /// public DateTime StepTime { get; set; } /// /// The unique log id /// public LogId? LogId { get; set; } } /// /// Trace of a set of node failures across multiple steps /// public class GetIssueSpanResponse { /// /// Unique id of this span /// public string Id { get; set; } = String.Empty; /// /// The template containing this step /// public TemplateId TemplateId { get; set; } /// /// Name of the step /// public string Name { get; set; } = String.Empty; /// /// Workflow that this span belongs to /// public WorkflowId? WorkflowId { get; set; } /// /// The previous build /// public GetIssueStepResponse? LastSuccess { get; set; } /// /// The failing builds for a particular event /// public List Steps { get; set; } = new List(); /// /// The following successful build /// public GetIssueStepResponse? NextSuccess { get; set; } } /// /// Information about a particular step /// public class GetIssueStreamResponse { /// /// Unique id of the stream /// public StreamId StreamId { get; set; } /// /// Minimum commit affected by this issue (ie. last successful build) /// [Obsolete("Use MinCommitId instead")] public int? MinChange { get => _minChange ?? _minCommitId?.GetPerforceChangeOrMinusOne(); set => _minChange = value; } int? _minChange; /// /// Maximum commit affected by this issue (ie. next successful build) /// [Obsolete("Use MaxCommitId instead")] public int? MaxChange { get => _maxChange ?? _maxCommitId?.GetPerforceChangeOrMinusOne(); set => _maxChange = value; } int? _maxChange; /// /// Minimum changelist affected by this issue (ie. last successful build) /// public CommitIdWithOrder? MinCommitId { get => _minCommitId ?? CommitIdWithOrder.FromPerforceChange(_minChange); set => _minCommitId = value; } CommitIdWithOrder? _minCommitId; /// /// Maximum changelist affected by this issue (ie. next successful build) /// public CommitIdWithOrder? MaxCommitId { get => _maxCommitId ?? CommitIdWithOrder.FromPerforceChange(_maxChange); set => _maxCommitId = value; } CommitIdWithOrder? _maxCommitId; /// /// Map of steps to (event signature id -> trace id) /// public List Nodes { get; set; } = new List(); } /// /// Outcome of a particular build /// public enum IssueBuildOutcome { /// /// Unknown outcome /// Unknown, /// /// Build succeeded /// Success, /// /// Build failed /// Error, /// /// Build finished with warnings /// Warning, } /// /// Information about a template affected by an issue /// public class GetIssueAffectedTemplateResponse { /// /// The template id /// public TemplateId TemplateId { get; set; } /// /// The template name /// public string TemplateName { get; set; } = String.Empty; /// /// Whether it has been resolved or not /// public bool Resolved { get; set; } /// /// The issue severity of the affected template /// public IssueSeverity Severity { get; set; } } /// /// Summary for the state of a stream in an issue /// public class GetIssueAffectedStreamResponse { /// /// Id of the stream /// public StreamId StreamId { get; set; } /// /// Name of the stream /// public string StreamName { get; set; } = String.Empty; /// /// Whether the issue has been resolved in this stream /// public bool Resolved { get; set; } /// /// The affected templates /// public List AffectedTemplates { get; set; } = new List(); /// /// List of affected template ids /// public List TemplateIds { get; set; } = new List(); /// /// List of resolved template ids /// public List ResolvedTemplateIds { get; set; } = new List(); /// /// List of unresolved template ids /// public List UnresolvedTemplateIds { get; set; } = new List(); } /// /// Stores information about a build health issue /// public class GetIssueResponse { /// /// The unique object id /// public int Id { get; set; } /// /// Time at which the issue was created /// public DateTime CreatedAt { get; set; } /// /// Time at which the issue was retrieved /// public DateTime RetrievedAt { get; set; } /// /// The associated project for the issue /// public string? Project { get; set; } /// /// The summary text for this issue /// public string Summary { get; set; } = String.Empty; /// /// Detailed description text /// public string? Description { get; set; } /// /// Description of the current fingerprint used for issue identification /// public string? FingerprintDescription { get; set; } /// /// Severity of this issue /// public IssueSeverity Severity { get; set; } /// /// Whether the issue is promoted /// public bool Promoted { get; set; } /// /// Owner of the issue [DEPRECATED] /// public string? Owner { get; set; } /// /// User id of the owner [DEPRECATED] /// public string? OwnerId { get; set; } /// /// Owner of the issue /// public GetThinUserInfoResponse? OwnerInfo { get; set; } /// /// User that nominated the current owner [DEPRECATED] /// public string? NominatedBy { get; set; } /// /// Owner of the issue /// public GetThinUserInfoResponse? NominatedByInfo { get; set; } /// /// Time that the issue was acknowledged /// public DateTime? AcknowledgedAt { get; set; } /// /// Perforce changelist that fixed this issue /// public int? FixChange { get => _fixChange ?? _fixCommitId?.GetPerforceChangeOrMinusOne(); set => _fixChange = value; } int? _fixChange; /// /// Commit that fixed this issue /// public CommitId? FixCommitId { get => _fixCommitId ?? CommitId.FromPerforceChange(_fixChange); set => _fixCommitId = value; } CommitId? _fixCommitId; /// /// Whether the issue is marked fixed as a systemic issue /// public bool FixSystemic { get => _fixSystemic ?? (_fixChange < 0); set => _fixSystemic = value; } bool? _fixSystemic; /// /// Time at which the issue was resolved /// public DateTime? ResolvedAt { get; set; } /// /// Name of the user that resolved the issue [DEPRECATED] /// public string? ResolvedBy { get; set; } /// /// User id of the person that resolved the issue [DEPRECATED] /// public string? ResolvedById { get; set; } /// /// User that resolved the issue /// public GetThinUserInfoResponse? ResolvedByInfo { get; set; } /// /// Time at which the issue was verified /// public DateTime? VerifiedAt { get; set; } /// /// Time that the issue was last seen /// public DateTime LastSeenAt { get; set; } /// /// List of stream paths affected by this issue /// public List Streams { get; set; } = new List(); /// /// List of affected stream ids /// public List ResolvedStreams { get; set; } = new List(); /// /// List of unresolved streams /// public List UnresolvedStreams { get; set; } = new List(); /// /// List of affected streams /// public List AffectedStreams { get; set; } = new List(); /// /// Most likely suspects for causing this issue [DEPRECATED] /// public List? PrimarySuspects { get; set; } /// /// User ids of the most likely suspects [DEPRECATED] /// public List? PrimarySuspectIds { get; set; } /// /// Most likely suspects for causing this issue /// public List PrimarySuspectsInfo { get; set; } = new List(); /// /// Whether to show alerts for this issue /// public bool ShowDesktopAlerts { get; set; } /// /// Key for this issue in external issue tracker /// public string? ExternalIssueKey { get; set; } /// /// User who quarantined the issue /// public GetThinUserInfoResponse? QuarantinedByUserInfo { get; set; } /// /// The UTC time when the issue was quarantined /// public DateTime? QuarantineTimeUtc { get; set; } /// /// User who force closed the issue /// public GetThinUserInfoResponse? ForceClosedByUserInfo { get; set; } /// /// The workflow thread url for this issue /// public Uri? WorkflowThreadUrl { get; set; } } /// /// Information about a span within an issue /// public class FindIssueSpanResponse { /// /// Unique id of this span /// public string Id { get; set; } = String.Empty; /// /// The template containing this step /// public string TemplateId { get; set; } = String.Empty; /// /// Name of the step /// public string Name { get; set; } = String.Empty; /// /// Workflow for this span /// public WorkflowId? WorkflowId { get; set; } /// /// The previous build /// public GetIssueStepResponse? LastSuccess { get; set; } /// /// The following successful build /// public GetIssueStepResponse? NextSuccess { get; set; } } /// /// Stores information about a build health issue /// public class FindIssueResponse { /// /// The unique object id /// public int Id { get; set; } /// /// Time at which the issue was created /// public DateTime CreatedAt { get; set; } /// /// Time at which the issue was retrieved /// public DateTime RetrievedAt { get; set; } /// /// The associated project for the issue /// public string? Project { get; set; } /// /// The summary text for this issue /// public string Summary { get; set; } = String.Empty; /// /// Detailed description text /// public string? Description { get; set; } /// /// Severity of this issue /// public IssueSeverity Severity { get; set; } /// /// Severity of this issue in the stream /// public IssueSeverity? StreamSeverity { get; set; } /// /// Whether the issue is promoted /// public bool Promoted { get; set; } /// /// Owner of the issue /// public GetThinUserInfoResponse? Owner { get; set; } /// /// Owner of the issue /// public GetThinUserInfoResponse? NominatedBy { get; set; } /// /// Time that the issue was acknowledged /// public DateTime? AcknowledgedAt { get; set; } /// /// Changelist that fixed this issue /// public int? FixChange { get => _fixChange ?? ((_fixSystemic ?? false) ? -1 : _fixCommitId?.GetPerforceChangeOrMinusOne()); set => _fixChange = value; } int? _fixChange; /// /// Changelist that fixed this issue /// public CommitId? FixCommitId { get => _fixCommitId ?? CommitId.FromPerforceChange(_fixChange); set => _fixCommitId = value; } CommitId? _fixCommitId; /// /// Whether the issue is marked fixed as a systemic issue /// public bool FixSystemic { get => _fixSystemic ?? (_fixChange < 0); set => _fixSystemic = value; } bool? _fixSystemic; /// /// Time at which the issue was resolved /// public DateTime? ResolvedAt { get; set; } /// /// User that resolved the issue /// public GetThinUserInfoResponse? ResolvedBy { get; set; } /// /// Time at which the issue was verified /// public DateTime? VerifiedAt { get; set; } /// /// Time that the issue was last seen /// public DateTime LastSeenAt { get; set; } /// /// Spans for this issue /// public List? Spans { get; set; } /// /// Key for this issue in external issue tracker /// public string? ExternalIssueKey { get; set; } /// /// User who quarantined the issue /// public GetThinUserInfoResponse? QuarantinedBy { get; set; } /// /// The UTC time when the issue was quarantined /// public DateTime? QuarantineTimeUtc { get; set; } /// /// The workflow thread url for this issue /// public Uri? WorkflowThreadUrl { get; set; } /// /// Workflows for which this issue is open /// public List? OpenWorkflows { get; set; } } /// /// Request an issue to be updated /// public class UpdateIssueRequest { /// /// Summary of the issue /// public string? Summary { get; set; } /// /// Description of the issue /// public string? Description { get; set; } /// /// Whether the issue is promoted or not /// public bool? Promoted { get; set; } /// /// New user id for owner of the issue, can be cleared by passing empty string /// public string? OwnerId { get; set; } /// /// User id that nominated the new owner /// public string? NominatedById { get; set; } /// /// Whether the issue has been acknowledged /// public bool? Acknowledged { get; set; } /// /// Whether the user has declined this issue /// public bool? Declined { get; set; } /// /// The change at which the issue is claimed fixed. 0 = not fixed, -1 = systemic issue. /// [Obsolete("Use FixCommitId and FixSystemic instead")] public int? FixChange { get => _fixChange ?? ((_fixSystemic ?? false) ? -1 : _fixCommitId?.GetPerforceChangeOrMinusOne()); set => _fixChange = value; } int? _fixChange; /// /// The change at which the issue is claimed fixed. """" = not fixed. /// public CommitId? FixCommitId { get => _fixCommitId ?? ((_fixChange < 0)? null : (_fixChange == 0)? CommitId.Empty : CommitId.FromPerforceChange(_fixChange)); set => _fixCommitId = value; } CommitId? _fixCommitId; /// /// Set to mark the issue as fixed systemically /// public bool FixSystemic { get => _fixSystemic ?? (_fixChange < 0); set => _fixSystemic = value; } bool? _fixSystemic; /// /// Whether the issue should be marked as resolved /// public bool? Resolved { get; set; } /// /// List of spans to add to this issue /// public List? AddSpans { get; set; } /// /// List of spans to remove from this issue /// public List? RemoveSpans { get; set; } /// /// A key to issue in external tracker /// public string? ExternalIssueKey { get; set; } /// /// Id of user quarantining issue /// public string? QuarantinedById { get; set; } /// /// Id of user who is forcibly closing this issue, skipping verification checks. This is useful for when a failing step has been removed for example /// public string? ForceClosedById { get; set; } } /// /// External issue project information /// public class GetExternalIssueProjectResponse { /// /// The project key /// public string ProjectKey { get; set; } = String.Empty; /// /// The name of the project /// public string Name { get; set; } = String.Empty; /// /// The id of the project /// public string Id { get; set; } = String.Empty; /// /// component id => name /// public Dictionary Components { get; set; } = new Dictionary(); /// /// IssueType id => name /// public Dictionary IssueTypes { get; set; } = new Dictionary(); } /// /// Marks an issue as fixed by another user. Designed for use from a Perforce trigger. /// public class MarkFixedViaPerforceRequest { /// /// Name of the user that fixed the issue /// public string UserName { get; set; } = String.Empty; /// /// Change that fixed the issue /// public int FixChange { get; set; } } /// /// Request an issue to be created on external issue tracking system /// public class CreateExternalIssueRequest { /// /// Horde issue which is linked to external issue /// public int IssueId { get; set; } = 0; /// /// StreamId of a stream with this issue /// public string StreamId { get; set; } = String.Empty; /// /// Summary text for external issue /// public string Summary { get; set; } = String.Empty; /// /// External issue project id /// public string ProjectId { get; set; } = String.Empty; /// /// External issue component id /// public string ComponentId { get; set; } = String.Empty; /// /// External issue type id /// public string IssueTypeId { get; set; } = String.Empty; /// /// Optional description text for external issue /// public string? Description { get; set; } /// /// Optional link to issue on Horde /// public string? HordeIssueLink { get; set; } } /// /// Response for externally created issue /// public class CreateExternalIssueResponse { /// /// External issue key /// public string Key { get; set; } /// /// Link to issue on external tracking site /// public string? Link { get; set; } /// /// Constructor /// /// /// public CreateExternalIssueResponse(string key, string? link) { Key = key; Link = link; } } /// /// External issue response object /// public class GetExternalIssueResponse { /// /// The external issue key /// public string Key { get; set; } = String.Empty; /// /// The issue link on external tracking site /// public string? Link { get; set; } /// /// The issue status name, "To Do", "In Progress", etc /// public string? StatusName { get; set; } /// /// The issue resolution name, "Fixed", "Closed", etc /// public string? ResolutionName { get; set; } /// /// The issue priority name, "1 - Critical", "2 - Major", etc /// public string? PriorityName { get; set; } /// /// The current assignee's user name /// public string? AssigneeName { get; set; } /// /// The current assignee's display name /// public string? AssigneeDisplayName { get; set; } /// /// The current assignee's email address /// public string? AssigneeEmailAddress { get; set; } } }