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.