Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add arg for changing pull request title #362

Merged
merged 5 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
11 changes: 7 additions & 4 deletions doc/submit.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ To use the **submit** command, you simply need to provide your [GitHub token](ht

## Usage

`wingetcreate.exe submit [\<options>] <PathToManifest>`
Submit local manifest file to Windows Package Manager repo:

`wingetcreate.exe submit --prtitle <PullRequestTitle> --token <GitHubPersonalAccessToken> <PathToManifest>`

## Arguments

The following arguments are available:

| <div style="width:100px">Argument</div> | Description |
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **-t, --token** | GitHub personal access token used for direct submission to the Windows Package Manager repo. If no token is provided, tool will prompt for GitHub login credentials. |
| Argument | Description |
|--------------|-------------|
| **-p, --prtitle** | The title of the pull request submitted to GitHub. Default is "{PackageId} version {Version}"
| **-t, --token** | GitHub personal access token used for direct submission to the Windows Package Manager repo. If no token is provided, tool will prompt for GitHub login credentials.

If you have provided your [GitHub token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) on the command line along with the **--submit** command and the device is registered with Github, **WingetCreate** will submit your PR to [Windows Package Manager repo](https://docs.microsoft.com/windows/package-manager/).

Expand Down
5 changes: 5 additions & 0 deletions doc/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ Override the architecture of an installer:

`wingetcreate.exe update --urls <InstallerUrl1>|<InstallerArchitecture> --version <Version> <PackageIdentifier>`

Update an existing manifest and submit PR to GitHub:

`wingetcreate.exe update --submit --token <GitHubPersonalAccessToken> --urls <InstallerUrl1> <InstallerUrl2> --version <Version> <PackageIdentifier>`

## Arguments

The following arguments are available:
Expand All @@ -43,6 +47,7 @@ The following arguments are available:
| **-v, --version** | Version to be used when updating the package version field.
| **-o, --out** | The output directory where the newly created manifests will be saved locally
| **-s, --submit** | Boolean value for submitting to the Windows Package Manager repo. If true, updated manifest will be submitted directly using the provided GitHub Token
| **-p, --prtitle** | The title of the pull request submitted to GitHub. Default is "{PackageId} version {Version}"
| **-t, --token** | GitHub personal access token used for direct submission to the Windows Package Manager repo. If no token is provided, tool will prompt for GitHub login credentials.
| **-?, --help** | Gets additional help on this command. |

Expand Down
15 changes: 11 additions & 4 deletions src/WingetCreateCLI/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -493,8 +493,9 @@ protected async Task<bool> CheckGitHubTokenAndSetClient()
/// Submits a pull request with multifile manifests using the user's GitHub access token.
/// </summary>
/// <param name="manifests">Wrapper object for manifest object models to be submitted.</param>
/// <param name="prTitle">Optional parameter specifying the title for the pull request.</param>
/// <returns>A <see cref="Task"/> representing the success of the asynchronous operation.</returns>
protected async Task<bool> GitHubSubmitManifests(Manifests manifests)
protected async Task<bool> GitHubSubmitManifests(Manifests manifests, string prTitle = null)
{
if (string.IsNullOrEmpty(this.GitHubToken))
{
Expand All @@ -507,7 +508,7 @@ protected async Task<bool> GitHubSubmitManifests(Manifests manifests)

try
{
PullRequest pullRequest = await this.GitHubClient.SubmitPullRequestAsync(manifests, this.SubmitPRToFork);
PullRequest pullRequest = await this.GitHubClient.SubmitPullRequestAsync(manifests, this.SubmitPRToFork, prTitle);
this.PullRequestNumber = pullRequest.Number;
PullRequestEvent pullRequestEvent = new PullRequestEvent { IsSuccessful = true, PullRequestNumber = pullRequest.Number };
TelemetryManager.Log.WriteEvent(pullRequestEvent);
Expand All @@ -530,12 +531,18 @@ protected async Task<bool> GitHubSubmitManifests(Manifests manifests)
StackTrace = e.StackTrace,
});

if (e is Octokit.ForbiddenException)
if (e is ForbiddenException || e is ArgumentException)
{
Logger.ErrorLocalized(nameof(Resources.Error_Prefix), e.Message);
return false;
}
else if (e is Octokit.NotFoundException)
else if (e is ApiValidationException ex)
{
// This exception is thrown in case of validation failure from GitHub Api.
// One such occasion is when the PR title exceeds max length.
Logger.ErrorLocalized(nameof(Resources.Error_Prefix), ex.ApiError.Errors[0].Message);
}
else if (e is NotFoundException)
{
// This exception can occur if the client is unable to create a reference due to being behind by too many commits.
// The user will need to manually update their master branch of their winget-pkgs fork.
Expand Down
12 changes: 9 additions & 3 deletions src/WingetCreateCLI/Commands/SubmitCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static IEnumerable<Example> Examples
{
yield return new Example(
Resources.Example_SubmitCommand_SubmitLocalManifest,
new SubmitCommand { Path = "<PathToManifest>", GitHubToken = "<GitHubPersonalAccessToken>" });
new SubmitCommand { Path = "<PathToManifest>", GitHubToken = "<GitHubPersonalAccessToken>", PRTitle = "<PullRequestTitle>" });
}
}

Expand All @@ -49,6 +49,12 @@ public static IEnumerable<Example> Examples
[Option('t', "token", Required = false, HelpText = "GitHubToken_HelpText", ResourceType = typeof(Resources))]
public override string GitHubToken { get => base.GitHubToken; set => base.GitHubToken = value; }

/// <summary>
/// Gets or sets the title for the pull request.
/// </summary>
[Option('p', "prtitle", Required = false, HelpText = "PullRequestTitle_HelpText", ResourceType = typeof(Resources))]
public string PRTitle { get; set; }

/// <summary>
/// Gets or sets the unbound arguments that exist after the first positional parameter.
/// </summary>
Expand Down Expand Up @@ -95,13 +101,13 @@ private async Task<bool> SubmitManifest()
{
Manifests manifests = new Manifests();
manifests.SingletonManifest = Serialization.DeserializeFromPath<SingletonManifest>(this.Path);
return await this.GitHubSubmitManifests(manifests);
return await this.GitHubSubmitManifests(manifests, this.PRTitle);
}
else if (Directory.Exists(this.Path) && ValidateManifest(this.Path))
{
List<string> manifestContents = Directory.GetFiles(this.Path).Select(f => File.ReadAllText(f)).ToList();
Manifests manifests = Serialization.DeserializeManifestContents(manifestContents);
return await this.GitHubSubmitManifests(manifests);
return await this.GitHubSubmitManifests(manifests, this.PRTitle);
}
else
{
Expand Down
9 changes: 8 additions & 1 deletion src/WingetCreateCLI/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public static IEnumerable<Example> Examples
yield return new Example(Resources.Example_UpdateCommand_SearchAndUpdateVersionAndInstallerURL, new UpdateCommand { Id = "<PackageIdentifier>", InstallerUrls = new string[] { "<InstallerUrl1>", "<InstallerUrl2>" }, Version = "<Version>" });
yield return new Example(Resources.Example_UpdateCommand_SaveAndPublish, new UpdateCommand { Id = "<PackageIdentifier>", Version = "<Version>", OutputDir = "<OutputDirectory>", GitHubToken = "<GitHubPersonalAccessToken>" });
yield return new Example(Resources.Example_UpdateCommand_OverrideArchitecture, new UpdateCommand { Id = "<PackageIdentifier>", InstallerUrls = new string[] { "<InstallerUrl1>|<InstallerArchitecture>" }, Version = "<Version>" });
yield return new Example(Resources.Example_UpdateCommand_SubmitToGitHub, new UpdateCommand { Id = "<PackageIdentifier>", Version = "<Version>", InstallerUrls = new string[] { "<InstallerUrl1>", "<InstallerUrl2>" }, SubmitToGitHub = true, GitHubToken = "<GitHubPersonalAccessToken>" });
}
}

Expand All @@ -64,6 +65,12 @@ public static IEnumerable<Example> Examples
[Option('o', "out", Required = false, HelpText = "OutputDirectory_HelpText", ResourceType = typeof(Resources))]
public string OutputDir { get; set; }

/// <summary>
/// Gets or sets the title for the pull request.
/// </summary>
[Option('p', "prtitle", Required = false, HelpText = "PullRequestTitle_HelpText", ResourceType = typeof(Resources))]
public string PRTitle { get; set; }

/// <summary>
/// Gets or sets a value indicating whether or not the updated manifest should be submitted to Github.
/// </summary>
Expand Down Expand Up @@ -198,7 +205,7 @@ await this.UpdateManifestsInteractively(initialManifests) :
}

