Skip to content

Commit

Permalink
Merge pull request #282 from microsoft/staging
Browse files Browse the repository at this point in the history
Release - 11/21/23
  • Loading branch information
EricJohnson327 authored Nov 20, 2023
2 parents 78b00f3 + 301f2ac commit 90abdf8
Show file tree
Hide file tree
Showing 52 changed files with 508 additions and 142 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,7 @@ dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_simplified_interpolation = true:suggestion

# Spelling

spelling_exclusion_path = .\exclusion.dic
2 changes: 1 addition & 1 deletion build/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ parameters:
- release

variables:
MSIXVersion: '0.600'
MSIXVersion: '0.700'
solution: '**/GitHubExtension.sln'
appxPackageDir: 'AppxPackages'
testOutputArtifactDir: 'TestResults'
Expand Down
2 changes: 1 addition & 1 deletion build/scripts/CreateBuildInfo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Param(
)

$Major = "0"
$Minor = "6"
$Minor = "7"
$Patch = "99" # default to 99 for local builds

$versionSplit = $Version.Split(".");
Expand Down
1 change: 1 addition & 0 deletions exclusion.dic
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
devhome
Binary file added src/GitHubExtension/Assets/GitHubLogo_Dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 20 additions & 1 deletion src/GitHubExtension/Client/Validation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,30 @@ private static bool IsValidHttpUri(string uriString, out Uri? uri)
}

public static bool IsValidGitHubURL(Uri uri)
{
return IsValidGitHubComURL(uri) || IsValidGitHubEnterpriseServerURL(uri);
}

public static bool IsValidGitHubComURL(Uri uri)
{
// Valid GitHub URL has three segments. The first is '/'.
if (uri.Segments.Length < 3 || (!uri.Host.Equals("github.com", StringComparison.OrdinalIgnoreCase) && !uri.Host.Equals("www.github.com", StringComparison.OrdinalIgnoreCase)))
{
Log.Logger()?.ReportDebug($"{uri.OriginalString} is not a valid github uri");
Log.Logger()?.ReportDebug($"{uri.OriginalString} is not a valid GitHub uri");
return false;
}

return true;
}

public static bool IsValidGitHubEnterpriseServerURL(Uri server)
{
// Valid GHES URL has three segments.
// There are no restrictions on the hostname, except what is covered in IsValidHttpUri()
// https://docs.github.com/en/[email protected]/admin/configuration/configuring-network-settings/configuring-the-hostname-for-your-instance
if (server.Segments.Length < 3)
{
Log.Logger()?.ReportDebug($"{server.OriginalString} is not a valid GHES repo uri");
return false;
}

Expand Down
1 change: 0 additions & 1 deletion src/GitHubExtension/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ internal class Constants
{
#pragma warning disable SA1310 // Field names should not contain underscore
public const string DEV_HOME_APPLICATION_NAME = "DevHome";
public const string GITHUB_REPOS_API = "https://api.github.com/repos/";
#pragma warning restore SA1310 // Field names should not contain underscore
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation and Contributors
// Licensed under the MIT license.

using GitHubExtension.DeveloperId;
using Microsoft.Windows.DevHome.SDK;

namespace GitHubExtension;
Expand Down
19 changes: 18 additions & 1 deletion src/GitHubExtension/DataManager/GitHubDataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ public partial class GitHubDataManager : IGitHubDataManager, IDisposable
private static readonly TimeSpan NotificationRetentionTime = TimeSpan.FromDays(7);
private static readonly TimeSpan SearchRetentionTime = TimeSpan.FromDays(7);
private static readonly TimeSpan PullRequestStaleTime = TimeSpan.FromDays(1);

// It is possible different widgets have queries which touch the same pull requests.
// We want to keep this window large enough that we don't delete data being used by
// other clients which simply haven't been updated yet but will in the near future.
// This is a conservative time period to check for pruning and give time for other
// consumers using the data to update its freshness before we remove it.
private static readonly TimeSpan LastObservedDeleteSpan = TimeSpan.FromMinutes(6);
private static readonly long CheckSuiteIdDependabot = 29110;

private static readonly string Name = nameof(GitHubDataManager);
Expand Down Expand Up @@ -417,6 +424,10 @@ private async Task UpdatePullRequestsForLoggedInDeveloperIdsAsync(DataStoreOpera

Log.Logger()?.ReportDebug(Name, $"Updated developer pull requests for {repoFullName}.");
}

// After we update for this developer, remove all pull requests for this developer that
// were not observed recently.
PullRequest.DeleteAllByDeveloperLoginAndLastObservedBefore(DataStore, devId.LoginId, DateTime.UtcNow - LastObservedDeleteSpan);
}
}

