Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ghdump/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
public class Issue
{
public required string Id { get; set; }
public required Author Author { get; set; }
public required string Title { get; set; }
public required string Body { get; set; }
public required string Url { get; set; }
Expand All @@ -99,6 +100,7 @@
public class PullRequest
{
public required string Id { get; set; }
public required Author Author { get; set; }
public required string Title { get; set; }
public required string Body { get; set; }
public required string Url { get; set; }
Expand Down Expand Up @@ -136,6 +138,7 @@
public class GithubIssueModel
{
public required string Id { get; set; }
public required string Author { get; set; }
public required string Title { get; set; }
public required string URL { get; set; }
public required DateTime CreatedAt { get; set; }
Expand Down Expand Up @@ -216,7 +219,7 @@
[JsonSerializable(typeof(CommentConnection))]
[JsonSerializable(typeof(Comment))]
[JsonSerializable(typeof(Author))]
[JsonSerializable(typeof(Edge<>))]

Check warning on line 222 in ghdump/Models.cs

View workflow job for this annotation

GitHub Actions / build

Did not generate serialization metadata for type 'Edge<>'. (https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1030)

Check warning on line 222 in ghdump/Models.cs

View workflow job for this annotation

GitHub Actions / build

Did not generate serialization metadata for type 'Edge<>'. (https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1030)
[JsonSerializable(typeof(PageInfo))]
[JsonSerializable(typeof(IssueConnection))]
[JsonSerializable(typeof(Issue))]
Expand Down
52 changes: 38 additions & 14 deletions ghdump/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
AllowMultipleArgumentsPerToken = true
};

var includeIssuesOption = new Option<bool?>(["-i", "--include-issues"], () => null, "Include GitHub issues.");
var includePullsOption = new Option<bool?>(["-p", "--include-pull-requests"], () => null, "Include GitHub pull-requests.");
var includeDiscussionsOption = new Option<bool?>(["-d", "--include-discussions"], () => null, "Include GitHub discussions.");

Expand All @@ -59,26 +60,34 @@
accessToken,
repoOption,
labelOption,
includeIssuesOption,
includePullsOption,
includeDiscussionsOption,
outputPath
};

rootCommand.SetHandler(RunAsync, accessToken, repoOption, labelOption, includePullsOption, includeDiscussionsOption, outputPath);
rootCommand.SetHandler(RunAsync, accessToken, repoOption, labelOption, includeIssuesOption, includePullsOption, includeDiscussionsOption, outputPath);

await rootCommand.InvokeAsync(args);

async Task RunAsync(string? accessToken, string? repo, string[] labels, bool? includePullRequests, bool? includeDiscussions, string? outputDirectory)
async Task RunAsync(string? accessToken, string? repo, string[] labels, bool? includeIssues, bool? includePullRequests, bool? includeDiscussions, string? outputDirectory)
{
accessToken ??= configAccessToken;
includeDiscussions ??= labels is [];
outputDirectory ??= Environment.CurrentDirectory;

bool includePulls = includePullRequests ?? false;
bool issuesIncluded = includeIssues ?? false;
bool pullsIncluded = includePullRequests ?? false;
bool discussionsIncluded = includeDiscussions ?? false;

if (!issuesIncluded && !pullsIncluded && !discussionsIncluded)
{
// If no options are specified, include issues by default
issuesIncluded = true;
}

var (repoOwner, repoName) = repo?.Trim().Split('/', StringSplitOptions.RemoveEmptyEntries) switch
{
[var owner, var name] => (owner, name),
[var owner, var name] => (owner, name),
_ => throw new InvalidOperationException("Invalid repository format, expected owner/repo. Example: dotnet/aspnetcore.")
};

Expand All @@ -102,8 +111,9 @@ async Task RunAsync(string? accessToken, string? repo, string[] labels, bool? in
Console.WriteLine("No Labels specified.");
}

Console.WriteLine($"Including pull-requests: {(includePulls ? "yes" : "no")}");
Console.WriteLine($"Including discussions: {(includeDiscussions.Value ? "yes" : "no")}");
Console.WriteLine($"Including issues: {(issuesIncluded ? "yes" : "no")}");
Console.WriteLine($"Including pull-requests: {(pullsIncluded ? "yes" : "no")}");
Console.WriteLine($"Including discussions: {(discussionsIncluded ? "yes" : "no")}");
Console.WriteLine($"Results directory: {outputDirectory}");

if (!await CheckRepositoryValid(repoOwner, repoName))
Expand All @@ -113,9 +123,9 @@ async Task RunAsync(string? accessToken, string? repo, string[] labels, bool? in

var sw = Stopwatch.StartNew();

var discussionsTask = GetDiscussionsAsync(includeDiscussions.Value);
var issuesTask = GetIssuesAsync(labels);
var pullsTask = GetPullRequestsAsync(labels, includePulls);
var discussionsTask = GetDiscussionsAsync(discussionsIncluded);
var issuesTask = GetIssuesAsync(labels, issuesIncluded);
var pullsTask = GetPullRequestsAsync(labels, pullsIncluded);

await Task.WhenAll(discussionsTask, issuesTask, pullsTask);

Expand All @@ -125,7 +135,7 @@ async Task RunAsync(string? accessToken, string? repo, string[] labels, bool? in
var pulls = await pullsTask;
var discussions = await discussionsTask;

await WriteResultsToDisk(outputDirectory, issues, includePulls, pulls, includeDiscussions.Value, discussions, sw.Elapsed);
await WriteResultsToDisk(outputDirectory, issuesIncluded, issues, pullsIncluded, pulls, discussionsIncluded, discussions, sw.Elapsed);

async Task<bool> CheckRepositoryValid(string repoOwner, string repoName)
{
Expand Down Expand Up @@ -157,6 +167,7 @@ async Task<bool> CheckRepositoryValid(string repoOwner, string repoName)

async Task WriteResultsToDisk(
string outputDirectory,
bool includeIssues,
List<GithubIssueModel> issues,
bool includePullRequests,
List<GithubIssueModel> pullRequests,
Expand All @@ -180,7 +191,7 @@ async Task WriteResultsToDisk(
Console.WriteLine($"Processed {issues.Count} issues.");
Console.WriteLine($"Issues have been written to {fileName}.");
}
else
else if (includeIssues)
{
Console.WriteLine("No issues found.");
}
Expand Down Expand Up @@ -225,8 +236,13 @@ async Task WriteResultsToDisk(
}


async Task<List<GithubIssueModel>> GetIssuesAsync(string[] labels)
async Task<List<GithubIssueModel>> GetIssuesAsync(string[] labels, bool includeIssues)
{
if (!includeIssues)
{
return [];
}

string? issuesCursor = null;
GraphqlResponse? graphqlResult = null;

Expand All @@ -241,6 +257,9 @@ async Task<List<GithubIssueModel>> GetIssuesAsync(string[] labels)
edges {
node {
id
author {
login
}
title
body
url
Expand Down Expand Up @@ -325,6 +344,7 @@ async Task<List<GithubIssueModel>> GetIssuesAsync(string[] labels)
var issueJson = new GithubIssueModel
{
Id = issue.Id,
Author = issue.Author?.Login ?? "??",
Title = issue.Title,
URL = issue.Url,
CreatedAt = DateTime.Parse(issue.CreatedAt).ToUniversalTime(),
Expand Down Expand Up @@ -517,6 +537,9 @@ async Task<List<GithubIssueModel>> GetPullRequestsAsync(string[] labels, bool in
edges {
node {
id
author {
login
}
title
body
url
Expand Down Expand Up @@ -596,11 +619,12 @@ async Task<List<GithubIssueModel>> GetPullRequestsAsync(string[] labels, bool in
{
var issue = issueEdge.Node;

Console.WriteLine($"Processing issue {issue.Title} ({issue.Url})");
Console.WriteLine($"Processing pull-request {issue.Title} ({issue.Url})");

var issueJson = new GithubIssueModel
{
Id = issue.Id,
Author = issue.Author?.Login ?? "??",
Title = issue.Title,
URL = issue.Url,
CreatedAt = DateTime.Parse(issue.CreatedAt).ToUniversalTime(),
Expand Down
4 changes: 2 additions & 2 deletions ghdump/ghdump.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>7daf1c07-0951-4b52-a198-e4a9c20265e7</UserSecretsId>
<AssemblyName>ghdump</AssemblyName>
<PublishAot>true</PublishAot>
<AssemblyName>ghdump</AssemblyName>
<PublishAot>true</PublishAot>
</PropertyGroup>

<ItemGroup>
Expand Down