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
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,77 @@ ... on Commit {
}
}

/// <summary>
/// Gets all releases for a repository using GraphQL with pagination.
/// </summary>
/// <param name="owner">Repository owner.</param>
/// <param name="repo">Repository name.</param>
/// <returns>List of release nodes.</returns>
public async Task<List<ReleaseNode>> GetReleasesAsync(
string owner,
string repo)
{
try
{
var allReleaseNodes = new List<ReleaseNode>();
string? afterCursor = null;
bool hasNextPage;

// Paginate through all releases
do
{
// Create GraphQL request to get releases for a repository with pagination support
var request = new GraphQLRequest
{
Query = @"
query($owner: String!, $repo: String!, $after: String) {
repository(owner: $owner, name: $repo) {
releases(first: 100, after: $after, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
tagName
}
pageInfo {
hasNextPage
endCursor
}
}
}
}",
Variables = new
{
owner,
repo,
after = afterCursor
}
};

// Execute GraphQL query
var response = await _graphqlClient.SendQueryAsync<GetReleasesResponse>(request);

// Extract release nodes from the GraphQL response, filtering out null or invalid values
var pageReleaseNodes = response.Data?.Repository?.Releases?.Nodes?
.Where(n => !string.IsNullOrEmpty(n.TagName))
.ToList() ?? [];

allReleaseNodes.AddRange(pageReleaseNodes);

// Check if there are more pages
var pageInfo = response.Data?.Repository?.Releases?.PageInfo;
hasNextPage = pageInfo?.HasNextPage ?? false;
afterCursor = pageInfo?.EndCursor;
}
while (hasNextPage);

// Return list of all release nodes
return allReleaseNodes;
}
catch
{
// If GraphQL query fails, return empty list
return [];
}
}

/// <summary>
/// Finds issue IDs linked to a pull request via closingIssuesReferences.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,33 @@ internal record CommitHistoryData(
/// <param name="Oid">Git object ID (SHA).</param>
internal record CommitNode(
string? Oid);

/// <summary>
/// Response for getting releases from a repository.
/// </summary>
/// <param name="Repository">Repository data containing release information.</param>
internal record GetReleasesResponse(
ReleaseRepositoryData? Repository);

/// <summary>
/// Repository data containing releases information.
/// </summary>
/// <param name="Releases">Releases connection data.</param>
internal record ReleaseRepositoryData(
ReleasesConnectionData? Releases);

/// <summary>
/// Releases connection data containing nodes and page info.
/// </summary>
/// <param name="Nodes">Release nodes.</param>
/// <param name="PageInfo">Pagination information.</param>
internal record ReleasesConnectionData(
List<ReleaseNode>? Nodes,
PageInfo? PageInfo);

/// <summary>
/// Release node containing release information.
/// </summary>
/// <param name="TagName">Tag name associated with the release.</param>
internal record ReleaseNode(
string? TagName);
26 changes: 21 additions & 5 deletions src/DemaConsulting.BuildMark/RepoConnectors/GitHubRepoConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ internal sealed record Commit(
/// </summary>
internal sealed record GitHubData(
IReadOnlyList<Commit> Commits,
IReadOnlyList<Release> Releases,
IReadOnlyList<ReleaseNode> Releases,
IReadOnlyList<RepositoryTag> Tags,
IReadOnlyList<PullRequest> PullRequests,
IReadOnlyList<Issue> Issues);
Expand All @@ -142,9 +142,9 @@ internal sealed record GitHubData(
internal sealed record LookupData(
Dictionary<int, Issue> IssueById,
Dictionary<string, PullRequest> CommitHashToPr,
List<Release> BranchReleases,
List<ReleaseNode> BranchReleases,
Dictionary<string, RepositoryTag> TagsByName,
Dictionary<string, Release> TagToRelease,
Dictionary<string, ReleaseNode> TagToRelease,
List<Version> ReleaseVersions,
HashSet<string> BranchTagNames);

Expand All @@ -166,7 +166,7 @@ private static async Task<GitHubData> FetchGitHubDataAsync(
{
// Fetch all data from GitHub in parallel
var commitsTask = GetAllCommitsAsync(graphqlClient, owner, repo, branch);
var releasesTask = client.Repository.Release.GetAll(owner, repo);
var releasesTask = GetAllReleasesAsync(graphqlClient, owner, repo);
var tagsTask = client.Repository.GetAllTags(owner, repo);
var pullRequestsTask = client.PullRequest.GetAllForRepository(owner, repo, new PullRequestRequest { State = ItemStateFilter.All });
var issuesTask = client.Issue.GetAllForRepository(owner, repo, new RepositoryIssueRequest { State = ItemStateFilter.All });
Expand Down Expand Up @@ -214,7 +214,7 @@ internal static LookupData BuildLookupData(GitHubData data)
// Build an ordered list of releases on the current branch.
// This is used to select the prior release version for identifying changes in the build.
var branchReleases = data.Releases
.Where(r => !string.IsNullOrEmpty(r.TagName) && branchTagNames.Contains(r.TagName))
.Where(r => r.TagName != null && branchTagNames.Contains(r.TagName))
.ToList();

// Build a mapping from tag name to tag object for quick lookup.
Expand Down Expand Up @@ -572,6 +572,22 @@ private static async Task<IReadOnlyList<Commit>> GetAllCommitsAsync(
return commitShas.Select(sha => new Commit(sha)).ToList();
}

/// <summary>
/// Gets all releases for a repository using GraphQL pagination.
/// </summary>
/// <param name="graphqlClient">GitHub GraphQL client.</param>
/// <param name="owner">Repository owner.</param>
/// <param name="repo">Repository name.</param>
/// <returns>List of all releases.</returns>
private static async Task<IReadOnlyList<ReleaseNode>> GetAllReleasesAsync(
GitHubGraphQLClient graphqlClient,
string owner,
string repo)
{
// Fetch all releases for the repository using GraphQL
return await graphqlClient.GetReleasesAsync(owner, repo);
}

/// <summary>
/// Gets commits in the range from fromHash (exclusive) to toHash (inclusive).
/// </summary>
Expand Down
Loading