Expand Down Expand Up @@ -467,6 +478,9 @@ private async Task UpdatePullRequestsAsync(Repository repository, Octokit.GitHub

CreatePullRequestStatus(dsPullRequest);
}

// Remove unobserved pull requests from this repository.
PullRequest.DeleteLastObservedBefore(DataStore, repository.Id, DateTime.UtcNow - LastObservedDeleteSpan);
}

private void CreatePullRequestStatus(PullRequest pullRequest)
Expand Down Expand Up @@ -602,6 +616,9 @@ private async Task UpdateIssuesAsync(Repository repository, Octokit.GitHubClient
// were not recently updated (within the last minute), remove them from the search result.
SearchIssue.DeleteBefore(DataStore, search, DateTime.Now - TimeSpan.FromMinutes(1));
}

// Remove issues from this repository that were not observed recently.
Issue.DeleteLastObservedBefore(DataStore, repository.Id, DateTime.UtcNow - LastObservedDeleteSpan);
}

// Removes unused data from the datastore.
Expand All @@ -622,7 +639,7 @@ private void SetLastUpdatedInMetaData()
MetaData.AddOrUpdate(DataStore, LastUpdatedKeyName, DateTime.Now.ToDataStoreString());
}

// Converts fullname -> owner, name.
// Converts fullName -> owner, name.
private string[] GetOwnerAndRepositoryNameFromFullName(string fullName)
{
var nameSplit = fullName.Split(new[] { '/' });
Expand Down
2 changes: 1 addition & 1 deletion src/GitHubExtension/DataManager/GitHubDataManagerUpdate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace GitHubExtension;
public partial class GitHubDataManager
{
// This is how frequently the DataStore update occurs.
private static readonly TimeSpan UpdateInterval = TimeSpan.FromMinutes(2);
private static readonly TimeSpan UpdateInterval = TimeSpan.FromMinutes(5);
private static DateTime lastUpdateTime = DateTime.MinValue;

public static async Task Update()
Expand Down
1 change: 0 additions & 1 deletion src/GitHubExtension/DataManager/IGitHubSearchManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT license.

using GitHubExtension.DataManager;
using GitHubExtension.DataModel;

namespace GitHubExtension;

Expand Down
53 changes: 35 additions & 18 deletions src/GitHubExtension/DataModel/DataObjects/Issue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class Issue

public long TimeClosed { get; set; } = DataStore.NoForeignKey;

public long TimeLastObserved { get; set; } = DataStore.NoForeignKey;

// Label IDs are a string concatenation of Label internalIds.
// We need to duplicate this data in order to properly do inserts and
// to compare two objects for changes in order to add/remove associations.
Expand All @@ -66,6 +68,10 @@ private DataStore? DataStore
[Computed]
public DateTime ClosedAt => TimeClosed.ToDateTime();

[Write(false)]
[Computed]
public DateTime LastObservedAt => TimeLastObserved.ToDateTime();

// Derived Properties so consumers of these objects do not
// need to do further queries of the datastore.
[Write(false)]
Expand Down Expand Up @@ -155,6 +161,7 @@ private static Issue CreateFromOctokitIssue(DataStore dataStore, Octokit.Issue o
TimeCreated = okitIssue.CreatedAt.DateTime.ToDataStoreInteger(),
TimeUpdated = okitIssue.UpdatedAt.HasValue ? okitIssue.UpdatedAt.Value.DateTime.ToDataStoreInteger() : 0,
TimeClosed = okitIssue.ClosedAt.HasValue ? okitIssue.ClosedAt.Value.DateTime.ToDataStoreInteger() : 0,
TimeLastObserved = DateTime.UtcNow.ToDataStoreInteger(),
};

// Labels are a string concat of label internal ids.
Expand Down Expand Up @@ -207,28 +214,22 @@ private static Issue AddOrUpdateIssue(DataStore dataStore, Issue issue)
var existing = GetByInternalId(dataStore, issue.InternalId);
if (existing is not null)
{
if (issue.TimeUpdated > existing.TimeUpdated)
{
issue.Id = existing.Id;
dataStore.Connection!.Update(issue);
issue.DataStore = dataStore;

if (issue.LabelIds != existing.LabelIds)
{
UpdateLabelsForIssue(dataStore, issue);
}

if (issue.AssigneeIds != existing.AssigneeIds)
{
UpdateAssigneesForIssue(dataStore, issue);
}
// Existing issues must be updated and always marked observed.
issue.Id = existing.Id;
dataStore.Connection!.Update(issue);
issue.DataStore = dataStore;

return issue;
if (issue.LabelIds != existing.LabelIds)
{
UpdateLabelsForIssue(dataStore, issue);
}
else

if (issue.AssigneeIds != existing.AssigneeIds)
{
return existing;
UpdateAssigneesForIssue(dataStore, issue);
}

return issue;
}

// No existing issue, add it.
Expand Down Expand Up @@ -353,4 +354,20 @@ private static void UpdateAssigneesForIssue(DataStore dataStore, Issue issue)
}
}
}