return await this.LoadGitHubClient(true)
? (commandEvent.IsSuccessful = await this.GitHubSubmitManifests(updatedManifests))
? (commandEvent.IsSuccessful = await this.GitHubSubmitManifests(updatedManifests, this.PRTitle))
: false;
}

Expand Down
24 changes: 22 additions & 2 deletions src/WingetCreateCLI/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions src/WingetCreateCLI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@
<value>Search for an existing manifest and update the installer url and version</value>
<comment>Describes a usage scenario for the Update Command that pulls down a manifest by ID and updates the installer URL field and version field with the values provided by the user.</comment>
</data>
<data name="Example_UpdateCommand_SubmitToGitHub" xml:space="preserve">
<value>Update an existing manifest and submit PR to GitHub</value>
<comment>Describes a usage scenario for the Update Command that updates an existing manifest and submits a pull request to GitHub.</comment>
</data>
<data name="FileExtensions_KeywordDescription" xml:space="preserve">
<value>List of file extensions the package could support</value>
</data>
Expand Down Expand Up @@ -348,6 +352,9 @@
<data name="Publisher_KeywordDescription" xml:space="preserve">
<value>The publisher name |e.g. Microsoft|</value>
</data>
<data name="PullRequestTitle_HelpText" xml:space="preserve">
<value>The title of the pull request submitted to GitHub. Default is "{PackageId} version {Version}"</value>
</data>
<data name="PullRequestURI_Message" xml:space="preserve">
<value>Pull request can be found here: {0}</value>
<comment>{0} - will be replaced with the pull request URI</comment>
Expand Down
16 changes: 10 additions & 6 deletions src/WingetCreateCore/Common/GitHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ public async Task<List<string>> GetLatestManifestContentAsync(string packageId)
/// </summary>
/// <param name="manifests">Wrapper object for manifest object models to be submitted in the PR.</param>
/// <param name="submitToFork">Bool indicating whether or not to submit the PR via a fork.</param>
/// <param name="prTitle">Optional parameter specifying the title for the pull request.</param>
/// <returns>Pull request object.</returns>
public Task<PullRequest> SubmitPullRequestAsync(Manifests manifests, bool submitToFork)
public Task<PullRequest> SubmitPullRequestAsync(Manifests manifests, bool submitToFork, string prTitle = null)
{
Dictionary<string, string> contents = new Dictionary<string, string>();
string id;
Expand All @@ -155,7 +156,7 @@ public Task<PullRequest> SubmitPullRequestAsync(Manifests manifests, bool submit
contents.Add($"{id}.locale.{manifests.DefaultLocaleManifest.PackageLocale}", manifests.DefaultLocaleManifest.ToYaml());
}

return this.SubmitPRAsync(id, version, contents, submitToFork);
return this.SubmitPRAsync(id, version, contents, submitToFork, prTitle);
}

