< Summary

Information
Class: Services.ApiServices.TelegramBotApi.DeployCommit
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/TelegramBotApi/DeployNotification.cs
Line coverage
100%
Covered lines: 1
Uncovered lines: 0
Coverable lines: 1
Total lines: 83
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Sha()100%11100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/TelegramBotApi/DeployNotification.cs

#LineLine coverage
 1using System.Text.RegularExpressions;
 2
 3namespace Services.ApiServices.TelegramBotApi;
 4
 5[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
 6public enum DeployStage
 7{
 8    Started,
 9    Finished,
 10    Failed
 11}
 12
 13/// <summary>Коммит из обновления (первый родитель ветки деплоя: прямые коммиты и merge-коммиты PR).</summary>
 14914public sealed record DeployCommit(string Sha, string? Author, string? Subject, string? Body);
 15
 16/// <summary>Событие деплоя, которое присылает workflow GitHub Actions.</summary>
 17public sealed record DeployEvent(
 18    DeployStage Stage,
 19    string Sha,
 20    string? CommitDate,
 21    string? Repository,
 22    string? RunUrl,
 23    string? Actor,
 24    int? DurationSeconds,
 25    IReadOnlyList<DeployCommit> Commits);
 26
 27/// <summary>Изменение для списка «что в обновлении»: заголовок, коммит и (если есть) номер PR.</summary>
 28public sealed record DeployChange(string Title, string Sha, int? PullRequest);
 29
 30/// <summary>
 31/// Превращает коммиты деплоя в список изменений: merge-коммит PR заменяется заголовком PR,
 32/// squash-коммит «заголовок (#N)» — номером PR; технические merge веток пропускаются.
 33/// </summary>
 34public static partial class DeployChangeParser
 35{
 36    [GeneratedRegex(@"^Merge pull request #(?<n>\d+)\b", RegexOptions.IgnoreCase)]
 37    private static partial Regex MergePullRequest();
 38
 39    [GeneratedRegex(@"\s*\(#(?<n>\d+)\)\s*$")]
 40    private static partial Regex SquashSuffix();
 41
 42    [GeneratedRegex(@"^Merge (branch|remote-tracking branch|tag)\b", RegexOptions.IgnoreCase)]
 43    private static partial Regex TechnicalMerge();
 44
 45    public static IReadOnlyList<DeployChange> Parse(IEnumerable<DeployCommit> commits)
 46    {
 47        var result = new List<DeployChange>();
 48        var seenPr = new HashSet<int>();
 49        foreach (var commit in commits)
 50        {
 51            var subject = (commit.Subject ?? "").Trim();
 52            if (subject.Length == 0) continue;
 53
 54            var merge = MergePullRequest().Match(subject);
 55            if (merge.Success)
 56            {
 57                var pr = int.Parse(merge.Groups["n"].Value);
 58                if (!seenPr.Add(pr)) continue;
 59                var title = FirstLine(commit.Body);
 60                result.Add(new DeployChange(string.IsNullOrWhiteSpace(title) ? subject : title, commit.Sha, pr));
 61                continue;
 62            }
 63
 64            if (TechnicalMerge().IsMatch(subject)) continue;
 65
 66            var squash = SquashSuffix().Match(subject);
 67            if (squash.Success)
 68            {
 69                var pr = int.Parse(squash.Groups["n"].Value);
 70                if (!seenPr.Add(pr)) continue;
 71                result.Add(new DeployChange(subject[..squash.Index].Trim(), commit.Sha, pr));
 72                continue;
 73            }
 74
 75            result.Add(new DeployChange(subject, commit.Sha, null));
 76        }
 77
 78        return result;
 79    }
 80
 81    private static string? FirstLine(string? text) =>
 82        text?.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).FirstOrDefault();
 83}

Methods/Properties

get_Sha()