// Delete records in a repository not observed before the specified date.
public static void DeleteLastObservedBefore(DataStore dataStore, long repositoryId, DateTime date)
{
// Delete issues older than the time specified for the given repository.
// This is intended to be run after updating a repository's issues so that non-observed
// records will be removed.
var sql = @"DELETE FROM Issue WHERE RepositoryId = $RepositoryId AND TimeLastObserved < $Time;";
var command = dataStore.Connection!.CreateCommand();
command.CommandText = sql;
command.Parameters.AddWithValue("$Time", date.ToDataStoreInteger());
command.Parameters.AddWithValue("$RepositoryId", repositoryId);
Log.Logger()?.ReportDebug(DataStore.GetCommandLogMessage(sql, command));
var rowsDeleted = command.ExecuteNonQuery();
Log.Logger()?.ReportDebug(DataStore.GetDeletedLogMessage(rowsDeleted));
}
}
78 changes: 60 additions & 18 deletions src/GitHubExtension/DataModel/DataObjects/PullRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public class PullRequest

public long TimeClosed { get; set; } = DataStore.NoForeignKey;

public long TimeLastObserved { get; set; } = DataStore.NoForeignKey;

// Label IDs are a string concatenation of Label internalIds.
// We need to duplicate this data in order to properly do inserts and
// to compare two objects for changes in order to add/remove associations.
Expand Down Expand Up @@ -80,6 +82,10 @@ public class PullRequest
[Computed]
public DateTime ClosedAt => TimeClosed.ToDateTime();

[Write(false)]
[Computed]
public DateTime LastObservedAt => TimeLastObserved.ToDateTime();

// Derived Properties so consumers of these objects do not
// need to do further queries of the datastore.
[Write(false)]
Expand Down Expand Up @@ -336,6 +342,7 @@ private static PullRequest CreateFromOctokitPullRequest(DataStore dataStore, Oct
TimeUpdated = okitPull.UpdatedAt.DateTime.ToDataStoreInteger(),
TimeMerged = okitPull.MergedAt.HasValue ? okitPull.MergedAt.Value.DateTime.ToDataStoreInteger() : 0,
TimeClosed = okitPull.ClosedAt.HasValue ? okitPull.ClosedAt.Value.DateTime.ToDataStoreInteger() : 0,
TimeLastObserved = DateTime.UtcNow.ToDataStoreInteger(),
};

