mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-27 23:17:20 +01:00
Cleanup
This commit is contained in:
@@ -149,7 +149,32 @@ There is no strict process when it comes to merging pull requests. Pull requests
|
||||
|
||||
* Commits MUST be properly titled and commented as we only use merge commits for the pull request process
|
||||
|
||||
## Deployment process
|
||||
|
||||
Every issue/pull request in a release should share a common milestone named with the release version i.e. `4.5.3.5`
|
||||
|
||||
When every issue and PR in the milestone is closed. Create a version bump PR that changes the version numbers. At the time of this writing they exist in the following files
|
||||
|
||||
- `/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj`
|
||||
- `/src/Tgstation.Server.Host.Console/Tgstation.Server.Host.Console.csproj`
|
||||
- 2 in `/src/Tgstation.Server.Host.Service/Properties/AssemblyInfo.cs`
|
||||
- `/src/Tgstation.Server.Host.Watchdog/Tgstation.Server.Host.Watchdog.csproj`
|
||||
|
||||
Merge the pull request with `[TGSDeploy]` somewhere in the commit title. The scripts will handle amalgamating release notes, building, closing the milestone, and publishing the release. This will also trigger update notifications on existing TGS deployments.
|
||||
|
||||
### API/Client Deployment
|
||||
|
||||
The Api/Client project versions must be updated on nuget when changed. The numbers exist in the following files:
|
||||
|
||||
- `/src/Tgstation.Server.Api/Tgstation.Server.Api.csproj`
|
||||
- `/src/Tgstation.Server.Client/Tgstation.Server.Client.csproj`
|
||||
|
||||
These should not be the same numbers as the main suite. When bumping the API version the client should only receive a minor (3rd number) version bump unless major changes to CLIENT code were made.
|
||||
|
||||
Merge these alongside regular deployments with `[NugetDeploy]` in the commit title (Won't work without an accompanying `[TGSDeploy]`). This will handle the nuget publishing.
|
||||
|
||||
## Banned content
|
||||
|
||||
Do not add any of the following in a Pull Request or risk getting the PR closed:
|
||||
* National Socialist Party of Germany content, National Socialist Party of Germany related content, or National Socialist Party of Germany references
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[Release Notes]: # (Your PR should contain a detailed list of notable changes, titled appropriately. This includes any observable changes to the server or DMAPI. See example below)
|
||||
|
||||
:cl:
|
||||
Description of your change
|
||||
Each newline corresponds to a release note in the upcoming sprint
|
||||
/:cl:
|
||||
|
||||
:cl:
|
||||
You can also have multiple sets of release notes per pull request
|
||||
They will be amalgamated together in the end
|
||||
/:cl:
|
||||
|
||||
[Why]: # (Please add a short description [two lines down] of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding.)
|
||||
+27
-3
@@ -40,7 +40,33 @@ build:
|
||||
parallel: false
|
||||
verbosity: minimal
|
||||
publish_nuget: true
|
||||
test_script:
|
||||
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Api.Tests/Tgstation.Server.Api.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Api.Tests*]*" -output:".\api_coverage.xml" -oldstyle
|
||||
- ps: $wc = New-Object 'System.Net.WebClient'
|
||||
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Api.Tests\TestResults\results.trx))
|
||||
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Client.Tests/Tgstation.Server.Client.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Client.Tests*]*" -output:".\client_coverage.xml" -oldstyle
|
||||
- ps: $wc = New-Object 'System.Net.WebClient'
|
||||
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Client.Tests\TestResults\results.trx))
|
||||
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Models.Migrations*" -output:".\host_coverage.xml" -oldstyle
|
||||
- ps: $wc = New-Object 'System.Net.WebClient'
|
||||
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Tests\TestResults\results.trx))
|
||||
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Console.Tests/Tgstation.Server.Host.Console.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Console.Tests*]*" -output:".\console_coverage.xml" -oldstyle
|
||||
- ps: $wc = New-Object 'System.Net.WebClient'
|
||||
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Console.Tests\TestResults\results.trx))
|
||||
- set path=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow;%path%
|
||||
- copy "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions\appveyor.*" "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions" /y
|
||||
- vstest.console /logger:trx;LogFileName=results.trx "tests\Tgstation.Server.Host.Service.Tests\bin\%CONFIGURATION%\Tgstation.Server.Host.Service.Tests.dll" /Enablecodecoverage /inIsolation /Platform:x64
|
||||
- ps: $wc = New-Object 'System.Net.WebClient'
|
||||
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\TestResults\results.trx))
|
||||
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Watchdog.Tests/Tgstation.Server.Host.Watchdog.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Watchdog.Tests*]*" -output:".\watchdog_coverage.xml" -oldstyle
|
||||
- ps: $wc = New-Object 'System.Net.WebClient'
|
||||
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Watchdog.Tests\TestResults\results.trx))
|
||||
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Models.Migrations..*" -output:".\server_coverage.xml" -oldstyle
|
||||
- ps: $wc = New-Object 'System.Net.WebClient'
|
||||
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Tests\TestResults\results.trx))
|
||||
after_test:
|
||||
- ps: build/UploadCoverage.ps1
|
||||
- ps: build/BuildDox.ps1
|
||||
#host updater
|
||||
- dotnet publish src/Tgstation.Server.Host/Tgstation.Server.Host.csproj -o ../../artifacts/ServerHost -c %CONFIGURATION%
|
||||
#console
|
||||
@@ -54,8 +80,6 @@ after_test:
|
||||
- ps: Remove-Item artifacts/ServerHost/appsettings.json
|
||||
#deploy stuff
|
||||
- ps: build/prep_deployment.ps1
|
||||
- ps: Write-Host $env:TGSReleaseNotes
|
||||
- ps: Write-Host $env:TGSGoodNotes
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
release: "tgstation-server-v$(TGSVersion)"
|
||||
@@ -63,7 +87,7 @@ deploy:
|
||||
auth_token:
|
||||
secure: lJNGAXwiB5HlWdthz3K4PetqpTG5IEAyRgKaiKxFMQ8HW8CcOjRtB97B05op7BsK
|
||||
artifact: ServerConsole,ServerService,ServerUpdatePackage,DMAPI
|
||||
draft: $(TGSGoodNotes)
|
||||
draft: $(TGSDraftNotes)
|
||||
prerelease: true
|
||||
on:
|
||||
TGSDeploy: "Do it."
|
||||
|
||||
+20
-14
@@ -1,19 +1,25 @@
|
||||
$env:TGSVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$env:APPVEYOR_BUILD_FOLDER/artifacts/ServerHost/Tgstation.Server.Host.dll").FileVersion
|
||||
if (($env:CONFIGURATION -match "Release") -And ($env:APPVEYOR_REPO_BRANCH -match "master")) {
|
||||
if ($env:APPVEYOR_REPO_COMMIT_MESSAGE -match "\[TGSDeploy\]") {
|
||||
$env:TGSDeploy = "Do it."
|
||||
|
||||
Write-Host "TGS Version: $env:TGSVersion"
|
||||
|
||||
if (($env:CONFIGURATION -match "Release") -And ($env:APPVEYOR_REPO_BRANCH -match "master") -And ($env:APPVEYOR_REPO_COMMIT_MESSAGE -match "\[TGSDeploy\]")) {
|
||||
Write-Host "Deploying..."
|
||||
$env:TGSDeploy = "Do it."
|
||||
|
||||
Write-Host "Generating release notes..."
|
||||
dotnet run -p "$env:APPVEYOR_BUILD_FOLDER/tools/ReleaseNotes" $env:TGSVersion
|
||||
$env:TGSDraftNotes = !($?)
|
||||
$releaseNotesPath = "$env:APPVEYOR_BUILD_FOLDER/tools/ReleaseNotes/release_notes.md"
|
||||
if (Test-Path $releaseNotesPath -PathType Leaf) {
|
||||
$env:TGSReleaseNotes = [IO.File]::ReadAllText($releaseNotesPath)
|
||||
}
|
||||
else {
|
||||
Write-Host "Release note generation failed, release will be created as a draft!"
|
||||
$env:TGSReleaseNotes = "Automatic generation failed, please fill manually!"
|
||||
}
|
||||
|
||||
if ($env:APPVEYOR_REPO_COMMIT_MESSAGE -match "\[NugetDeploy\]") {
|
||||
$env:NugetDeploy = "Do it."
|
||||
}
|
||||
}
|
||||
|
||||
dotnet run -p "$env:APPVEYOR_BUILD_FOLDER/tools/ReleaseNotes" 4.0.2.0 --no-close
|
||||
$env:TGSGoodNotes = $?
|
||||
$releaseNotesPath = "$env:APPVEYOR_BUILD_FOLDER/tools/ReleaseNotes/release_notes.md"
|
||||
if (Test-Path $releaseNotesPath -PathType Leaf) {
|
||||
$env:TGSReleaseNotes = [IO.File]::ReadAllText($releaseNotesPath)
|
||||
}
|
||||
else {
|
||||
$env:TGSReleaseNotes = "Automatic generation failed, please fill manually!"
|
||||
Write-Host "Nuget deployment enabled"
|
||||
}
|
||||
}
|
||||
|
||||
+258
-266
@@ -9,309 +9,301 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace ReleaseNotes
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static async Task<int> Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Console.WriteLine("Missing version argument!");
|
||||
return 1;
|
||||
}
|
||||
/// <summary>
|
||||
/// Contains the application entrypoint
|
||||
/// </summary>
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The entrypoint for the <see cref="Program"/>
|
||||
/// </summary>
|
||||
static async Task<int> Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Console.WriteLine("Missing version argument!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var versionString = args[0];
|
||||
if (!Version.TryParse(versionString, out var version))
|
||||
{
|
||||
Console.WriteLine("Invalid version: " + versionString);
|
||||
return 2;
|
||||
}
|
||||
var versionString = args[0];
|
||||
if (!Version.TryParse(versionString, out var version))
|
||||
{
|
||||
Console.WriteLine("Invalid version: " + versionString);
|
||||
return 2;
|
||||
}
|
||||
|
||||
var doNotCloseMilestone = args.Length >= 2 && args[1].ToUpperInvariant() == "--NO-CLOSE";
|
||||
var doNotCloseMilestone = args.Length >= 2 && args[1].ToUpperInvariant() == "--NO-CLOSE";
|
||||
|
||||
const string ReleaseNotesEnvVar = "TGS_RELEASE_NOTES_TOKEN";
|
||||
var githubToken = Environment.GetEnvironmentVariable(ReleaseNotesEnvVar);
|
||||
if (String.IsNullOrWhiteSpace(githubToken))
|
||||
{
|
||||
Console.WriteLine("Missing " + ReleaseNotesEnvVar + " environment variable!");
|
||||
return 3;
|
||||
}
|
||||
const string ReleaseNotesEnvVar = "TGS_RELEASE_NOTES_TOKEN";
|
||||
var githubToken = Environment.GetEnvironmentVariable(ReleaseNotesEnvVar);
|
||||
if (String.IsNullOrWhiteSpace(githubToken))
|
||||
{
|
||||
Console.WriteLine("Missing " + ReleaseNotesEnvVar + " environment variable!");
|
||||
return 3;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var client = new GitHubClient(new ProductHeaderValue("tgs_release_notes"));
|
||||
client.Credentials = new Credentials(githubToken);
|
||||
try
|
||||
{
|
||||
var client = new GitHubClient(new ProductHeaderValue("tgs_release_notes"));
|
||||
client.Credentials = new Credentials(githubToken);
|
||||
|
||||
const string RepoOwner = "tgstation";
|
||||
const string RepoName = "tgstation-server";
|
||||
const string RepoOwner = "tgstation";
|
||||
const string RepoName = "tgstation-server";
|
||||
|
||||
var releasesTask = client.Repository.Release.GetAll(RepoOwner, RepoName);
|
||||
var releasesTask = client.Repository.Release.GetAll(RepoOwner, RepoName);
|
||||
|
||||
Console.WriteLine("Getting pull requests in milestone " + versionString + "...");
|
||||
var milestonePRs = await client.Search.SearchIssues(new SearchIssuesRequest
|
||||
{
|
||||
Milestone = versionString,
|
||||
Type = IssueTypeQualifier.PullRequest,
|
||||
Repos = { { RepoOwner, RepoName } }
|
||||
}).ConfigureAwait(false);
|
||||
Console.WriteLine("Getting pull requests in milestone " + versionString + "...");
|
||||
var milestonePRs = await client.Search.SearchIssues(new SearchIssuesRequest
|
||||
{
|
||||
Milestone = versionString,
|
||||
Type = IssueTypeQualifier.PullRequest,
|
||||
Repos = { { RepoOwner, RepoName } }
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
if (milestonePRs.IncompleteResults)
|
||||
{
|
||||
Console.WriteLine("Incomplete results for milestone PRs query!");
|
||||
return 5;
|
||||
}
|
||||
Console.WriteLine(milestonePRs.Items.Count + " total pull requests");
|
||||
if (milestonePRs.IncompleteResults)
|
||||
{
|
||||
Console.WriteLine("Incomplete results for milestone PRs query!");
|
||||
return 5;
|
||||
}
|
||||
Console.WriteLine(milestonePRs.Items.Count + " total pull requests");
|
||||
|
||||
Task<Milestone> milestoneTask = null;
|
||||
var milestoneTaskLock = new object();
|
||||
var releaseDictionary = new Dictionary<int, List<string>>();
|
||||
var authorizedUsers = new Dictionary<long, Task<bool>>();
|
||||
Task<Milestone> milestoneTask = null;
|
||||
var milestoneTaskLock = new object();
|
||||
var releaseDictionary = new Dictionary<int, List<string>>();
|
||||
var authorizedUsers = new Dictionary<long, Task<bool>>();
|
||||
|
||||
async Task GetReleaseNotesFromPR(Issue pullRequest)
|
||||
{
|
||||
PullRequest fullPR = null;
|
||||
async Task GetFullPR()
|
||||
{
|
||||
if (fullPR != null)
|
||||
return;
|
||||
fullPR = await client.Repository.PullRequest.Get(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
|
||||
};
|
||||
async Task GetReleaseNotesFromPR(Issue pullRequest)
|
||||
{
|
||||
//need to check it was merged
|
||||
var fullPr = await client.Repository.PullRequest.Get(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
|
||||
|
||||
async Task<Milestone> GetMilestone()
|
||||
{
|
||||
await GetFullPR().ConfigureAwait(false);
|
||||
if (fullPR.Milestone == null)
|
||||
return null;
|
||||
return await client.Issue.Milestone.Get(RepoOwner, RepoName, fullPR.Milestone.Number);
|
||||
};
|
||||
async Task<Milestone> GetMilestone()
|
||||
{
|
||||
if (fullPR.Milestone == null)
|
||||
return null;
|
||||
return await client.Issue.Milestone.Get(RepoOwner, RepoName, fullPR.Milestone.Number);
|
||||
};
|
||||
|
||||
if (pullRequest.State.Value == ItemState.Closed)
|
||||
{
|
||||
//need to check it was merged
|
||||
await GetFullPR().ConfigureAwait(false);
|
||||
lock (milestoneTaskLock)
|
||||
if (milestoneTask == null)
|
||||
milestoneTask = GetMilestone();
|
||||
if (!fullPR.Merged)
|
||||
return;
|
||||
};
|
||||
lock (milestoneTaskLock)
|
||||
if (milestoneTask == null)
|
||||
milestoneTask = GetMilestone();
|
||||
|
||||
async Task BuildNotesFromComment(string comment, User user)
|
||||
{
|
||||
var commentSplits = comment.Split('\n');
|
||||
var notesOpen = false;
|
||||
var notesClosed = false;
|
||||
var notes = new List<string>();
|
||||
foreach (var line in commentSplits)
|
||||
{
|
||||
var trimmedLine = line.Trim();
|
||||
if (!notesOpen)
|
||||
{
|
||||
notesOpen = trimmedLine.StartsWith(":cl:", StringComparison.Ordinal);
|
||||
notesClosed = false;
|
||||
continue;
|
||||
}
|
||||
if (trimmedLine.StartsWith("/:cl:", StringComparison.Ordinal))
|
||||
{
|
||||
notesClosed = true;
|
||||
notesOpen = false;
|
||||
continue;
|
||||
}
|
||||
if (trimmedLine.Length == 0)
|
||||
continue;
|
||||
notes.Add(trimmedLine);
|
||||
}
|
||||
if (!notesClosed || notes.Count == 0)
|
||||
return;
|
||||
if (!fullPR.Merged)
|
||||
return;
|
||||
|
||||
Task<bool> authTask;
|
||||
TaskCompletionSource<bool> ourTcs = null;
|
||||
lock (authorizedUsers)
|
||||
{
|
||||
if (!authorizedUsers.TryGetValue(user.Id, out authTask))
|
||||
{
|
||||
ourTcs = new TaskCompletionSource<bool>();
|
||||
authTask = ourTcs.Task;
|
||||
authorizedUsers.Add(user.Id, authTask);
|
||||
}
|
||||
}
|
||||
async Task BuildNotesFromComment(string comment, User user)
|
||||
{
|
||||
var commentSplits = comment.Split('\n');
|
||||
var notesOpen = false;
|
||||
var notesClosed = false;
|
||||
var notes = new List<string>();
|
||||
foreach (var line in commentSplits)
|
||||
{
|
||||
var trimmedLine = line.Trim();
|
||||
if (!notesOpen)
|
||||
{
|
||||
notesOpen = trimmedLine.StartsWith(":cl:", StringComparison.Ordinal);
|
||||
notesClosed = false;
|
||||
continue;
|
||||
}
|
||||
if (trimmedLine.StartsWith("/:cl:", StringComparison.Ordinal))
|
||||
{
|
||||
notesClosed = true;
|
||||
notesOpen = false;
|
||||
continue;
|
||||
}
|
||||
if (trimmedLine.Length == 0)
|
||||
continue;
|
||||
notes.Add(trimmedLine);
|
||||
}
|
||||
if (!notesClosed || notes.Count == 0)
|
||||
return;
|
||||
|
||||
if (ourTcs != null)
|
||||
try
|
||||
{
|
||||
//check if the user has access
|
||||
var perm = await client.Repository.Collaborator.ReviewPermission(RepoOwner, RepoName, user.Login).ConfigureAwait(false);
|
||||
ourTcs.SetResult(perm.Permission == PermissionLevel.Write || perm.Permission == PermissionLevel.Admin);
|
||||
}
|
||||
catch
|
||||
{
|
||||
ourTcs.SetResult(false);
|
||||
throw;
|
||||
}
|
||||
Task<bool> authTask;
|
||||
TaskCompletionSource<bool> ourTcs = null;
|
||||
lock (authorizedUsers)
|
||||
{
|
||||
if (!authorizedUsers.TryGetValue(user.Id, out authTask))
|
||||
{
|
||||
ourTcs = new TaskCompletionSource<bool>();
|
||||
authTask = ourTcs.Task;
|
||||
authorizedUsers.Add(user.Id, authTask);
|
||||
}
|
||||
}
|
||||
|
||||
var authorized = await authTask.ConfigureAwait(false);
|
||||
if (!authorized)
|
||||
return;
|
||||
if (ourTcs != null)
|
||||
try
|
||||
{
|
||||
//check if the user has access
|
||||
var perm = await client.Repository.Collaborator.ReviewPermission(RepoOwner, RepoName, user.Login).ConfigureAwait(false);
|
||||
ourTcs.SetResult(perm.Permission == PermissionLevel.Write || perm.Permission == PermissionLevel.Admin);
|
||||
}
|
||||
catch
|
||||
{
|
||||
ourTcs.SetResult(false);
|
||||
throw;
|
||||
}
|
||||
|
||||
lock (releaseDictionary)
|
||||
{
|
||||
foreach (var I in notes)
|
||||
Console.WriteLine("#" + pullRequest.Number + " - " + I + " (@" + user.Login + ")");
|
||||
if (releaseDictionary.TryGetValue(pullRequest.Number, out var currentValues))
|
||||
currentValues.AddRange(notes);
|
||||
else
|
||||
releaseDictionary.Add(pullRequest.Number, notes);
|
||||
}
|
||||
}
|
||||
var authorized = await authTask.ConfigureAwait(false);
|
||||
if (!authorized)
|
||||
return;
|
||||
|
||||
var comments = await client.Issue.Comment.GetAllForIssue(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
|
||||
await Task.WhenAll(BuildNotesFromComment(pullRequest.Body, pullRequest.User), Task.WhenAll(comments.Select(x => BuildNotesFromComment(x.Body, x.User)))).ConfigureAwait(false);
|
||||
lock (releaseDictionary)
|
||||
{
|
||||
foreach (var I in notes)
|
||||
Console.WriteLine("#" + pullRequest.Number + " - " + I + " (@" + user.Login + ")");
|
||||
if (releaseDictionary.TryGetValue(pullRequest.Number, out var currentValues))
|
||||
currentValues.AddRange(notes);
|
||||
else
|
||||
releaseDictionary.Add(pullRequest.Number, notes);
|
||||
}
|
||||
}
|
||||
|
||||
lock (milestoneTaskLock)
|
||||
if (milestoneTask == null)
|
||||
milestoneTask = GetMilestone();
|
||||
}
|
||||
var comments = await client.Issue.Comment.GetAllForIssue(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
|
||||
await Task.WhenAll(BuildNotesFromComment(pullRequest.Body, pullRequest.User), Task.WhenAll(comments.Select(x => BuildNotesFromComment(x.Body, x.User)))).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var tasks = new List<Task>();
|
||||
foreach (var I in milestonePRs.Items)
|
||||
tasks.Add(GetReleaseNotesFromPR(I));
|
||||
var tasks = new List<Task>();
|
||||
foreach (var I in milestonePRs.Items)
|
||||
tasks.Add(GetReleaseNotesFromPR(I));
|
||||
|
||||
var releases = await releasesTask.ConfigureAwait(false);
|
||||
var releases = await releasesTask.ConfigureAwait(false);
|
||||
|
||||
var releasingSuite = version.Major;
|
||||
var releasingSuite = version.Major;
|
||||
|
||||
Version highestReleaseVersion = null;
|
||||
Release highestRelease = null;
|
||||
foreach (var I in releases)
|
||||
{
|
||||
if (!Version.TryParse(I.TagName.Replace("tgstation-server-v", String.Empty), out var currentReleaseVersion))
|
||||
{
|
||||
Console.WriteLine("WARNING: Unable to determine version of release " + I.HtmlUrl);
|
||||
continue;
|
||||
}
|
||||
Version highestReleaseVersion = null;
|
||||
Release highestRelease = null;
|
||||
foreach (var I in releases)
|
||||
{
|
||||
if (!Version.TryParse(I.TagName.Replace("tgstation-server-v", String.Empty), out var currentReleaseVersion))
|
||||
{
|
||||
Console.WriteLine("WARNING: Unable to determine version of release " + I.HtmlUrl);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentReleaseVersion.Major == releasingSuite && (highestReleaseVersion == null || currentReleaseVersion > highestReleaseVersion))
|
||||
{
|
||||
highestReleaseVersion = currentReleaseVersion;
|
||||
highestRelease = I;
|
||||
}
|
||||
}
|
||||
if (currentReleaseVersion.Major == releasingSuite && (highestReleaseVersion == null || currentReleaseVersion > highestReleaseVersion))
|
||||
{
|
||||
highestReleaseVersion = currentReleaseVersion;
|
||||
highestRelease = I;
|
||||
}
|
||||
}
|
||||
|
||||
if (highestReleaseVersion == null)
|
||||
{
|
||||
Console.WriteLine("Unable to determine highest release version for suite " + releasingSuite + "!");
|
||||
return 6;
|
||||
}
|
||||
if (highestReleaseVersion == null)
|
||||
{
|
||||
Console.WriteLine("Unable to determine highest release version for suite " + releasingSuite + "!");
|
||||
return 6;
|
||||
}
|
||||
|
||||
var oldNotes = highestRelease.Body;
|
||||
var oldNotes = highestRelease.Body;
|
||||
|
||||
var splits = new List<string>(oldNotes.Split('\n'));
|
||||
//trim away all the lines that don't start with #
|
||||
var splits = new List<string>(oldNotes.Split('\n'));
|
||||
//trim away all the lines that don't start with #
|
||||
|
||||
string keepThisRelease;
|
||||
if (version.Revision == 0)
|
||||
if (version.Build == 0)
|
||||
keepThisRelease = "# ";
|
||||
else
|
||||
keepThisRelease = "## ";
|
||||
else
|
||||
keepThisRelease = "### ";
|
||||
string keepThisRelease;
|
||||
if (version.Revision == 0)
|
||||
if (version.Build == 0)
|
||||
keepThisRelease = "# ";
|
||||
else
|
||||
keepThisRelease = "## ";
|
||||
else
|
||||
keepThisRelease = "### ";
|
||||
|
||||
for (; !splits[0].StartsWith(keepThisRelease, StringComparison.Ordinal); splits.RemoveAt(0))
|
||||
if (splits.Count == 1)
|
||||
{
|
||||
Console.WriteLine("Error formatting release notes: Can't detemine notes start!");
|
||||
return 7;
|
||||
}
|
||||
for (; !splits[0].StartsWith(keepThisRelease, StringComparison.Ordinal); splits.RemoveAt(0))
|
||||
if (splits.Count == 1)
|
||||
{
|
||||
Console.WriteLine("Error formatting release notes: Can't detemine notes start!");
|
||||
return 7;
|
||||
}
|
||||
|
||||
oldNotes = String.Join('\n', splits);
|
||||
oldNotes = String.Join('\n', splits);
|
||||
|
||||
string prefix;
|
||||
switch (releasingSuite)
|
||||
{
|
||||
case 3:
|
||||
prefix = "The /tg/station server suite";
|
||||
break;
|
||||
default:
|
||||
prefix = "See https://tgstation.github.io/tgstation-server for installation instructions";
|
||||
break;
|
||||
}
|
||||
string prefix;
|
||||
switch (releasingSuite)
|
||||
{
|
||||
case 3:
|
||||
prefix = "The /tg/station server suite";
|
||||
break;
|
||||
default:
|
||||
prefix = "See https://tgstation.github.io/tgstation-server for installation instructions";
|
||||
break;
|
||||
}
|
||||
|
||||
var newNotes = new StringBuilder(prefix);
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append(Environment.NewLine);
|
||||
if (version.Revision == 0)
|
||||
if (version.Build == 0)
|
||||
{
|
||||
newNotes.Append("# [Version ");
|
||||
newNotes.Append(version.Minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNotes.Append("## [Changelog for ");
|
||||
newNotes.Append(version.Build);
|
||||
newNotes.Append(".x");
|
||||
}
|
||||
else
|
||||
{
|
||||
newNotes.Append("### [Patch ");
|
||||
newNotes.Append(version.Revision);
|
||||
}
|
||||
newNotes.Append("](");
|
||||
var milestone = await milestoneTask.ConfigureAwait(false);
|
||||
if (milestone == null)
|
||||
{
|
||||
Console.WriteLine("Unable to detemine milestone!");
|
||||
return 9;
|
||||
}
|
||||
newNotes.Append(milestone.HtmlUrl);
|
||||
newNotes.Append("?closed=1)");
|
||||
newNotes.Append(Environment.NewLine);
|
||||
var newNotes = new StringBuilder(prefix);
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append(Environment.NewLine);
|
||||
if (version.Revision == 0)
|
||||
if (version.Build == 0)
|
||||
{
|
||||
newNotes.Append("# [Version ");
|
||||
newNotes.Append(version.Minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNotes.Append("## [Changelog for ");
|
||||
newNotes.Append(version.Build);
|
||||
newNotes.Append(".x");
|
||||
}
|
||||
else
|
||||
{
|
||||
newNotes.Append("### [Patch ");
|
||||
newNotes.Append(version.Revision);
|
||||
}
|
||||
newNotes.Append("](");
|
||||
var milestone = await milestoneTask.ConfigureAwait(false);
|
||||
if (milestone == null)
|
||||
{
|
||||
Console.WriteLine("Unable to detemine milestone!");
|
||||
return 9;
|
||||
}
|
||||
newNotes.Append(milestone.HtmlUrl);
|
||||
newNotes.Append("?closed=1)");
|
||||
newNotes.Append(Environment.NewLine);
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
if (releaseDictionary.Count == 0)
|
||||
{
|
||||
Console.WriteLine("No release notes for this milestone!");
|
||||
return 8;
|
||||
}
|
||||
if (releaseDictionary.Count == 0)
|
||||
{
|
||||
Console.WriteLine("No release notes for this milestone!");
|
||||
return 8;
|
||||
}
|
||||
|
||||
foreach (var I in releaseDictionary)
|
||||
foreach (var note in I.Value)
|
||||
{
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append("- ");
|
||||
newNotes.Append(note);
|
||||
newNotes.Append(" (#");
|
||||
newNotes.Append(I.Key);
|
||||
newNotes.Append(')');
|
||||
}
|
||||
foreach (var I in releaseDictionary)
|
||||
foreach (var note in I.Value)
|
||||
{
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append("- ");
|
||||
newNotes.Append(note);
|
||||
newNotes.Append(" (#");
|
||||
newNotes.Append(I.Key);
|
||||
newNotes.Append(')');
|
||||
}
|
||||
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append(oldNotes);
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append(Environment.NewLine);
|
||||
newNotes.Append(oldNotes);
|
||||
|
||||
Console.WriteLine("Writing out new release notes...");
|
||||
var releaseNotes = newNotes.ToString();
|
||||
await File.WriteAllTextAsync("release_notes.md", releaseNotes).ConfigureAwait(false);
|
||||
Console.WriteLine("Writing out new release notes...");
|
||||
var releaseNotes = newNotes.ToString();
|
||||
await File.WriteAllTextAsync("release_notes.md", releaseNotes).ConfigureAwait(false);
|
||||
|
||||
if (doNotCloseMilestone)
|
||||
Console.WriteLine("Not closing milestone due to parameter!");
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Closing milestone...");
|
||||
await client.Issue.Milestone.Update(RepoOwner, RepoName, milestone.Number, new MilestoneUpdate
|
||||
{
|
||||
State = ItemState.Closed
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
if (doNotCloseMilestone)
|
||||
Console.WriteLine("Not closing milestone due to parameter!");
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Closing milestone...");
|
||||
await client.Issue.Milestone.Update(RepoOwner, RepoName, milestone.Number, new MilestoneUpdate
|
||||
{
|
||||
State = ItemState.Closed
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user