Skip to content

Commit 0341198

Browse files
author
Antoine Aubry
committed
Setup a release task to make it easier to release a new version
1 parent a66b0d5 commit 0341198

40 files changed

+581
-423
lines changed

GitVersion.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
mode: Mainline
1+
mode: Mainline
2+
increment: None
3+
commit-message-incrementing: MergeMessageOnly
4+
branches:
5+
master:
6+
commit-message-incrementing: MergeMessageOnly
7+
increment: None

README.md

Lines changed: 2 additions & 382 deletions
Large diffs are not rendered by default.

YamlDotNet.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Global
5959
{689D2A30-C52E-4CF8-8BA1-3178F4EB245A}.Debug|Any CPU.Build.0 = Debug|Any CPU
6060
{689D2A30-C52E-4CF8-8BA1-3178F4EB245A}.Debug-AOT|Any CPU.ActiveCfg = Debug|Any CPU
6161
{689D2A30-C52E-4CF8-8BA1-3178F4EB245A}.Release|Any CPU.ActiveCfg = Release|Any CPU
62+
{689D2A30-C52E-4CF8-8BA1-3178F4EB245A}.Release|Any CPU.Build.0 = Release|Any CPU
6263
{A9F67018-0240-4D16-A4EA-BCB780D0AF05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
6364
{A9F67018-0240-4D16-A4EA-BCB780D0AF05}.Debug|Any CPU.Build.0 = Debug|Any CPU
6465
{A9F67018-0240-4D16-A4EA-BCB780D0AF05}.Debug-AOT|Any CPU.ActiveCfg = Debug|Any CPU

appveyor.yml

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
version: 0.0.{build}
22

3+
branches:
4+
only:
5+
# Releases must be built from a release tag
6+
- /^(?!master).+$/
7+
- /^master.+$/
8+
39
image: Visual Studio 2017
410

11+
test: off
12+
513
build:
614
publish_nuget: true
715

@@ -12,21 +20,31 @@ build_script:
1220
- ps: .\build.ps1 -Target Package # -Verbosity Diagnostic -buildVerbosity=Verbose
1321

1422
artifacts:
15-
- path: YamlDotNet\bin\Release\net45
16-
name: Release-Net45
17-
1823
- path: YamlDotNet\bin\Release\netstandard1.3
1924
name: Release-NetStandard
2025

26+
- path: YamlDotNet\bin\Release\net45
27+
name: Release-Net45
28+
2129
- path: YamlDotNet\bin\Release\net35
30+
name: Release-Net35
31+
32+
- path: YamlDotNet\bin\Release\net20
33+
name: Release-Net20
34+
35+
- path: YamlDotNet\bin\Release\net40
2236
name: Release-UnitySubset-v35
2337

2438
- path: YamlDotNet\bin\*.nupkg
2539

26-
deploy:
27-
- provider: NuGet
28-
api_key:
29-
secure: GMc0xUTASI8qTPK1/eN/GFs6PBhPFBin1TT1hE5N8NlkU7VSBx3z4zQinSv/ICmx
30-
artifact: /.*\.nupkg/
31-
32-
test: off
40+
for:
41+
- branches:
42+
only:
43+
- master
44+
skip_non_tags: true
45+
46+
deploy:
47+
- provider: NuGet
48+
api_key:
49+
secure: GMc0xUTASI8qTPK1/eN/GFs6PBhPFBin1TT1hE5N8NlkU7VSBx3z4zQinSv/ICmx
50+
artifact: /.*\.nupkg/

build.cake

Lines changed: 162 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
#tool "nuget:?package=Mono.TextTransform&version=1.0.0"
33
#tool "nuget:?package=GitVersion.CommandLine&version=4.0.0"
44
#addin "nuget:?package=Cake.Incubator&version=4.0.1"
5+
#addin "nuget:?package=Cake.SemVer&version=3.0.0"
6+
#addin "nuget:?package=semver&version=2.0.4"
7+
#addin "nuget:?package=ConsoleMenuLib&version=3.2.1"
8+
#addin "nuget:?package=System.Interactive.Async&version=3.2.0"
59

610
using System.Reflection;
711
using System.Text.RegularExpressions;
812
using System.Xml.Linq;
913
using Cake.Incubator.LoggingExtensions;
14+
using ConsoleUi;
1015

1116
//////////////////////////////////////////////////////////////////////
1217
// ARGUMENTS
@@ -33,7 +38,7 @@ if (!IsRunningOnWindows())
3338
releaseConfigurations.Add("Debug-AOT");
3439
}
3540

36-
var nugetVersion = "0.0.1";
41+
GitVersion version = null;
3742

3843
//////////////////////////////////////////////////////////////////////
3944
// TASKS
@@ -62,42 +67,37 @@ Task("Restore-NuGet-Packages")
6267
NuGetRestore(solutionPath);
6368
});
6469

65-
Task("Show-Version")
70+
Task("Get-Version")
6671
.Does(() =>
6772
{
68-
var version = GitVersion(new GitVersionSettings
73+
version = GitVersion(new GitVersionSettings
6974
{
7075
UpdateAssemblyInfo = false,
7176
});
7277

73-
Information("Version:\n{0}", version.Dump());
78+
if (AppVeyor.IsRunningOnAppVeyor)
79+
{
80+
if (!string.IsNullOrEmpty(version.PreReleaseTag))
81+
{
82+
version.NuGetVersion = string.Format("{0}-{1}{2}", version.MajorMinorPatch, version.PreReleaseLabel, AppVeyor.Environment.Build.Version.Replace("0.0.", "").PadLeft(4, '0'));
83+
}
84+
AppVeyor.UpdateBuildVersion(version.NuGetVersion);
85+
}
86+
87+
Information("Building release:\n{0}", version.Dump());
7488
});
7589

7690
Task("Set-Build-Version")
91+
.IsDependentOn("Get-Version")
7792
.Does(() =>
7893
{
79-
var version = GitVersion(new GitVersionSettings
80-
{
81-
UpdateAssemblyInfo = false,
82-
});
83-
nugetVersion = version.NuGetVersion;
84-
8594
var assemblyInfo = TransformTextFile("YamlDotNet/Properties/AssemblyInfo.template")
8695
.WithToken("assemblyVersion", $"{version.Major}.0.0.0")
8796
.WithToken("assemblyFileVersion", $"{version.MajorMinorPatch}.0")
88-
.WithToken("assemblyInformationalVersion", nugetVersion)
97+
.WithToken("assemblyInformationalVersion", version.NuGetVersion)
8998
.ToString();
9099

91100
System.IO.File.WriteAllText("YamlDotNet/Properties/AssemblyInfo.cs", assemblyInfo);
92-
93-
if (AppVeyor.IsRunningOnAppVeyor)
94-
{
95-
if (!string.IsNullOrEmpty(version.PreReleaseTag))
96-
{
97-
nugetVersion = string.Format("{0}-{1}{2}", version.MajorMinorPatch, version.PreReleaseLabel, AppVeyor.Environment.Build.Version.Replace("0.0.", "").PadLeft(4, '0'));
98-
}
99-
AppVeyor.UpdateBuildVersion(nugetVersion);
100-
}
101101
});
102102

103103
Task("Build")
@@ -168,11 +168,132 @@ Task("Package")
168168

169169
NuGetPack(finalNuspecFile, new NuGetPackSettings
170170
{
171-
Version = nugetVersion,
171+
Version = version.NuGetVersion,
172172
OutputDirectory = Directory("YamlDotNet/bin"),
173173
});
174174
});
175175

176+
Task("Release")
177+
.IsDependentOn("Get-Version")
178+
.WithCriteria(() => version.BranchName == "master", "Releases must be created from the master branch")
179+
.Does(() =>
180+
{
181+
// Find previous release
182+
var releases = RunProcess("git", "tag", "--list", "--merged", "master", "--format=\"%(refname:short)\"", "v*")
183+
.Select(tag => new
184+
{
185+
Tag = tag,
186+
Version = ParseSemVer(tag.TrimStart('v')),
187+
})
188+
.OrderByDescending(v => v.Version)
189+
.ToList();
190+
191+
var previousVersion = releases.First();
192+
193+
Information("The previous release was {0}", previousVersion.Version);
194+
195+
var releaseNotesPath = Directory("releases").Path.CombineWithFilePath($"{version.NuGetVersion}.md").FullPath;
196+
Action scaffoldReleaseNotes = () =>
197+
{
198+
// Get the git log to scaffold the release notes
199+
string currentHash = null;
200+
var commits = RunProcess("git", "rev-list", $"{previousVersion.Tag}..HEAD", "--first-parent", "--reverse", "--pretty=tformat:%B")
201+
.Select(l =>
202+
{
203+
var match = Regex.Match(l, "^commit (?<hash>[a-f0-9]+)$");
204+
if (match.Success)
205+
{
206+
currentHash = match.Groups["hash"].Value;
207+
}
208+
return new
209+
{
210+
message = l,
211+
commit = currentHash
212+
};
213+
})
214+
.GroupBy(l => l.commit, (k, list) => new
215+
{
216+
commit = k,
217+
message = list
218+
.Skip(1)
219+
.Select(l => l.message.Trim())
220+
.Where(l => !string.IsNullOrEmpty(l))
221+
.ToList()
222+
});
223+
224+
var log = commits
225+
.Select(c => c.message.Select((l, i) => $"{(i == 0 ? '-' : ' ')} {l}"))
226+
.Select(c => string.Join(" \n", c));
227+
228+
var releaseNotes = $"# Release {version.NuGetVersion}\n\n{string.Join("\n\n", log)}";
229+
System.IO.File.WriteAllText(releaseNotesPath, releaseNotes);
230+
};
231+
232+
if (!FileExists(releaseNotesPath))
233+
{
234+
scaffoldReleaseNotes();
235+
}
236+
237+
// Show release menu
238+
Menu menu = null;
239+
240+
Action updateMenuDescription = () => menu.Description = System.IO.File.ReadAllText(releaseNotesPath);
241+
242+
menu = new Menu(
243+
"Release",
244+
new ActionMenuItem("Edit release notes", ctx =>
245+
{
246+
ctx.SuppressPause();
247+
RunProcess(IsRunningOnWindows() ? "notepad" : "nano", releaseNotesPath);
248+
updateMenuDescription();
249+
}),
250+
new ActionMenuItem("Scaffold release notes", async ctx =>
251+
{
252+
ctx.SuppressPause();
253+
if (await ctx.UserInterface.Confirm(true, "This will erase the current draft. Are you sure ?"))
254+
{
255+
scaffoldReleaseNotes();
256+
updateMenuDescription();
257+
}
258+
}),
259+
new ActionMenuItem("Release", async ctx =>
260+
{
261+
ctx.SuppressPause();
262+
if (await ctx.UserInterface.Confirm(true, "This will publish a new release. Are you sure ?"))
263+
{
264+
menu.ShouldExit = true;
265+
266+
var previousReleases = releases
267+
.Select(r => new
268+
{
269+
r.Version,
270+
Path = $"releases/{r.Version}.md"
271+
})
272+
.Where(r => FileExists(r.Path))
273+
.Select(r => $"- [{r.Version}]({r.Path})");
274+
275+
var releaseNotesFile = string.Join("\n",
276+
"# Release notes",
277+
menu.Description.Replace("# Release", "## Release"),
278+
"# Previous releases",
279+
string.Join("\n", previousReleases)
280+
);
281+
282+
System.IO.File.WriteAllText("RELEASE_NOTES.md", releaseNotesFile);
283+
284+
RunProcess("git", "add", $"\"{releaseNotesPath}\"", "RELEASE_NOTES.md");
285+
RunProcess("git", "commit", "-m", $"\"Prepare release {version.NuGetVersion}\"");
286+
RunProcess("git", "tag", $"v{version.NuGetVersion}");
287+
288+
ctx.UserInterface.Info($"Your release is ready. Remember to push it using the following commands:\n\n git push && git push origin v{version.NuGetVersion}");
289+
}
290+
})
291+
);
292+
293+
updateMenuDescription();
294+
new ConsoleUi.Console.ConsoleMenuRunner().Run(menu).Wait();
295+
});
296+
176297
Task("Document")
177298
.IsDependentOn("Build")
178299
.Does(() =>
@@ -297,23 +418,34 @@ void BuildSolution(string solutionPath, string configuration, Verbosity verbosit
297418
settings
298419
.SetVerbosity(verbosity)
299420
.SetConfiguration(configuration)
300-
.WithProperty("Version", nugetVersion);
421+
.WithProperty("Version", version.NuGetVersion);
301422
});
302423
}
303424

304-
void RunProcess(string processName, params string[] arguments)
425+
IEnumerable<string> RunProcess(string processName, params string[] arguments)
305426
{
306-
var exitCode = StartProcess(processName, new ProcessSettings().WithArguments(a =>
427+
var settings = new ProcessSettings()
428+
.SetRedirectStandardOutput(true)
429+
.WithArguments(a =>
430+
{
431+
foreach (var argument in arguments)
432+
{
433+
a.Append(argument);
434+
}
435+
});
436+
437+
using (var process = StartAndReturnProcess(processName, settings))
307438
{
308-
foreach (var argument in arguments)
439+
var output = new List<string>(process.GetStandardOutput());
440+
process.WaitForExit();
441+
442+
var exitCode = process.GetExitCode();
443+
if (exitCode != 0)
309444
{
310-
a.Append(argument);
445+
throw new Exception(string.Format("{0} failed with exit code {1}", processName, exitCode));
311446
}
312-
}));
313447

314-
if (exitCode != 0)
315-
{
316-
throw new Exception(string.Format("{0} failed with exit code {1}", processName, exitCode));
448+
return output;
317449
}
318450
}
319451

releases/2.0.0.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Release 2.0.0
2+
3+
* YamlSerializer has been replaced by the Deserializer class. It offer the same functionality of YamlSerializer but is easier to maintain and extend.
4+
* **Breaking change:** DeserializationOverrides is no longer supported. If you need this, please file a bug and we will analyze it.
5+
* **Breaking change:** IDeserializationContext is no longer supported. If you need this, please file a bug and we will analyze it.
6+
* Tag mappings are registered directly on the Deserializer using RegisterTagMapping()
7+
* ObjectFactory is specified in the constructor, if required.
8+
9+
* Bug fixes to the Serializer:
10+
* Fix bug when serializing lists with nulls inside. e9019d5f224f266e88d9882502f83f0c6865ec24
11+
12+
* Adds a YAML editor add-in for Visual Studio 2012. Available on the [Visual Studio Gallery](http://visualstudiogallery.msdn.microsoft.com/34423c06-f756-4721-8394-bc3d23b91ca7).

releases/2.1.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Release 2.1.0
2+
3+
TODO
4+

releases/2.2.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Release 2.2.0
2+
3+
TODO
4+

releases/3.0.0.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Release 3.0.0
2+
3+
* Fix issue #26: Use the actual type of the objects instead of the statically detected one.
4+
* Merged the Core, Converters and RepresentationModel assemblies. **The NuGet packages YamlDotNet.Core and YamlDotNet.RepresentationModel are now a single package, named YamlDotNet**.
5+
* Removed YamlDotNet.Configuration and YamlDotNet.Converters.
6+
* Line numbers in error messages now start at one.
7+
* TypeConverter is now used to cast list items.
8+
* Various code improvements.
9+
* More and better unit tests.
10+

releases/3.1.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Release 3.1.0
2+
3+
* Add a parameter to the deserializer to ignore unmapped properties in YAML.
4+

0 commit comments

Comments
 (0)