/// <summary> /// Archives all revisions that are marked as "archive pending". If options DeleteTags is set this will remove tags from GitLag. /// If Deleting is successfull (deleted or didn't exist) then the revision is marked as "Archived". /// </summary> private static void ArchivePendingRevisions(RunArchiverVerb options, ISessionFactory sessionFactory, GitLabApi gitLab) { Console.WriteLine("Archiving Pending Revisions"); var tagNameFormat = "reviewer/{0}/r{1}/{2}"; using (var session = sessionFactory.OpenSession()) { var pendingRevisions = session.Query <ReviewRevision>().Where(x => x.ArchiveState == (int)ArchiveState.ArchivePending).ToArray(); int counter = 0; foreach (var revision in pendingRevisions) { counter++; Console.WriteLine($"[{counter}/{pendingRevisions.Length}] Clearing Tags for {revision.ReviewId.ProjectId}/{revision.ReviewId.ReviewId}"); var baseTag = string.Format(tagNameFormat, revision.ReviewId.ReviewId, revision.RevisionNumber, "base"); var headTag = string.Format(tagNameFormat, revision.ReviewId.ReviewId, revision.RevisionNumber, "head"); bool success = true; success = DeleteTag(options, revision, baseTag, gitLab) && success; success = DeleteTag(options, revision, headTag, gitLab) && success; if (success && options.DeleteTags) { revision.ArchiveState = (int)ArchiveState.Archived; session.Save(revision); session.Flush(); } } session.Flush(); } }
/// <summary> /// Marks old closed and merged merge requests (determine by options DaysThreshold parameter) as "archive pending". /// This method does not update Git in any way. /// </summary> private static void MarkAsArchivePending(RunArchiverVerb options, ISessionFactory sessionFactory, GitLabApi gitLab) { Console.WriteLine("Marking As ArchivePending"); using (var session = sessionFactory.OpenSession()) { var mergeRequests = FindPotentialMergeRequests(options, session); int counter = 0; var toArchive = WhereEligibleToArchiving(mergeRequests, options, gitLab, id => Console.WriteLine($"[{counter++}/{mergeRequests.Length}] Ignoring {id.ProjectId}/{id.ReviewId}")); foreach (var mrId in toArchive) { counter++; var sqlUpdate = "UPDATE [Revisions] SET [ArchiveState] = :archivePending WHERE ProjectId = :projectId and ReviewId = :reviewId"; Console.WriteLine($"[{counter}/{mergeRequests.Length}] Setting ArchivePending for {mrId.ProjectId}/{mrId.Id} merged/closed at: {mrId.MergedAt ?? mrId.ClosedAt}"); session.CreateSQLQuery(sqlUpdate) .SetParameter("archivePending", (int)ArchiveState.ArchivePending) .SetParameter("projectId", mrId.ProjectId) .SetParameter("reviewId", mrId.Id) .ExecuteUpdate(); } } }
private static ReviewIdentifier[] FindPotentialMergeRequests(RunArchiverVerb options, ISession session) { var thresholdDate = options.ThresholdDate; ReviewRevision revision = null; Review review = null; var reviewsQuery = session.QueryOver <ReviewRevision>(() => revision).Where(() => revision.ArchiveState == (int)ArchiveState.NotArchived) .JoinEntityAlias(() => review, () => revision.Id == review.RevisionId) .Where(() => review.ReviewedAt < thresholdDate); if (options.ProjectId.HasValue) { reviewsQuery = reviewsQuery.Where(() => revision.ReviewId.ProjectId == options.ProjectId.Value); } IEnumerable <ReviewIdentifier> idList = reviewsQuery .Select(Projections.Distinct(Projections.Property(() => revision.ReviewId))) .List <ReviewIdentifier>(); if (options.BatchSize.HasValue) { idList = idList.Take(options.BatchSize.Value); } var mergeRequests = idList.ToArray(); Console.WriteLine($"Total of {mergeRequests.Length} potential archive merge requests."); return(mergeRequests); }
private static void RunArchiver(RunArchiverVerb options) { var config = new ConfigurationBuilder() .AddJsonFile(options.ConfigFile.Trim()) .Build(); var sessionFactory = BuildSessionFactory(config); var gitLab = BuildGitLabApi(config); Console.WriteLine(options.ToString()); MarkAsArchivePending(options, sessionFactory, gitLab); ArchivePendingRevisions(options, sessionFactory, gitLab); }
private static IEnumerable <MergeRequest> WhereEligibleToArchiving( IEnumerable <ReviewIdentifier> mergeRequests, RunArchiverVerb options, GitLabApi gitLab, Action <ReviewIdentifier> notEligibleCallback) { foreach (var mergeRequest in mergeRequests) { MergeRequest mrInfo = null; try { mrInfo = gitLab.GetMergeRequestInfo(mergeRequest.ProjectId, mergeRequest.ReviewId).Result; } catch (Exception e) { Console.WriteLine(e.Message); } if (mrInfo != null && (mrInfo.State == MergeRequestState.closed || mrInfo.State == MergeRequestState.merged)) { var finalDate = mrInfo.MergedAt ?? mrInfo.ClosedAt; if (!finalDate.HasValue) { notEligibleCallback(mergeRequest); continue; } if (finalDate.Value < options.ThresholdDate) { yield return(mrInfo); } else { notEligibleCallback(mergeRequest); } } else { notEligibleCallback(mergeRequest); } } }
private static bool DeleteTag(RunArchiverVerb options, ReviewRevision revision, string tagName, GitLabApi gitLab) { if (options.DeleteTags) { try { Console.WriteLine($"Deleting {tagName} from project {revision.ReviewId.ProjectId}"); gitLab.DeleteRef(revision.ReviewId.ProjectId, tagName).Wait(); } catch (System.AggregateException) { Console.WriteLine($"Failed to delete {tagName}"); return(false); } } else { Console.WriteLine($"Would delete {tagName} from project {revision.ReviewId.ProjectId}"); } return(true); }