/// <summary>
Expand Down Expand Up @@ -275,7 +276,7 @@ private async Task<string> FindPackageIdRecursive(string[] packageId, string pat
return null;
}

private async Task<PullRequest> SubmitPRAsync(string packageId, string version, Dictionary<string, string> contents, bool submitToFork)
private async Task<PullRequest> SubmitPRAsync(string packageId, string version, Dictionary<string, string> contents, bool submitToFork, string prTitle = null)
{
bool createdRepo = false;
Repository repo;
Expand All @@ -301,7 +302,10 @@ private async Task<PullRequest> SubmitPRAsync(string packageId, string version,
string newBranchName = $"autogenerated/{packageId}/{Guid.NewGuid()}";
string newBranchNameHeads = $"heads/{newBranchName}";

string message = $"{packageId} version {version}";
if (string.IsNullOrEmpty(prTitle))
{
prTitle = $"{packageId} version {version}";
}

var upstreamMaster = await this.github.Git.Reference.Get(this.wingetRepoOwner, this.wingetRepo, HeadMasterRef);
var upstreamMasterSha = upstreamMaster.Object.Sha;
Expand Down Expand Up @@ -348,7 +352,7 @@ await retryPolicy.ExecuteAsync(async () =>

var newTree = await this.github.Git.Tree.Create(repo.Id, nt);

var newCommit = new NewCommit(message, newTree.Sha, updatedSha);
var newCommit = new NewCommit(prTitle, newTree.Sha, updatedSha);
var commit = await this.github.Git.Commit.Create(repo.Id, newCommit);

await this.github.Git.Reference.Update(repo.Id, newBranchNameHeads, new ReferenceUpdate(commit.Sha));
Expand All @@ -357,7 +361,7 @@ await retryPolicy.ExecuteAsync(async () =>
string description = await this.GetFileContentsAsync(PRDescriptionRepoPath);

string targetBranch = submitToFork ? repo.Parent.DefaultBranch : repo.DefaultBranch;
var newPullRequest = new NewPullRequest(message, $"{repo.Owner.Login}:{newBranchName}", targetBranch) { Body = description };
var newPullRequest = new NewPullRequest(prTitle, $"{repo.Owner.Login}:{newBranchName}", targetBranch) { Body = description };
var pullRequest = await this.github.PullRequest.Create(this.wingetRepoOwner, this.wingetRepo, newPullRequest);

return pullRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ private async Task RunSubmitAndUpdateFlow(string packageId, string manifestPath,
GitHubToken = this.GitHubApiKey,
WingetRepo = this.WingetPkgsTestRepo,
WingetRepoOwner = this.WingetPkgsTestRepoOwner,
Path = manifestPath,
Path = manifestPath,
PRTitle = packageId + ' ' + PackageVersion,
SubmitPRToFork = this.SubmitPRToFork,
OpenPRInBrowser = false,
};
Expand All @@ -77,7 +78,8 @@ private async Task RunSubmitAndUpdateFlow(string packageId, string manifestPath,
SubmitToGitHub = true,
WingetRepo = this.WingetPkgsTestRepo,
WingetRepoOwner = this.WingetPkgsTestRepoOwner,
SubmitPRToFork = this.SubmitPRToFork,
SubmitPRToFork = this.SubmitPRToFork,
PRTitle = packageId + ' ' + PackageVersion,
OpenPRInBrowser = false,
};

Expand Down
5 changes: 5 additions & 0 deletions src/WingetCreateTests/WingetCreateTests/TestConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public static class TestConstants
/// </summary>
public const string TestPackageIdentifier = "TestPublisher.TestApp";

/// <summary>
/// Test pull request title to be used in test cases.
/// </summary>
public const string TestPRTitle = "TestPublisher.TestApp.TestTitle";

/// <summary>
/// Invalid PackageIdentifier to be used in test cases.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class GitHubTests : GitHubTestsBase

private const string GitHubPullRequestBaseUrl = "https://github.com/{0}/{1}/pull/";

private const string TitleMismatch = "Pull request title does not match test title.";

private GitHub gitHub;

/// <summary>
Expand Down Expand Up @@ -59,7 +61,7 @@ public async Task FindMatchingPackageIdentifierAsync()
}

/// <summary>
/// Verifies that the GitHub client is able to submit a PR by verifying that the generated PR url matches the correct pattern.
/// Verifies that the GitHub client is able to submit a PR by verifying that the generated PR url and title match the correct pattern.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Test]
Expand All @@ -70,7 +72,8 @@ public async Task GetLatestManifestAndSubmitPR()
manifests.SingletonManifest = Serialization.DeserializeFromString<SingletonManifest>(latestManifest.First());
Assert.That(manifests.SingletonManifest.PackageIdentifier, Is.EqualTo(TestConstants.TestPackageIdentifier), FailedToRetrieveManifestFromId);

PullRequest pullRequest = await this.gitHub.SubmitPullRequestAsync(manifests, this.SubmitPRToFork);
PullRequest pullRequest = await this.gitHub.SubmitPullRequestAsync(manifests, this.SubmitPRToFork, TestConstants.TestPRTitle);
Assert.That(TestConstants.TestPRTitle, Is.EqualTo(pullRequest.Title), TitleMismatch);
await this.gitHub.ClosePullRequest(pullRequest.Number);
StringAssert.StartsWith(string.Format(GitHubPullRequestBaseUrl, this.WingetPkgsTestRepoOwner, this.WingetPkgsTestRepo), pullRequest.HtmlUrl, PullRequestFailedToGenerate);
}
Expand Down