diff --git a/demodata/example.zip b/demodata/example.zip
new file mode 100644
index 0000000..119e684
Binary files /dev/null and b/demodata/example.zip differ
diff --git a/src/GitHubReleaser/GitHubReleaser.args.json b/src/GitHubReleaser/GitHubReleaser.args.json
index 56c9eb9..b7c4fab 100644
--- a/src/GitHubReleaser/GitHubReleaser.args.json
+++ b/src/GitHubReleaser/GitHubReleaser.args.json
@@ -6,6 +6,18 @@
"Id": "a6460bf8-07be-48ea-b2f4-11bca9e86648",
"Command": "Test1",
"Items": [
+ {
+ "Id": "2762c393-a835-4357-8543-d0c1c1d45fdb",
+ "Command": "/github-repo:\"Suplanus/GitHubReleaser\""
+ },
+ {
+ "Id": "82ec0542-defa-498f-814d-b85df87b49b1",
+ "Command": "/github-token:\"Fill out Secrets.cs\""
+ },
+ {
+ "Id": "3735ff7a-efec-45ad-a02e-1f2fe65e5926",
+ "Command": "/file-for-version:\".\\GitHubReleaser.exe\""
+ },
{
"Id": "912b3373-c011-40ab-857c-1aa38c0b5042",
"Command": "/create-changelog-file:\"true\""
@@ -16,7 +28,7 @@
},
{
"Id": "3c1e4015-2cf8-4927-b596-4cb39742ddcb",
- "Command": "/release-attachments:\"TODO\" \"TODO\""
+ "Command": "/release-attachments:\".\\..\\..\\..\\..\\..\\demodata\\example.zip\""
},
{
"Id": "29245bfd-5851-4c3d-9089-e6648a84e599",
@@ -24,23 +36,15 @@
},
{
"Id": "1da6e697-648d-495f-b2a4-27447f58ba81",
- "Command": "/issue-labels:\"bug;Bug\" \"feature;Feature\""
+ "Command": "/issue-labels:\"bug;Bug\" \"enhancement;Enhancement\""
},
{
"Id": "a01d7c65-8590-4015-a84e-da00eb1e8ecd",
"Command": "/pre-release:\"false\""
},
{
- "Id": "3735ff7a-efec-45ad-a02e-1f2fe65e5926",
- "Command": "/file-for-version:\"TODO\""
- },
- {
- "Id": "82ec0542-defa-498f-814d-b85df87b49b1",
- "Command": "/github-token:\"Fill out Secrets.cs\""
- },
- {
- "Id": "2762c393-a835-4357-8543-d0c1c1d45fdb",
- "Command": "/github-repo:\"Suplanus/GitHubReleaser\""
+ "Id": "d9b72d73-4d90-4975-bae5-41bc95787a9a",
+ "Command": "/draft:\"true\""
}
]
}
diff --git a/src/GitHubReleaser/GitHubReleaser.csproj b/src/GitHubReleaser/GitHubReleaser.csproj
index b8f9276..f9f1714 100644
--- a/src/GitHubReleaser/GitHubReleaser.csproj
+++ b/src/GitHubReleaser/GitHubReleaser.csproj
@@ -8,6 +8,7 @@
+
diff --git a/src/GitHubReleaser/Model/CommandLineParameters.cs b/src/GitHubReleaser/Model/CommandLineParameters.cs
index 832e212..dec5d4f 100644
--- a/src/GitHubReleaser/Model/CommandLineParameters.cs
+++ b/src/GitHubReleaser/Model/CommandLineParameters.cs
@@ -1,5 +1,5 @@
using System.Collections.Generic;
-using System.Runtime.CompilerServices;
+using System.Linq;
using Fclp;
namespace GitHubReleaser.Model
@@ -8,7 +8,9 @@ internal class CommandLineParameters : ReleaserSettings
{
public ICommandLineParserResult Result { get; set; }
- public static CommandLineParameters GetCommandLineParameters(string[] args)
+ public List IssueLabelsWithHeader { get; set; }
+
+ public static CommandLineParameters FromArguments(string[] args)
{
var parser = new FluentCommandLineParser();
parser.Setup(arg => arg.GitHubRepo)
@@ -26,7 +28,7 @@ public static CommandLineParameters GetCommandLineParameters(string[] args)
parser.Setup(arg => arg.IsPreRelease)
.As("pre-release");
- parser.Setup(arg => arg.IssueLabels)
+ parser.Setup(arg => arg.IssueLabelsWithHeader)
.As("issue-labels");
parser.Setup(arg => arg.IssueFilterLabel)
@@ -41,8 +43,22 @@ public static CommandLineParameters GetCommandLineParameters(string[] args)
parser.Setup(arg => arg.IsChangelogFileCreationEnabled)
.As("create-changelog-file");
+ parser.Setup(arg => arg.IsDraft)
+ .As("draft");
+
var result = parser.Parse(args);
var commandLineArguments = parser.Object;
+
+ // Manual map
+ if (parser.Object.IssueLabelsWithHeader != null)
+ {
+ foreach (var issueLabelWithHeader in parser.Object.IssueLabelsWithHeader)
+ {
+ var split = issueLabelWithHeader.Split(';');
+ parser.Object.IssueLabels.Add(split.First(), split.Last());
+ }
+ }
+
commandLineArguments.Result = result;
#if DEBUG
diff --git a/src/GitHubReleaser/Model/IssueWithLabel.cs b/src/GitHubReleaser/Model/IssueWithLabel.cs
new file mode 100644
index 0000000..1f9cc74
--- /dev/null
+++ b/src/GitHubReleaser/Model/IssueWithLabel.cs
@@ -0,0 +1,16 @@
+using Octokit;
+
+namespace GitHubReleaser.Model
+{
+ internal class IssueWithLabel
+ {
+ public string Label { get; }
+ public Issue Issue { get; }
+
+ public IssueWithLabel(string label, Issue issue)
+ {
+ Label = label;
+ Issue = issue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/GitHubReleaser/Model/Releaser.cs b/src/GitHubReleaser/Model/Releaser.cs
index c85e005..2016c3b 100644
--- a/src/GitHubReleaser/Model/Releaser.cs
+++ b/src/GitHubReleaser/Model/Releaser.cs
@@ -1,17 +1,271 @@
-namespace GitHubReleaser.Model
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Octokit;
+using Serilog;
+
+namespace GitHubReleaser.Model
{
internal class Releaser
{
+ public ReleaserSettings Settings { get; set; }
+ private readonly GitHubClient _client;
+ private readonly string ACCOUNT;
+ private readonly string REPO;
+ private readonly string VersionMilestone;
+ private string VersionFull;
+
public Releaser(ReleaserSettings releaserSettings)
{
Settings = releaserSettings;
+ var version = Assembly.LoadFile(Settings.FileForVersion).GetName().Version;
+ VersionMilestone = version.ToString(3);
+ VersionFull = version.ToString();
+
+ var split = Settings.GitHubRepo.Split('/');
+ ACCOUNT = split.First();
+ REPO = split.Last();
+
+ // GitHub
+ ServicePointManager.SecurityProtocol =
+ SecurityProtocolType.Tls12; // needed https://github.com/octokit/octokit.net/issues/1756
+ var connection = new Connection(new ProductHeaderValue(REPO));
+ _client = new GitHubClient(connection);
+ var tokenAuth = new Credentials(Settings.GitHubToken);
+ _client.Credentials = tokenAuth;
}
- public ReleaserSettings Settings { get; set; }
+ public async Task ExecuteAsync()
+ {
+ if (Settings.IsUpdateOnly)
+ {
+ // todo
+ }
+ else
+ {
+ var release = await CreateRelease();
+ }
+
+ if (Settings.IsChangelogFileCreationEnabled)
+ {
+ // todo
+ }
+ }
- public void Execute()
+ private async Task CreateRelease()
{
-
+ // Remove existing
+ Release release = await _client.Repository.Release.Get(ACCOUNT, REPO, VersionFull);
+ if (release != null)
+ {
+ Log.Information("Remove release...");
+ await _client.Repository.Release.Delete(ACCOUNT, REPO, release.Id);
+ }
+
+ // Create
+ Log.Information("Create release...");
+ NewRelease newRelease = new NewRelease(VersionFull);
+ newRelease.Name = VersionFull;
+ newRelease.Prerelease = Settings.IsPreRelease;
+ newRelease.Draft = Settings.IsDraft;
+
+ // Changelog
+ var changelog = await GetReleaseChangelog();
+ if (newRelease.Prerelease)
+ {
+ string alert = "| :warning: **PreRelease**: Bitte nur in Testumgebung nutzen! |" +
+ Environment.NewLine +
+ "| --- |";
+ changelog = alert + Environment.NewLine + changelog;
+ }
+ newRelease.Body = changelog;
+
+ release = await _client.Repository.Release.Create(ACCOUNT, REPO, newRelease);
+
+ // Upload: Attachments
+ Log.Information("Upload attachments...");
+ bool deleteFilesAfterUpload = true;
+ try
+ {
+ for (var index = 0; index < Settings.ReleaseAttachments.Count; index++)
+ {
+ Log.Information(index + 1 + " / " + Settings.ReleaseAttachments.Count);
+
+ var setupFile = Settings.ReleaseAttachments[index];
+ await using var archiveContents = File.OpenRead(setupFile);
+ string assetFilename = Path.GetFileName(setupFile);
+ var assetUpload = new ReleaseAssetUpload
+ {
+ FileName = assetFilename,
+ ContentType = "application/x-msdownload",
+ RawData = archiveContents
+ };
+ await _client.Repository.Release.UploadAsset(release, assetUpload);
+ }
+ }
+ catch (Exception exception)
+ {
+ Log.Error(exception.ToString());
+ deleteFilesAfterUpload = false;
+ }
+
+ if (deleteFilesAfterUpload)
+ {
+ foreach (var attachment in Settings.ReleaseAttachments)
+ {
+ Directory.Delete(attachment, true);
+ }
+ }
+
+ return release;
+ }
+
+ private async Task GetReleaseChangelog()
+ {
+ var releases = await _client.Repository.Release.GetAll(ACCOUNT, REPO);
+ Release lastRelease = releases.OrderBy(obj => obj.CreatedAt.DateTime).Last();
+ IssueRequest recently = new IssueRequest();
+ recently.Filter = IssueFilter.All;
+ recently.State = ItemStateFilter.Closed;
+
+ if (Settings.IsPreRelease)
+ {
+ var lastReleaseCreatedDate = lastRelease.PublishedAt;
+ recently.Since = lastReleaseCreatedDate;
+ }
+
+ var allIssues = await _client.Issue.GetAllForCurrent(recently);
+ var issuesWithLabel = new List();
+ foreach (var issue in allIssues)
+ {
+ if (issue.Milestone == null)
+ {
+ continue;
+ }
+
+ if (!issue.Milestone.Title.Equals(VersionMilestone))
+ {
+ continue;
+ }
+
+ if (Settings.IssueFilterLabel != null)
+ {
+ if (issue.Labels.Any(obj => obj.Name.ToUpper().Equals(Settings.IssueFilterLabel)))
+ {
+ continue;
+ }
+ }
+
+ // Filter by issue label
+ if (Settings.IssueLabels != null &&
+ Settings.IssueLabels.Any())
+ {
+ foreach (var label in issue.Labels)
+ {
+ if (Settings.IssueLabels.Any(obj => obj.Key.Equals(label.Name.ToLower())))
+ {
+ issuesWithLabel.Add(new IssueWithLabel(label.Name, issue));
+ break;
+ }
+ }
+ }
+ else
+ {
+ issuesWithLabel.Add(new IssueWithLabel(null, issue));
+ }
+ }
+
+ // Build changelog text
+ var issueGroups = issuesWithLabel.GroupBy(obj => obj.Label).OrderBy(obj => obj.Key);
+ var changelog = GetChangelogFromIssues(issueGroups);
+
+ return changelog;
+ }
+
+ private string GetChangelogFromIssues(IEnumerable> issueGroups)
+ {
+ var sb = new StringBuilder();
+ foreach (var issueGroup in issueGroups)
+ {
+ sb.AppendLine();
+ sb.AppendLine($"#### {issueGroup.Key}:");
+ foreach (IssueWithLabel issueWithLabel in issueGroup.OrderBy(obj => obj.Issue.Title))
+ {
+ sb.AppendLine($"- [{issueWithLabel.Issue.Title}]({issueWithLabel.Issue.HtmlUrl})");
+ }
+ }
+ string changelog = sb.ToString().Trim();
+ return changelog;
+ }
+
+ public async Task CreateChangelogComplete()
+ {
+ Log.Information("Create Changelog...");
+
+ StringBuilder sb = new StringBuilder();
+ sb.AppendLine("Changelog"); // needed for broken encoding
+ sb.AppendLine();
+
+ var releases = await _client.Repository.Release.GetAll(ACCOUNT, REPO);
+ foreach (var release in releases.OrderByDescending(obj => obj.CreatedAt.Date))
+ {
+ if (release.Draft)
+ {
+ continue;
+ }
+
+ var version = new Version(release.Name);
+ var versionToDisplay = $"{version.Major}.{version.Minor}.{version.Build}";
+ var dateTime = release.CreatedAt.DateTime.ToLocalTime();
+ dateTime = dateTime.AddDays(1); // Don't know why but this is needed
+ dateTime = dateTime.AddHours(1); // Think this is problem with summer & winter time
+ var dateTimeToDisplay = dateTime.ToString("yyyy-MM-dd HH:mm");
+
+ sb.AppendLine($"## [{versionToDisplay}]({release.HtmlUrl})");
+ sb.AppendLine();
+
+ if (release.Prerelease)
+ {
+ sb.AppendLine($"#### Build: {version.Revision} | Date: {dateTimeToDisplay} | Prerelease");
+ }
+ else
+ {
+ sb.AppendLine($"#### Build: {version.Revision} | Date: {dateTimeToDisplay}");
+ }
+
+ sb.AppendLine();
+
+ string changeLog = release.Body.Trim();
+ var changeLogLines = changeLog.Split('\n');
+ foreach (var line in changeLogLines)
+ {
+ if (!line.StartsWith("|")) // Ignore Tables
+ {
+ sb.AppendLine(line);
+ }
+ }
+ sb.AppendLine();
+ }
+
+ // Commit Changelog
+ var changelog = sb.ToString();
+ string path = "CHANGELOG.md";
+ IReadOnlyList contents = await _client
+ .Repository
+ .Content
+ .GetAllContents(ACCOUNT, REPO, path);
+
+ await _client.Repository.Content.CreateFile(
+ ACCOUNT,
+ REPO,
+ path,
+ new UpdateFileRequest("Changelog",
+ changelog, contents.First().Sha));
}
}
}
\ No newline at end of file
diff --git a/src/GitHubReleaser/Model/ReleaserSettings.cs b/src/GitHubReleaser/Model/ReleaserSettings.cs
index 24ebe98..ad5989f 100644
--- a/src/GitHubReleaser/Model/ReleaserSettings.cs
+++ b/src/GitHubReleaser/Model/ReleaserSettings.cs
@@ -12,10 +12,12 @@ internal class ReleaserSettings
public string IssueFilterLabel { get; set; }
- public List IssueLabels { get; set; }
+ public Dictionary IssueLabels { get; set; }
public bool IsPreRelease { get; set; }
+ public bool IsDraft { get; set; }
+
public string FileForVersion { get; set; }
public string GitHubToken { get; set; }
diff --git a/src/GitHubReleaser/Program.cs b/src/GitHubReleaser/Program.cs
index f92b716..c938173 100644
--- a/src/GitHubReleaser/Program.cs
+++ b/src/GitHubReleaser/Program.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
+using System.Threading.Tasks;
using GitHubReleaser.Model;
using Serilog;
using Serilog.Sinks.SystemConsole.Themes;
@@ -9,9 +11,7 @@ namespace GitHubReleaser
{
class Program
{
- public static CommandLineParameters CommandLineParameters { get; private set; }
-
- static void Main(string[] args)
+ static async Task Main(string[] args)
{
// Setup
var argumentString = string.Join(" ", args.Skip(1));
@@ -22,25 +22,59 @@ static void Main(string[] args)
.CreateLogger();
// CommandLineParameters
- CommandLineParameters = CommandLineParameters.GetCommandLineParameters(args);
- if (CommandLineParameters.Result.HasErrors)
+ var commandLine = GetCommandline(args);
+
+ // Execute
+ Releaser releaser = new Releaser(commandLine);
+ await releaser.ExecuteAsync();
+ }
+
+ private static CommandLineParameters GetCommandline(string[] args)
+ {
+ var commandLineParameters = CommandLineParameters.FromArguments(args);
+
+ // Checks
+ if (commandLineParameters.Result.HasErrors)
{
- Log.Error($"Error in parameters: {CommandLineParameters.Result.ErrorText}");
+ Log.Error($"Error in parameters: {commandLineParameters.Result.ErrorText}");
Environment.Exit(160);
}
- LogParameter(nameof(CommandLineParameters.GitHubRepo), CommandLineParameters.GitHubRepo);
- LogParameter(nameof(CommandLineParameters.GitHubToken), CommandLineParameters.GitHubToken);
- LogParameter(nameof(CommandLineParameters.FileForVersion), CommandLineParameters.FileForVersion);
- LogParameter(nameof(CommandLineParameters.IsChangelogFileCreationEnabled), CommandLineParameters.IsChangelogFileCreationEnabled);
- LogParameter(nameof(CommandLineParameters.IsPreRelease), CommandLineParameters.IsPreRelease);
- LogParameter(nameof(CommandLineParameters.IsUpdateOnly), CommandLineParameters.IsUpdateOnly);
- LogParameter(nameof(CommandLineParameters.IssueFilterLabel), CommandLineParameters.IssueFilterLabel);
- LogParameter(nameof(CommandLineParameters.IssueLabels), CommandLineParameters.IssueLabels);
- LogParameter(nameof(CommandLineParameters.ReleaseAttachments), CommandLineParameters.ReleaseAttachments);
- // Execute
- Releaser releaser = new Releaser(CommandLineParameters);
- releaser.Execute();
+ if (!File.Exists(commandLineParameters.FileForVersion))
+ {
+ Log.Error($"File not exists: {commandLineParameters.FileForVersion}");
+ Environment.Exit(160);
+ }
+
+ var extension = Path.GetExtension(commandLineParameters.FileForVersion)?.ToLower();
+ if (extension != ".dll" &&
+ extension != ".exe")
+ {
+ Log.Error($"File type not supported: {extension}");
+ Environment.Exit(160);
+ }
+
+ foreach (var attachment in commandLineParameters.ReleaseAttachments)
+ {
+ if (!File.Exists(attachment))
+ {
+ Log.Error($"Attachment file not found: {attachment}");
+ Environment.Exit(160);
+ }
+ }
+
+ LogParameter(nameof(commandLineParameters.GitHubRepo), commandLineParameters.GitHubRepo);
+ LogParameter(nameof(commandLineParameters.GitHubToken), commandLineParameters.GitHubToken);
+ LogParameter(nameof(commandLineParameters.FileForVersion), commandLineParameters.FileForVersion);
+ LogParameter(nameof(commandLineParameters.IsChangelogFileCreationEnabled),
+ commandLineParameters.IsChangelogFileCreationEnabled);
+ LogParameter(nameof(commandLineParameters.IsPreRelease), commandLineParameters.IsPreRelease);
+ LogParameter(nameof(commandLineParameters.IsUpdateOnly), commandLineParameters.IsUpdateOnly);
+ LogParameter(nameof(commandLineParameters.IssueFilterLabel), commandLineParameters.IssueFilterLabel);
+ LogParameter(nameof(commandLineParameters.IssueLabels), commandLineParameters.IssueLabels);
+ LogParameter(nameof(commandLineParameters.ReleaseAttachments), commandLineParameters.ReleaseAttachments);
+
+ return commandLineParameters;
}
private static void LogParameter(string name, object value)
diff --git a/src/GitHubReleaser/Properties/launchSettings.json b/src/GitHubReleaser/Properties/launchSettings.json
index 132fc58..4a47b2c 100644
--- a/src/GitHubReleaser/Properties/launchSettings.json
+++ b/src/GitHubReleaser/Properties/launchSettings.json
@@ -2,7 +2,7 @@
"profiles": {
"GitHubReleaser": {
"commandName": "Project",
- "commandLineArgs": "/create-changelog-file:\"true\" /update-only:\"false\" /release-attachments:\"TODO\" \"TODO\" /issue-filter-label:\"not-in-changelog\" /issue-labels:\"bug;Bug\" \"feature;Feature\" /pre-release:\"false\" /file-for-version:\"TODO\" /github-token:\"TODO\" /github-repo:\"Suplanus/GitHubReleaser\""
+ "commandLineArgs": "/github-repo:\"Suplanus/GitHubReleaser\" /github-token:\"Fill out Secrets.cs\" /file-for-version:\".\\GitHubReleaser.exe\" /create-changelog-file:\"true\" /update-only:\"false\" /release-attachments:\".\\..\\..\\..\\..\\..\\demodata\\example.zip\" /issue-filter-label:\"not-in-changelog\" /issue-labels:\"bug;Bug\" \"feature;Feature\" /pre-release:\"false\""
}
}
}
\ No newline at end of file