// Labels are a string concat of label internal ids.
Expand Down Expand Up @@ -385,28 +392,22 @@ private static PullRequest AddOrUpdatePullRequest(DataStore dataStore, PullReque
var existingPull = GetByInternalId(dataStore, pull.InternalId);
if (existingPull is not null)
{
if (pull.TimeUpdated > existingPull.TimeUpdated)
{
pull.Id = existingPull.Id;
dataStore.Connection!.Update(pull);
pull.DataStore = dataStore;

if (pull.LabelIds != existingPull.LabelIds)
{
UpdateLabelsForPullRequest(dataStore, pull);
}

if (pull.AssigneeIds != existingPull.AssigneeIds)
{
UpdateAssigneesForPullRequest(dataStore, pull);
}
// Existing pull requests must always be updated to update the LastObserved time.
pull.Id = existingPull.Id;
dataStore.Connection!.Update(pull);
pull.DataStore = dataStore;

return pull;
if (pull.LabelIds != existingPull.LabelIds)
{
UpdateLabelsForPullRequest(dataStore, pull);
}
else

if (pull.AssigneeIds != existingPull.AssigneeIds)
{
return existingPull;
UpdateAssigneesForPullRequest(dataStore, pull);
}

return pull;
}

// No existing pull request, add it.
Expand Down Expand Up @@ -526,4 +527,45 @@ private static void UpdateAssigneesForPullRequest(DataStore dataStore, PullReque
}
}
}

// Delete records in a repository not observed before the specified date.
public static void DeleteLastObservedBefore(DataStore dataStore, long repositoryId, DateTime date)
{
// Delete pull requests older than the time specified for the given repository.
// This is intended to be run after updating a repository's Pull Requests so that non-observed
// records will be removed.
var sql = @"DELETE FROM PullRequest WHERE RepositoryId = $RepositoryId AND TimeLastObserved < $Time;";
var command = dataStore.Connection!.CreateCommand();
command.CommandText = sql;
command.Parameters.AddWithValue("$Time", date.ToDataStoreInteger());
command.Parameters.AddWithValue("$RepositoryId", repositoryId);
Log.Logger()?.ReportDebug(DataStore.GetCommandLogMessage(sql, command));
var rowsDeleted = command.ExecuteNonQuery();
Log.Logger()?.ReportDebug(DataStore.GetDeletedLogMessage(rowsDeleted));
}

// Delete all records from a particular user before the specified date.
// This is for removing developer pull requests across any repository that were not updated
// recently. This should remove non-open pull requests from the developer across all repositories.
public static void DeleteAllByDeveloperLoginAndLastObservedBefore(DataStore dataStore, string loginId, DateTime date)
{
var developerUsers = User.GetDeveloperUsers(dataStore);
foreach (var user in developerUsers)
{
if (user.Login != loginId)
{
continue;
}

var sql = @"DELETE FROM PullRequest WHERE AuthorId = $UserId AND TimeLastObserved < $Time;";
var command = dataStore.Connection!.CreateCommand();
command.CommandText = sql;
command.Parameters.AddWithValue("$Time", date.ToDataStoreInteger());
command.Parameters.AddWithValue("$UserId", user.Id);
Log.Logger()?.ReportDebug(DataStore.GetCommandLogMessage(sql, command));
var rowsDeleted = command.ExecuteNonQuery();
Log.Logger()?.ReportDebug(DataStore.GetDeletedLogMessage(rowsDeleted));
break;
}
}
}
4 changes: 3 additions & 1 deletion src/GitHubExtension/DataModel/GitHubDataStoreSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public GitHubDataStoreSchema()
}

// Update this anytime incompatible changes happen with a released version.
private const long SchemaVersionValue = 0x0004;
private const long SchemaVersionValue = 0x0005;

private static readonly string Metadata =
@"CREATE TABLE Metadata (" +
Expand Down Expand Up @@ -79,6 +79,7 @@ public GitHubDataStoreSchema()
"TimeCreated INTEGER NOT NULL," +
"TimeUpdated INTEGER NOT NULL," +
"TimeClosed INTEGER NOT NULL," +
"TimeLastObserved INTEGER NOT NULL," +
"HtmlUrl TEXT NULL COLLATE NOCASE," +
"Locked INTEGER NOT NULL," +
"AssigneeIds TEXT NULL COLLATE NOCASE," +
Expand Down Expand Up @@ -116,6 +117,7 @@ public GitHubDataStoreSchema()
"TimeUpdated INTEGER NOT NULL," +
"TimeMerged INTEGER NOT NULL," +
"TimeClosed INTEGER NOT NULL," +
"TimeLastObserved INTEGER NOT NULL," +
"HtmlUrl TEXT NULL COLLATE NOCASE," +
"Locked INTEGER NOT NULL," +
"Draft INTEGER NOT NULL," +
Expand Down
Loading

0 comments on commit 90abdf8

Please sign in to comment.