ã¿ãªããããã«ã¡ã¯ïŒ CakeïŒCïŒMakeïŒã®ãããªããŒã«ã«ã€ããŠè©±ãããã§ãã
ã§ã¯ãCakeãšã¯äœã§ããïŒ
Cakeã¯ããœãŒã¹ã³ãŒãããã®ãã€ããªã®ã³ã³ãã€ã«ããã¡ã€ã«ã®ã³ããŒããã©ã«ããŒã®äœæ/æ¶å»/åé€ãã¢ãŒãã£ãã¡ã¯ãã®ã¢ãŒã«ã€ãããã²ããããã±ãŒãžã®ãããã³ã°ããŠãããå®è¡ãªã©ã®ããšãè¡ãããã«ãDSLãCïŒæ§æã§äœ¿çšããã¯ãã¹ãã©ãããã©ãŒã ãã«ãã·ã¹ãã ã§ã-ãã¹ããªã©ã Cakeã«ã¯ãéçºãããã¢ããªã³ã·ã¹ãã ïŒå€ãã®å Žånugetã«ããã±ãŒãžåãããCïŒã¯ã©ã¹ã®ã¿ïŒããããŸãã ããããã®äŸ¿å©ãªé¢æ°ãæ¢ã«Cakeã«çµã¿èŸŒãŸããŠããããšã«æ³šæããŠãã ãããããã«ãã»ãšãã©ãã¹ãŠã®å Žåããããã¯ã³ãã¥ããã£ã«ãã£ãŠäœæãããéåžžã«ããŸãé åžãããŠããŸãã
Takeã¯ã RakeãFakeãªã©ã®ä»ã®åæ§ã®ã·ã¹ãã ã«äŒŒãã äŸåé¢ä¿ããŒã¹ã®ããã°ã©ãã³ã°ãšåŒã°ããããã°ã©ãã³ã°ã¢ãã«ã䜿çšããŸãã ãã®ã¢ãã«ã®æ¬è³ªã¯ãããã°ã©ã ãå®è¡ããããã«ã¿ã¹ã¯ãšã¿ã¹ã¯éã®äŸåé¢ä¿ãå®çŸ©ããããšã§ãã ãã®ã¢ãã«ã®è©³çŽ°ã«ã€ããŠã¯ã Martin Fowlerãã芧ãã ããã
åæ§ã®ã¢ãã«ã¯ãã¢ã»ã³ããªããã»ã¹ãããã€ãã®ã¿ã¹ã¯ãšãããã®éã®äŸåé¢ä¿ãšããŠæ³åãããŸãã ãã®å Žåãå®è¡ã¯éã®é åºã§è«ççã§ããå®è¡ãããã¿ã¹ã¯ãšãã®äŸåé¢ä¿ã瀺ããCakeã¯å®è¡ã§ããã¿ã¹ã¯ã決å®ãïŒäŸåé¢ä¿ã¯èš±å¯ãŸãã¯æ¬ èœïŒãããããå®è¡ããŸãã
ãããã£ãŠãããšãã°ãAãå®è¡ãããããBãšCã«äŸåããBã¯Dã«äŸåããŸãããããã£ãŠãCakeã¯æ¬¡ã®é åºã§ããããå®è¡ããŸãã
- CãŸãã¯D
- B
- A
Cakeã®ã¿ã¹ã¯ã¯ãéåžžãã¢ã»ã³ããª/ãã¹ã/ããã±ãŒãžã³ã°äœæ¥ã®å®å šãªéšåã§ãã 次ã®ããã«å®£èšãããŠããŸã
Task("A") // .Does(() => { // Task A });
IsDependentOnã¡ãœããã䜿çšããŠãã¿ã¹ã¯Aãã¿ã¹ã¯Bãªã©ã«äŸåããŠããããšã瀺ãã«ã¯ïŒ
Task("A") // .IsDependentOn("B") .Does(() => { // Task A });
WithCriteriaã¡ãœããã䜿çšããŠãã¿ã¹ã¯ãå®è¡ããæ¡ä»¶ãšå®è¡ããªãæ¡ä»¶ãç°¡åã«èšå®ããããšãã§ããŸãã
Task("B") // .IsDependentOn("C") .WithCriteria(DateTime.Now.Second % 2 == 0) .Does(() => { // Task A });
äžéšã®ã¿ã¹ã¯ãã¿ã¹ã¯Bã«äŸåããŠãããåºæºãfalseã®å Žåãã¿ã¹ã¯Bã¯å®è¡ãããŸããããå®è¡ãããŒã¯ããã«é²ãã§Bã®ã¿ã¹ã¯ãå®è¡ããŸãã
WithCriteriaã¡ãœããã®ãªãŒããŒããŒãããããŸããããã¯ãboolãè¿ãé¢æ°ããã©ã¡ãŒã¿ãŒãšããŠåãåããŸãã ãã®å ŽåãåŒã¯ãã¥ãŒãã¿ã¹ã¯ã«å°éãããšãã«ã®ã¿ã«ãŠã³ããããã¿ã¹ã¯ããªãŒã®æ§ç¯æã§ã¯ãããŸããã
Cakeã¯ã load ã reference ã tool ã breakãªã©ãç¹å®ã®ããªããã»ããµãã£ã¬ã¯ãã£ãããµããŒãããŠããŸãã ãããã®è©³çŽ°ã«ã€ããŠã¯ãããã¥ã¡ã³ãã®å¯Ÿå¿ããããŒãžãã芧ãã ãã ã
DevOpsæ代ã«èªåã®æã§ãããžã§ã¯ããåéãã人ã¯ããã»ã©å€ããªããšæããŸãã æåã¢ã»ã³ããªãšæ¯èŒããã¢ã»ã³ããªã·ã¹ãã ã®å©ç¹ã¯æããã§ããèªåæ§æããã»ã¹ã¯ãæåæäœãããåžžã«åªããŠããŸãã
Cã§éçºããå Žåã®Cakeã®å©ç¹
éåžžã«å€ãã®éžæè¢ãããã®ã§ããªãCakeã䜿çšããŸããïŒ CïŒã§éçºããŠããªãå Žåãã»ãšãã©äœããããŸããã ãŸããéçºããŠããå Žåãå¥ã®ããã°ã©ãã³ã°èšèªãåŠç¿ããŠåãã³ãŒãããŒã¹å ã§åç©åãäœæããå¿ èŠããªããããã¡ã€ã³ãããžã§ã¯ããèšè¿°ãããŠããã®ãšåãèšèªã§ã¢ã»ã³ããªã¹ã¯ãªãããèšè¿°ããããšã¯çã«ããªã£ãŠããŸãã ãããã RakeïŒRubyïŒ ã PsakeïŒPowershellïŒ ã FakeïŒFïŒïŒãªã©ã®ã¢ã»ã³ããªã·ã¹ãã ãç»å Žãå§ããçç±ã§ãã
確ãã«ãCïŒãããžã§ã¯ãããã«ãããæ¹æ³ã¯Cakeã ãã§ã¯ãããŸããã ãªãã·ã§ã³ãšããŠãçŽç²ãªMSBuildãPowershellãBatã¹ã¯ãªããããŸãã¯TeamcityãJenkinsãªã©ã®CIãµãŒããŒãäŸãšããŠäœ¿çšã§ããŸããããã¹ãŠã«é·æãšçæããããŸãã
- Bat / Bashãšåæ§ã«ãPowershellã¹ã¯ãªããã¯ä¿å®ãããªãå°é£ã§ã
- CïŒããŒã¹ã®DSLã¯ãMSBuildã®XMLããŒã¹ã®DSLã®æ§æãåªããŠããŸãã ããã«ãLinux / Macã§ã®MSBuildã®ãµããŒããç»å Žããã®ã¯ããã»ã©åã§ã¯ãããŸããã
- CIãµãŒããŒã¯ãã³ããŒããã¯ãå®è£ ããå€ãã®å ŽåãããŠã¹ã«ããããã°ã©ãã³ã°ããå¿ èŠãšããããããªããžããªå ã®ã³ãŒãã®ããŒãžã§ã³ãããã«ãããã»ã¹ã®ããŒãžã§ã³ããã€ã³ã解é€ããŸãããäžéšã®CIã·ã¹ãã ã§ã¯ãã³ãŒããšãšãã«ãã«ãããã»ã¹ã®èª¬æãå«ããã¡ã€ã«ãä¿åã§ããŸãã
- CIã䜿çšãããšãCIãµãŒããŒãšåãæ¹æ³ã§ããŒã«ã«ã«ã³ãŒããåéã§ããŸãã
ã±ãŒãã®ã€ã³ã¹ããŒã«
次ã«ãã¿ã¹ã¯ã䜿çšããŠã¹ã¯ãªãããå®è¡ããæ¹æ³ã«ã€ããŠèª¬æããŸãã Cakeã«ã¯ããã¹ãŠãè¡ãããŒãããŒããŒããããŸãã æåã§ããŠã³ããŒããããã次ã®powershellã³ãã³ãã䜿çšããŠããŠã³ããŒãã§ããŸãã
Invoke-WebRequest http://cakebuild.net/download/bootstrapper/windows -OutFile build.ps1
ããŠã³ããŒããããbuild.ps1ãã¡ã€ã«ã¯ ãå¿ èŠãªcake.exeããŸã ããŒããããŠããªãå Žåã¯ããŠã³ããŒããã次ã®ã³ãã³ãã§åŒã³åºããšãcakeã¹ã¯ãªããïŒããã©ã«ãã§ã¯build.cake ïŒãå®è¡ããŸãã
Powershell -File ".\build.ps1" -Configuration "Debug"
ã³ãã³ãã©ã€ã³åŒæ°ãbuild.ps1ã«æž¡ãããšãã§ããŸãããããå®è¡ãããŸãã ãããã¯ãããšãã°ã¢ã»ã³ããªã®æ§æãéåžžæ åœããconfigurationãªã©ã®çµã¿èŸŒã¿ããŸãã¯ç¬ç«ããŠèšå®ã§ããŸãããã®å Žåã次ã®2ã€ã®æ¹æ³ããããŸãã
- ScriptArgsãã©ã¡ãŒã¿ãŒã®å€ãšããŠæž¡ããŸãã
Powershell -File ".\build.ps1" -Script "version.cake" -ScriptArgs '--buildNumber="123"'
- build.ps1ãå€æŽããŠãæž¡ãããcake.exeåŒæ°ã転éããŸãã
äŸ
ããã§ã¯ãç·Žç¿ã«ç§»ããŸãããã å žåçãªnugetããã±ãŒãžã®ãã«ããµã€ã¯ã«ã¯ç°¡åã«æ³åã§ããŸãã
- dllãœãŒã¹ããMSBuildã䜿çšããŠãã«ãããŸã
- åäœãã¹ããå®è¡ããŸã
- nuspecã®èª¬æã«åŸã£ãŠããã¹ãŠããŸãšããŠnugetã«å ¥ããŸã
- Nugetãã£ãŒã
ãã«ãDLL
ãœãŒã¹ãããœãªã¥ãŒã·ã§ã³ãåéããã«ã¯ã2ã€ã®ããšãè¡ãå¿ èŠããããŸãã
- ãœãªã¥ãŒã·ã§ã³ãNuGetRestoreé¢æ°ã®äœ¿çšã«äŸåããŠããnugetããã±ãŒãžã埩å ãã
- æ§æãã©ã¡ãŒã¿ãŒãæž¡ãããšã«ããã DotNetBuildé¢æ°ãcakeã«çµã¿èŸŒã¿ãããã©ã«ãã§ãœãªã¥ãŒã·ã§ã³ããã«ãããŸãã
cake-dslã§ãœãªã¥ãŒã·ã§ã³ãæ§ç¯ããã¿ã¹ã¯ã«ã€ããŠèª¬æããŸãã
var configuration = Argument("configuration", "Debug"); Task("Build") .Does(() => { NuGetRestore("../Solution/Solution.sln"); DotNetBuild("../Solution/Solution.sln", x => x .SetConfiguration(configuration) .SetVerbosity(Verbosity.Minimal) .WithTarget("build") .WithProperty("TreatWarningsAsErrors", "false") ); }); RunTarget("Build");
ã¢ã»ã³ããªæ§æã¯ããããããããã©ã«ãå€ã®ããããã°ãã§åŒæ°é¢æ°ã䜿çšããŠãã³ãã³ãã©ã€ã³ã«ãã£ãŠåŒæ°ããèªã¿åãããŸãã RunTargeté¢æ°ã¯æå®ãããã¿ã¹ã¯ãèµ·åããã±ãŒãã¹ã¯ãªããã®æ£ããåäœãããã«ç¢ºèªã§ããããã«ããŸãã
åäœãã¹ã
nunit v3.xãšäºææ§ã®ããåäœãã¹ããå®è¡ããã«ã¯ã NUnit3é¢æ°ãå¿ èŠã§ããããã¯Cakeã«å«ãŸããŠããªããããïŒtoolããªããã»ããµãã£ã¬ã¯ãã£ããä»ããæ¥ç¶ãå¿ èŠã§ãã #toolãã£ã¬ã¯ãã£ãã䜿çšãããšãnugetããã±ãŒãžã®ããŒã«ãæ¥ç¶ã§ããŸããããã䜿çšããŸãã
#tool "nuget:?package=NUnit.ConsoleRunner&version=3.6.0"
ããã«ãã¿ã¹ã¯èªäœã¯éåžžã«ã·ã³ãã«ã§ããããšãããããŸããã ãã¡ããããã«ãã¿ã¹ã¯ã«äŸåããããšãå¿ããªãã§ãã ããã
#tool "nuget:?package=NUnit.ConsoleRunner&version=3.6.0" Task("Tests::Unit") .IsDependentOn("Build") .Does(()=> { NUnit3(@"..\Solution\MyProject.Tests\bin\" + configuration + @"\MyProject.Tests.dll"); }); RunTarget("Tests::Unit");
ãã¹ãŠããã²ããã«è©°ã蟌ã¿ãŸã
ã¢ã»ã³ããªãnugetã«ããã±ãŒãžåããã«ã¯ã次ã®nugetä»æ§ã䜿çšããŸãã
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>Solution</id> <version>1.0.0</version> <title>Test solution for demonstration purposes</title> <description> Test solution for demonstration purposes </description> <authors>Gleb Smagliy</authors> <owners>Gleb Smagliy</owners> <requireLicenseAcceptance>false</requireLicenseAcceptance> <tags></tags> <references> <reference file="MyProject.dll" /> </references> </metadata> <files> <file src=".\MyProject.dll" target="lib\net45"/> <file src=".\MyProject.pdb" target="lib\net45"/> </files> </package>
build.cakeã¹ã¯ãªãããå«ããã©ã«ããŒã«é 眮ããŸãã Packã¿ã¹ã¯ãå®è¡ãããšãããã±ãŒãžåã«å¿ èŠãªãã¹ãŠã®ã¢ãŒãã£ãã¡ã¯ããã.. \ãArtefactsããã©ã«ããŒã«è»¢éãããŸãã ãããè¡ãã«ã¯ã EnsureDirectoryExistsé¢æ°ã䜿çšããŠååšããããšã確èªãïŒååšããªãå Žåã¯äœæãïŒãCakeã«çµã¿èŸŒãŸããŠããCleanDirectoryé¢æ°ã䜿çšããŠåé€ããŸãã ãã¡ã€ã«ã³ããŒæ©èœã®å©ããåããŠãå¿ èŠãªdllãšpdbãarefactoryãã©ã«ããŒã«ç§»åããŸãã
ããã©ã«ãã§ã¯ãã¢ã»ã³ãã«ãããnupkgã¯çŸåšã®ãã©ã«ããŒã«ããããããã©ã«ã㌠".. \ package"ãOutputDirectoryãšããŠæå®ã ããããäœæããã³ã¯ãªãŒã³ã¢ããããŸãã
Task("Pack") .IsDependentOn("Tests::Unit") .Does(()=> { var packageDir = @"..\package"; var artefactsDir = @"..\.artefacts"; MoveFiles("*.nupkg", packageDir); EnsureDirectoryExists(packageDir); CleanDirectory(packageDir); EnsureDirectoryExists(artefactsDir); CleanDirectory(artefactsDir); CopyFiles(@"..\Solution\MyProject\bin\" + configuration + @"\*.dll", artefactsDir); CopyFiles(@"..\Solution\MyProject\bin\" + configuration + @"\*.pdb", artefactsDir); CopyFileToDirectory(@".\Solution.nuspec", artefactsDir); NuGetPack(new FilePath(artefactsDir + @"\Solution.nuspec"), new NuGetPackSettings { OutputDirectory = packageDir }); }); RunTarget("Pack");
å ¬éãã
ããã±ãŒãžãå ¬éããã«ã¯ã NuGetPushé¢æ°ã䜿çšããŸã ãããã¯ãnupkgãã¡ã€ã«ãžã®ãã¹ãšãèšå®ïŒnugetãã£ãŒããžã®ãªã³ã¯ãšAPIããŒã䜿çšããŸãã ãã¡ãããAPIããŒããªããžããªã«ä¿åããã®ã§ã¯ãªãã Argumenté¢æ°ã䜿çšããŠå€éšã«å床枡ããŸãã nupkgã®å Žåã¯ã ããã±ãŒãžãã£ã¬ã¯ããªå ã®æåã®ãã¡ã€ã«ãååŸãã GetFilesã䜿çšããŠãã¹ã¯ãäžèŽãããŸãã ããã±ãŒãžãäœæããåã«ãã£ã¬ã¯ããªã以åã«ã¯ãªãŒã³ã¢ãããããŠããããããããå¯èœã§ãã ãã®ãããå ¬éã¿ã¹ã¯ã¯æ¬¡ã®dslã§èšè¿°ãããŸãã
var nugetApiKey = Argument("NugetApiKey", ""); Task("Publish") .IsDependentOn("Pack") .Does(()=> { NuGetPush(GetFiles(@"..\package\*.nupkg").First(), new NuGetPushSettings { Source = "https://www.nuget.org/api/v2", ApiKey = nugetApiKey }); }); RunTarget("Publish");
ããªãã®äººçãç°¡çŽ å
cakeã¹ã¯ãªããããããã°ããŠããéããããŠåã«nugetããã±ãŒãžããããã°ããããã«ãæ¯åãªã¢ãŒããã£ãŒãã«å ¬éããããšã¯ã§ããŸããã ããã§ã 調æ»ããWithCriteriaé¢æ°ã圹ç«ã¡ãŸãã ãã®ãã©ã°ã®å€ã«ãã£ãŠããã±ãŒãžããªã¢ãŒããã£ãŒãã«é 眮ãããã©ããã決å®ããããã«ããã©ã¡ãŒã¿ïŒããã©ã«ãã§ã¯falseã«èšå®ïŒã§ã¹ã¯ãªããã«PublishRemotelyãã©ã°ãæž¡ããŸãã ãã ãã RunTargeté¢æ°ã§æå®ãããã¿ã¹ã¯ãã¹ããããããšãcakeã¯ã¹ã¯ãªãããå®è¡ããŸããã ãããã£ãŠã Publishã«äŸåããæ¶ç©ºã®ç©ºã®ã¿ã¹ã¯BuildAndPublishãéå§ããŸãã
Task("BuildAndPublish") .IsDependentOn("Publish") .Does(()=> { }); RunTarget("BuildAndPublish");
ãããŠãå ¬éã¿ã¹ã¯ã«æ¡ä»¶ãè¿œå ããŸãã
var nugetApiKey = Argument("NugetApiKey", ""); var publishRemotely = Argument("PublishRemotely", false); Task("Publish") .IsDependentOn("Pack") .WithCriteria(publishRemotely) .Does(()=> { NuGetPush(GetFiles(@"..\package\*.nupkg").First(), new NuGetPushSettings { Source = "https://www.nuget.org/api/v2", ApiKey = nugetApiKey }); });
nugetããã±ãŒãžãæ§ç¯ããã³å ¬éããããã®ã¹ã¯ãªããã¯ã»ãšãã©æºåãã§ããŠããããã¹ãŠã®ã¿ã¹ã¯ãäžç·ã«çµåããã ãã§ãã ã³ãŒãã®æçµããŒãžã§ã³ã¯githubãªããžããªã«ãããŸãã
ãããã«
ã±ãŒãã®æãç°¡åãªäœ¿çšäŸãèŠãŸããã ããã«ãããã¹ã©ãã¯ãšã®çµ±åããã¹ãã«ããã³ãŒãã«ãã¬ããžã®ç£èŠãªã©ãå¯èœã«ãªããŸãã è±å¯ãªã¢ããªã³ã·ã¹ãã ã掻çºãªã³ãã¥ããã£ãããã³éåžžã«åªããããã¥ã¡ã³ããåããCakeã¯ãCïŒã³ãŒããæ§ç¯ããããã®CIã·ã¹ãã ããã³MSBuildã®ä»£æ¿ãšããŠéåžžã«åªããŠããŸãã