var PROJECT='AspNet' var VERSION='0.2.1-dev' use namespace='System' use namespace='System.IO' use namespace='System.Collections.Generic' use namespace='System.Net' use namespace='System.Text.RegularExpressions' use import="BuildEnv" default BASE_DIR='${Directory.GetCurrentDirectory()}' default TARGET_DIR='${Path.Combine(BASE_DIR, "artifacts", "build")}' var useHttps='${UseHttps(BASE_DIR)}' var gitHubUriPrefix='${useHttps ? "https://github.com/aspnet/" : "git@github.com:aspnet/"}' var repos='${new Dictionary { /* {"KRuntime", gitHubUriPrefix + "KRuntime.git"}, */ // Let's not build the sdk :) {"Configuration", gitHubUriPrefix + "Configuration.git"}, {"DataCommon", gitHubUriPrefix + "DataCommon.git"}, {"DataCommon.SQLite", gitHubUriPrefix + "DataCommon.SQLite.git"}, {"DataProtection", gitHubUriPrefix + "DataProtection.git"}, {"DependencyInjection", gitHubUriPrefix + "DependencyInjection.git"}, {"Diagnostics", gitHubUriPrefix + "Diagnostics.git"}, {"EntityFramework", gitHubUriPrefix + "EntityFramework.git"}, {"Entropy", gitHubUriPrefix + "Entropy.git"}, {"FileSystem", gitHubUriPrefix + "FileSystem.git"}, {"Helios", gitHubUriPrefix + "Helios.git"}, {"Hosting", gitHubUriPrefix + "Hosting.git"}, {"HttpAbstractions", gitHubUriPrefix + "HttpAbstractions.git"}, {"Identity", gitHubUriPrefix + "Identity.git"}, {"Mvc", gitHubUriPrefix + "Mvc.git"}, {"Razor", gitHubUriPrefix + "Razor.git"}, {"Routing", gitHubUriPrefix + "Routing.git"}, {"Security", gitHubUriPrefix + "Security.git"}, {"SignalR-Server", gitHubUriPrefix + "SignalR-Server.git"}, {"StaticFiles", gitHubUriPrefix + "StaticFiles.git"}, {"Testing", gitHubUriPrefix + "Testing.git"}, {"WebListener", gitHubUriPrefix + "WebListener.git"}, }}' @{ VERSION += "-" + BuildNumber; } #default .compile #pull #compile .pull #install .pull #pack directory create='${TARGET_DIR}' nuget-pack nuspecFile='${Path.Combine(BASE_DIR, "KoreBuild.nuspec")}' packageVersion='${VERSION}' outputDir='${TARGET_DIR}' #pack-install .pack nuget-local-publish sourcePackagesDir='${TARGET_DIR}' #git-pull target='pull' @{ foreach(var repo in repos) { if(Directory.Exists(repo.Key)) { GitPull(repo.Value, "dev", repo.Key); } else { if (IsHttpsUrl(repo.Value) && !IsAccessible(repo.Key)) { Log.Warn(string.Format("The repo at '{0}' is not accessible. If you do not have access to this repository, skip the git prompt" + " for credentials to skip cloning this repository. To avoid this prompt, re-clone the Universe repository over ssh.", repo.Value)); } try { GitClone(repo.Value, "dev"); } catch (Exception ex) { Log.Warn(string.Format("Unable to clone repository at '{0}'.", repo.Value)); continue; } GitConfig("bugtraq.url", "http://github.com/aspnet/" + repo.Key + "/issues/%BUGID%", repo.Key); GitConfig("bugtraq.logregex", @"#(\d+)", repo.Key); } } } #init @{ var templatePath = Path.Combine(BASE_DIR, "build-template"); var templateFiles = Files.Include(templatePath + Path.DirectorySeparatorChar + "*.*").Select(Path.GetFileName).ToList(); foreach(var repo in repos) { foreach (string fileName in templateFiles) { var targetFile = Path.Combine(Directory.GetCurrentDirectory(), repo.Key, fileName); var sourceFile = Path.Combine(Directory.GetCurrentDirectory(), templatePath, fileName); // Don't update the makefile if(fileName.Equals("makefile.shake", StringComparison.OrdinalIgnoreCase) && File.Exists(targetFile)) { continue; } if(!File.Exists(sourceFile) || (File.ReadAllText(sourceFile) != File.ReadAllText(targetFile))) { Log.Info("Updating " + fileName + " to " + repo.Key); File.Copy(sourceFile, targetFile, true); } } } } #only-compile target='compile' @{ var failed = new Dictionary(); foreach(var repo in repos) { try { Log.Info(string.Format("Building {0}", repo.Key)); if (IsMono) { Exec("build.sh", "compile", repo.Key); } else { Exec("build.cmd", "compile", repo.Key); } Log.Info(string.Format("Build {0} succeeded", repo.Key)); } catch(Exception ex) { Log.Warn(string.Format("Build {0} failed: {1}", repo.Key, ex.Message)); failed[repo.Key] = ex; } } foreach(var repo in repos) { Exception ex; if (failed.TryGetValue(repo.Key, out ex)) { Log.Warn(string.Format("Build {0} failed: {1}", repo.Key, ex.Message)); } else { Log.Info(string.Format("Build {0} succeeded", repo.Key)); } } } #only-install target='install' @{ foreach(var repo in repos) { if (IsMono) { Exec("build.sh", "install", repo.Key); } else { Exec("build.cmd", "install", repo.Key); } } } #run-snapshot-manager @{ Exec(@".nuget\nuget.exe", @"restore -out packages tools\TCDependencyManager\packages.config", ""); var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); var msbuildPath = Path.Combine(programFiles, "MSBuild", "12.0", "Bin", "MsBuild.exe"); Exec(msbuildPath, "TCDependencyManager.csproj", @"tools\TCDependencyManager"); Exec(@"tools\TCDependencyManager\bin\Debug\TCDependencyManager.exe", "", ""); } #git-status decription='Show status of repos known by Universe' @{ foreach(var repo in repos) { GitStatus(repo.Key); } } #git-clean decription='REMOVE ALL CHANGES to the working directory' @{ Console.WriteLine("This runs `git clean -xfd` in all non-Universe repos."); Console.WriteLine("This should REMOVE ALL CHANGES to the working directory."); Console.Write("***** Are you sure? ***** (Y or anything else)? "); if (Console.ReadLine() != "Y") { throw new Exception("git-clean cancelled"); } foreach(var repo in repos) { GitClean(repo.Key); } } macro name='GitPull' gitUri='string' gitBranch='string' gitFolder='string' git-pull macro name='GitClone' gitUri='string' gitBranch='string' git-clone macro name='GitConfig' gitOptionName='string' gitOptionValue='string' gitFolder='string' git-config macro name='GitStatus' gitFolder='string' git gitCommand='status' macro name='GitClean' gitFolder='string' git gitCommand='clean -xdf' macro name='Exec' program='string' commandline='string' workingdir='string' exec functions @{ bool UseHttps(string directory) { var filename = Path.Combine(directory, ".git", "config"); if (!File.Exists(filename)) { Log.Warn(string.Format("Unable to find '{0}' file", filename)); return false; } var url = ReadOriginUrl(filename); return IsHttpsUrl(url); } // Perform equivalent of `git config remote.origin.url` but directly // read config file to get value. string ReadOriginUrl(string filename) { // Subsection portion of configuration name is case-sensitive; rest // of name is case-insensitive. var beginOriginSection = new Regex(@"^\[(?i:remote) ""origin""\]\s*$"); var beginSection = new Regex(@"^\["); var urlLine = new Regex(@"^\s+url = (\S+)\s*$", RegexOptions.IgnoreCase); var inRemoteOriginSection = false; foreach (var line in File.ReadAllLines(filename)) { if (beginOriginSection.IsMatch(line)) { inRemoteOriginSection = true; continue; } if (inRemoteOriginSection) { if (beginSection.IsMatch(line)) { // Read through the section without finding URL line. break; } var match = urlLine.Match(line); if (match.Success && match.Groups.Count == 2 && match.Groups[1].Success) { return match.Groups[1].Value; } } } Log.Warn(string.Format("Unable to parse '{0}' file", filename)); return null; } static bool IsHttpsUrl(string url) { if (string.IsNullOrEmpty(url)) { return false; } return url.StartsWith("https://", System.StringComparison.OrdinalIgnoreCase); } static bool IsAccessible(string key) { var req = WebRequest.CreateHttp("https://github.com/aspnet/" + key); req.Method = "HEAD"; try { using (req.GetResponse()); } catch (WebException ex) { if (ex.Response != null && ((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotFound) { return false; } // Ignore any other exception. They should surface as part of git clone with well-known messages. } return true; } }