Skip to content

Add initial implementation of Microsoft.DotNet.Automation library#2158

Draft
lbussell wants to merge 3 commits into
mainfrom
lbussell/automation-code
Draft

Add initial implementation of Microsoft.DotNet.Automation library#2158
lbussell wants to merge 3 commits into
mainfrom
lbussell/automation-code

Conversation

@lbussell

Copy link
Copy Markdown
Member

This PR is the start of #2152. It has a small initial scope focusing only on creating pull requests and branches. It also only targets GitHub for now.

Introduce the Microsoft.DotNet.Automation library for automating git commits and pull requests against GitHub. Provides a RepoHostEngine and supporting types for branch/PR automation, replacing the previous ImageBuilder.Automation implementation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/Automation/GitWorkspace.cs Fixed
Comment thread src/Automation/GitWorkspace.cs Dismissed
Comment thread src/Automation/GitWorkspace.cs Fixed
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an initial Microsoft.DotNet.Automation library intended to provide a service-agnostic reconciliation API for automating git commits, branches, and (currently GitHub-only) pull requests, forming the foundation for the broader automation library described in #2152.

Changes:

  • Adds a new Microsoft.DotNet.Automation project with branch and pull request “ensure desired state” APIs.
  • Implements git operations via the git CLI (GitWorkspace/GitCli) and GitHub PR operations via Octokit (GitHubPullRequestApi).
  • Wires the new project into the repo solution (Microsoft.DotNet.DockerTools.slnx).

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/Automation/RepoHostEngine.cs Core reconciliation engine for ensuring branch content and PR state; contains create/update logic and foreign-commit policy handling.
src/Automation/RemoteRepo.cs Abstraction for remote repositories, including authenticated clone URL construction.
src/Automation/README.md Usage docs and examples for ensuring PRs/branches and configuring policies.
src/Automation/PullRequestUpdateStrategy.cs Defines append vs replace strategy for PR updates.
src/Automation/PullRequestSpec.cs Defines desired-state contract for an automated PR (key, target branch, apply callback, policies).
src/Automation/PullRequestResult.cs Result object for PR ensure operations (outcome, URL, commits, details).
src/Automation/PullRequestOutcome.cs Enumerates possible PR ensure outcomes (unchanged/created/updated/stopped/dry-run).
src/Automation/PullRequestInfo.cs Internal representation of a PR as seen via IPullRequestApi.
src/Automation/Microsoft.DotNet.Automation.csproj New packable library project with logging abstractions + Octokit dependencies.
src/Automation/IRepoHost.cs Public interface for ensuring PRs and direct branch updates.
src/Automation/IPullRequestApi.cs Internal service-specific PR API surface used by the engine.
src/Automation/IGitContext.cs Public interface for producing commits in a temporary workspace.
src/Automation/GitWorkspace.cs Temporary clone implementation and git operations (clone, fetch, commit, push, diff logging).
src/Automation/GitHub/GitHubRepoHost.cs Public GitHub-backed IRepoHost implementation wiring engine + GitHub API client.
src/Automation/GitHub/GitHubRepo.cs GitHub RemoteRepo implementation and clone/auth URL handling.
src/Automation/GitHub/GitHubPullRequestApi.cs Octokit-backed PR/comment operations used by the engine.
src/Automation/GitException.cs Exception type that masks credentials in command/error text.
src/Automation/GitContext.cs Default IGitContext implementation that commits via GitWorkspace.
src/Automation/GitCommit.cs Commit model plus helper to extract subject line.
src/Automation/GitCliResult.cs Wrapper for git stdout output plus trimming helper.
src/Automation/GitCli.cs Git CLI execution wrapper with secret masking in logs/errors.
src/Automation/GitAutomationOptions.cs Shared options (token, author, dry run).
src/Automation/GitAuthor.cs Commit author identity record.
src/Automation/ForeignCommitPolicy.cs Policy for handling commits not authored by automation.
src/Automation/BranchSpec.cs Desired-state contract for direct branch updates.
src/Automation/BranchResult.cs Result object for branch ensure operations (outcome, commits).
src/Automation/BranchOutcome.cs Enumerates possible branch ensure outcomes.
Microsoft.DotNet.DockerTools.slnx Adds the new Automation project to the solution for CI build/test inclusion.

Comment thread src/Automation/README.md
},
};

AutomationResult result = await host.EnsurePullRequestAsync(spec);
Comment thread src/Automation/README.md
Comment on lines +63 to +65
AutomationResult result = await host.EnsureBranchContentAsync(spec);
// result.CommitShas contains the pushed commits, or is empty if nothing needed to change.
```

string desiredTreeSha = await workspace.RevParseAsync("HEAD^{tree}");
string headTreeSha = await workspace.RevParseAsync($"{headSha}^{{tree}}");
bool contentChanged = context.Commits.Count > 0 && desiredTreeSha != headTreeSha;
Comment thread src/Automation/GitHub/GitHubRepo.cs Outdated
Comment on lines +16 to +19
internal override Uri GetAuthenticatedCloneUrl(string token) =>
string.IsNullOrEmpty(token)
? CloneUrl
: new Uri($"https://x-access-token:{Uri.EscapeDataString(token)}@github.com/{Owner}/{Name}");
Comment on lines +61 to +65
public async Task<PullRequestResult> EnsurePullRequestAsync(
PullRequestSpec spec,
CancellationToken cancellationToken = default)
{
GitCli git = new(logger, options.Token);
string rootPath = CreateTempDirectory();
try
{
string barePath = Path.Combine(rootPath, "remote.git");
try
{
string barePath = Path.Combine(rootPath, "remote.git");
string workPath = Path.Combine(rootPath, "work");
private static async Task<string> WriteAndCommitAsync(
string workPath, string relativePath, string content, GitAuthor author, string message)
{
string fullPath = Path.Combine(workPath, relativePath);

private static string CreateTempDirectory()
{
string path = Path.Combine(Path.GetTempPath(), $"automation-test-{Path.GetRandomFileName()}");
async (context, cancellationToken) =>
{
await File.WriteAllTextAsync(
Path.Combine(context.Directory, relativePath), content, cancellationToken);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants