Cake.Net. Useful scripts for AngularJS, dotnet core, docker application
There is a great cross-platform build automation tool - Cake.Net.
I started using it and created some useful scripts to Release and Publish new version of application.
I am using AngularJS as frontend framework, asp net core (dotnet core) as backend framework, git as source system and docker to deploy and run application on remote server.
So it is a small cake script to release a new version of application:
#addin "Cake.Docker" #addin "Cake.FileHelpers" // Release: ./build.sh -t Release "-packageVersion=x.x.x.x" // Publish: ./build.sh -t Publish "-packageVersion=x.x.x.x" "-env=one" // Delete release: ./build.sh -t Delete "-packageVersion=x.x.x.x" var target = Argument<string>("target"); var version = Argument<string>("packageVersion"); public class Settings { public string SshAddress; public string SshPort; public string HomePath; } Settings sets; Task("SelectEnvironment") .Does(()=>{ var env = Argument<string>("env"); var environments = new Dictionary<string, Settings> { ["one"] = new Settings { SshAddress = "root@66.66.66.66", SshPort = "22", HomePath = "/root/Templates" }, ["two"] = new Settings{ SshAddress = "root@99.99.99.99", SshPort = "26", HomePath = "/home/Templates" } }; sets = environments[env]; }); Task("Publish") .IsDependentOn("SelectEnvironment") .IsDependentOn("CheckAllCommitted") .IsDependentOn("CheckoutTag") .IsDependentOn("BuildAngular") .IsDependentOn("BuildDocker") .IsDependentOn("CheckoutBranch") .IsDependentOn("PushToGitLab") .IsDependentOn("PublishService") .Does(()=> { Information("Finished!"); }); Task("Release") .IsDependentOn("SetVersion") .IsDependentOn("ReleaseNotes") .IsDependentOn("Commit") .IsDependentOn("Build") .IsDependentOn("PushTagToGit") .Does(()=> { Information("Finished!"); }); //build angular Task("Build Angular") .Does(() => { StartProcess("ng", "build"); }); // delete release (tag) Task("Delete") .Does(()=> { StartProcess("git", $"tag --delete v{version}"); StartProcess("git", $"push --delete origin v{version}"); }); // add release notes to historys Task("ReleaseNotes") .Does(()=> { IEnumerable<string> redirectedOutput; StartProcess("git", new ProcessSettings { Arguments = $"describe --abbrev=0 --tags", RedirectStandardOutput = true }, out redirectedOutput ); var previousVersion = redirectedOutput.First(); Information(previousVersion); IEnumerable<string> redirectedOutput2; StartProcess("git", new ProcessSettings { Arguments = $"log --pretty=\"%s\" HEAD...{previousVersion}", RedirectStandardOutput = true }, out redirectedOutput2 ); FileAppendLines("./src/HISTORY.txt", new string[]{$"------release v{version}-----"}); FileAppendLines("./src/HISTORY.txt", redirectedOutput2.ToArray()); }); // push docker image to gitlab Task("PushToGitLab") .Does(()=>{ StartProcess("docker", $"push registry.gitlab.com/counterra/service:{version}"); }); // build project locally Task("Build") .Does(() => { DotNetCoreRestore("./src/counterra.csproj"); CleanDirectory("./artifacts"); var settings = new DotNetCorePublishSettings { Framework = "netcoreapp1.1", Configuration = "Release", OutputDirectory = "./artifacts/" }; DotNetCorePublish("./src/counterra.csproj", settings); }); // set new version in project file Task("SetVersion") .Does(()=> { var file = File("./src/counterra.csproj"); XmlPoke(file, "/Project/PropertyGroup/Version", version); }); // build docker Task("BuildDocker") .Does(() => { var settings = new DockerBuildSettings { Tag = new []{ $"registry.gitlab.com/counterra/service:{version}" } }; DockerBuild(settings, "."); }); // go to remote server and replace docker there Task("PublishService") .Does(() => { StartProcess("scp", $"-P {sets.SshPort} {sets.SshAddress}:{sets.HomePath}/server/docker-compose.yml ./artifacts/"); ReplaceRegexInFiles("./artifacts/docker-compose.yml", @"registry.gitlab.com/counterra/service:\d+\.\d+\.\d+\.\d+", $"registry.gitlab.com/counterra/service:{version}"); StartProcess("ssh", $"-p {sets.SshPort} {sets.SshAddress} cd {sets.HomePath}/server/; docker-compose stop service"); StartProcess("ssh", $"-p {sets.SshPort} {sets.SshAddress} cd {sets.HomePath}/server/; docker-compose rm -f service"); StartProcess("scp", $"-P {sets.SshPort} ./artifacts/docker-compose.yml {sets.SshAddress}:{sets.HomePath}/server/"); StartProcess("ssh", $"-p {sets.SshPort} {sets.SshAddress} cd {sets.HomePath}/server/; docker-compose create service"); StartProcess("ssh", $"-p {sets.SshPort} {sets.SshAddress} cd {sets.HomePath}/server/; docker-compose start service"); }); // push new tag Task("PushTagToGit") .Does(() => { StartProcess("git", $"tag v{version}"); StartProcess("git", "push --tags"); }); // checkout tag Task("CheckoutTag") .Does(() => { StartProcess("git", $"checkout tags/v{version}"); }); // checkout master Task("CheckoutBranch") .Does(() => { StartProcess("git", $"checkout master"); }); // commit all to branch and push it Task("Commit") .Does(() => { StartProcess("git", $"add ."); StartProcess("git", $"commit -m \"Release v{version}\" "); StartProcess("git", $"push"); }); // check that we haven't uncommitted files Task("CheckAllCommitted") .Does(() => { IEnumerable<string> redirectedOutput; StartProcess("git", new ProcessSettings { Arguments = "status", RedirectStandardOutput = true }, out redirectedOutput ); if (!redirectedOutput.LastOrDefault().Contains("nothing to commit")) { throw new Exception("Exists uncommitted changes"); } }); RunTarget(target);
It is a script to build released version and publish a docker container to a server:
// Release: ./build.sh -t Release "-packageVersion=x.x.x.x" // Publish: ./build.sh -t Publish "-packageVersion=x.x.x.x" "-env=counterra" // Delete release: ./build.sh -t Delete "-packageVersion=x.x.x.x" var target = Argument<string>("target"); var version = Argument<string>("packageVersion"); public class Settings { public string SshAddress; public string SshPort; public string HomePath; } Settings sets; Task("SelectEnvironment") .Does(()=>{ var env = Argument<string>("env"); var environments = new Dictionary<string, Settings> { ["counterra"] = new Settings { SshAddress = "root@83.220.171.23", SshPort = "22", HomePath = "/root/Templates" }, ["tj"] = new Settings{ SshAddress = "vorsa@195.14.96.218", SshPort = "26", HomePath = "/home/vorsa" } }; sets = environments[env]; }); Task("Publish") .IsDependentOn("SelectEnvironment") .IsDependentOn("CheckAllCommitted") .IsDependentOn("CheckoutTag") // build angular .IsDependentOn("Build Angular") .IsDependentOn("BuildDocker") .IsDependentOn("CheckoutBranch") .IsDependentOn("PushToGitLab") .IsDependentOn("PublishService") .Does(()=> { Information("Finished!"); }); Task("Release") .IsDependentOn("SetVersion") .IsDependentOn("ReleaseNotes") .IsDependentOn("Commit") .IsDependentOn("Build") .IsDependentOn("PushTagToGit") .Does(()=> { Information("Finished!"); }); Task("Publish") // check that current 'master' branch hasn't uncommitted changes .IsDependentOn("CheckAllCommitted") // checkout release tag .IsDependentOn("CheckoutTag") // build angular .IsDependentOn("Build Angular") // build release .IsDependentOn("Build") // return 'master' to HEAD as we have published release in artifacts folder .IsDependentOn("CheckoutBranch") // create docker image using published release .IsDependentOn("BuildDocker") // copy image to remote server .IsDependentOn("ExportDocker") // import new image, replace running container .IsDependentOn("PublishService") .Does(()=> { Information("Finished!"); }); Task("Build Angular") .Does(() => { StartProcess("ng", "build"); }); Task("Build") .Does(() => { DotNetCoreRestore($ "./src/{Settings.ProjectName}"); CleanDirectory("./artifacts"); var settings = new DotNetCorePublishSettings { Framework = "netcoreapp1.1", Configuration = "Release", OutputDirectory = "./artifacts/" }; DotNetCorePublish($ "./src/{Settings.ProjectName}", settings); // clean up artifacts folder DeleteDirectory("./artifacts/e2e", recursive:true); DeleteDirectory("./artifacts/src", recursive:true); DeleteFiles("./artifacts/ts*.json"); }); Task("BuildDocker") .Does(() => { var settings = new DockerBuildSettings { Tag = new []{ $ "{Settings.ContainerName}:{version}" } }; DockerBuild(settings, "."); }); Task("ExportDocker") .Does(() => { var settings = new DockerSaveSettings { Output = $ "./artifacts/{Settings.ContainerName}.{version}.tar" }; // save docker image to tar archive DockerSave(settings, new[] { $ "{Settings.ContainerName}:{version}"}); }); Task("PublishService") .Does(() => { // cope docker image to remote server StartProcess("scp", $ "-P {Settings.SshPort} ./artifacts/{Settings.ContainerName}.{version}.tar {Settings.SshAddress}:{Settings.HomePath}/"); // load copied image to docker on remote server StartProcess("ssh", $ "-p {Settings.SshPort} {Settings.SshAddress} docker load < {Settings.HomePath}/{Settings.ContainerName}.{version}.tar"); // copy docker-compose configuration from remote server to artifacts folder StartProcess("scp", $ "-P {Settings.SshPort} {Settings.SshAddress}:{Settings.HomePath}/docker-compose.yml ./artifacts/"); // replace the version of docker image in docker-compose configuration ReplaceRegexInFiles("./artifacts/docker-compose.yml", $ "{Settings.ContainerName}:\\d+\\.\\d+\\.\\d+\\.\\d+", $ "{Settings.ContainerName}:{version}"); // stop old docker container on server StartProcess("ssh", $ "-p {Settings.SshPort} {Settings.SshAddress} cd {Settings.HomePath}/; docker-compose stop {Settings.ContainerName}"); // delete old container StartProcess("ssh", $ "-p {Settings.SshPort} {Settings.SshAddress} cd {Settings.HomePath}/; docker-compose rm -f {Settings.ContainerName}"); // copy new docker-compose configuration to remote server StartProcess("scp", $ "-P {Settings.SshPort} ./artifacts/docker-compose.yml {Settings.SshAddress}:{Settings.HomePath}/"); // recreate docker container, it will create a new version StartProcess("ssh", $ "-p {Settings.SshPort} {Settings.SshAddress} cd {Settings.HomePath}/; docker-compose create {Settings.ContainerName}"); // start new docker container StartProcess("ssh", $ "-p {Settings.SshPort} {Settings.SshAddress} cd {Settings.HomePath}/; docker-compose start {Settings.ContainerName}"); }); Task("CheckoutTag") .Does(() => { StartProcess("git", $ "checkout tags/v{version}"); }); Task("CheckoutBranch") .Does(() => { StartProcess("git", $ "checkout master"); }); Task("CheckAllCommitted") .Does(() => { IEnumerable<string> redirectedOutput; var exitCodeWithArgument = StartProcess("git", new ProcessSettings{ Arguments = "status", RedirectStandardOutput = true }, out redirectedOutput ); if (!redirectedOutput.LastOrDefault().Contains("nothing to commit")) { throw new Exception("Exists uncommitted changes"); } }); RunTarget(target);
I am running service using docker compose like:
version: '2' services: ContainerName: image: ContainerName:x.x.x.x
Thanks.