public async Task <string> CloneIfNotExistLocally(string remoteUrl, string localRepository, bool isPrivateRepository) { if (Directory.Exists(localRepository) && Repository.IsValid(localRepository)) { return(localRepository); } var cloneOption = new CloneOptions() { OnTransferProgress = CloneTransferProgressHandler }; if (isPrivateRepository) { cloneOption.CredentialsProvider = (url, user, cred) => _gitCredential; } try { return(await Task.Run(() => Repository.Clone(remoteUrl, localRepository, cloneOption))); } catch (Exception ex) { _logger.LogError(ex, ex.Message); return(""); } }
public void Pull(Octokit.Repository rep) { string reppath = Path.Combine(_account.TempRepPath, rep.Name); if (!Repository.IsValid(reppath)) { Repository.Clone(rep.CloneUrl, reppath); using (var repo = new Repository(reppath)) { var upstream = repo.Network.Remotes.Add("upstream", rep.Parent.CloneUrl); Commands.Fetch(repo, "upstream", new List <string>() { }, new FetchOptions(), null); Branch upstreamMaster = repo.Branches["upstream/master"]; Branch localMaster = repo.Branches["master"]; repo.Branches.Update(localMaster, b => b.TrackedBranch = upstreamMaster.CanonicalName); var sign = new LibGit2Sharp.Signature(_account.UserName, _account.Email, new DateTimeOffset(DateTime.Now)); Commands.Pull(repo, sign, new PullOptions()); } } else { using (var repo = new Repository(reppath)) { var branchMaster = repo.Branches["master"]; Commands.Checkout(repo, branchMaster); var sign = new LibGit2Sharp.Signature(_account.UserName, _account.Email, new DateTimeOffset(DateTime.Now)); Commands.Pull(repo, sign, new PullOptions()); } } }
/// <summary> /// Handles a webhook event created by github /// </summary> // TODO: Find use for the webhookEvent parameter public void HandleEvent(GithubWebhookEvent webhookEvent) { if (!this.IsCloned) { this.Logger?.Debug( "Cloning repository to {@path}", this.ClonePath.FullName ); Repository.Clone(this.RepositoryUrl, this.ClonePath.FullName); this._repository = new Repository(this.ClonePath.FullName); return; } var signature = new Signature( "Jay", "*****@*****.**", DateTimeOffset.Now ); var pullOptions = new PullOptions(); var mergeResult = Commands.Pull( this._repository, signature, pullOptions ); // This shouldn't really happen since the repo on the server should not be edited directly if (mergeResult.Status == MergeStatus.Conflicts) { this.Logger?.Error( "Pull operation resulted in a merge conflict" ); } }
bool CloneCore(CommonRepository repository) { var co = new CloneOptions(); co.CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials { Username = "******", Password = "******" }; co.BranchName = $"20{repository.Version}"; var result = Repository.Clone("http://gitserver/XPF/VisualTests.git", repository.Path, co); return(Directory.Exists(result)); }
public void Clone(Uri pullEndpoint) { _logger.Normal($"Git clone {pullEndpoint} to {WorkingFolder.FullPath}"); Repository.Clone(pullEndpoint.AbsoluteUri, WorkingFolder.FullPath, new CloneOptions { CredentialsProvider = UsernamePasswordCredentials, OnTransferProgress = OnTransferProgress }); _logger.Detailed("Git clone complete"); }
public void Clone(Uri pullEndpoint, string branchName) { _logger.Normal($"Git clone {pullEndpoint}, branch {branchName ?? "default"}, to {WorkingFolder.FullPath}"); Repository.Clone(pullEndpoint.AbsoluteUri, WorkingFolder.FullPath, new CloneOptions { CredentialsProvider = UsernamePasswordCredentials, OnTransferProgress = OnTransferProgress, BranchName = branchName }); _logger.Detailed("Git clone complete"); }
public static void Clone(string url, string branchName, string path) { CloneOptions option = new CloneOptions { CredentialsProvider = (_url, _user, _cred) => Token, BranchName = branchName }; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } GitRepo.Clone(url, path, option); }
private async Task SetupSrcRepo() { if (!Directory.Exists("srcRepo")) { Logger.Info("Cloning source repository... ", false); Directory.CreateDirectory("srcRepo"); await Task.Run(() => GitRepository.Clone(_ghSrc.CloneUrl, "srcRepo", new CloneOptions { CredentialsProvider = GitCredentials })); Console.WriteLine("Done."); } }
public RepositoryProcessor(Uri repositoryUrl, UsernamePasswordCredentials credentials) { _repositoryUrl = repositoryUrl; _credentials = credentials; Console.WriteLine($"Cloning {_repositoryUrl}"); _clonePath = Path.Combine(".", _repositoryUrl.ToString().Split("/").Last(x => !string.IsNullOrWhiteSpace(x))); var repoPath = Repository.Clone( _repositoryUrl.ToString(), _clonePath, new CloneOptions { CredentialsProvider = (x, y, z) => _credentials }); _repository = new Repository(repoPath); _baseBranch = _repository.Branches[_repository.Head.FriendlyName]; }
private static async Task Clone( IEnumerable <Organization> organizations, string clonePath, string userName, string pat) { var credentials = new NetworkCredential(userName, pat); var cloneOptions = new CloneOptions { Checkout = true, CredentialsProvider = (url, user, cred) => new SecureUsernamePasswordCredentials { Username = credentials.UserName, Password = credentials.SecurePassword } }; foreach (var organization in organizations) { foreach (var project in organization.Projects) { foreach (var repository in project.Repositories) { var path = Path.Combine(clonePath, repository.Name); var repoRoot = Repository.Discover(path); // don't crash when there is no repo to this path, return empty changes if (repoRoot != null) { Console.WriteLine($"Repo {repository.Name} already exists! Continue with other."); continue; } Console.WriteLine($"Cloning {repository.Name} repository!"); Directory.CreateDirectory(path); await Task.Run(() => Repository.Clone( $"https://{Uri.EscapeUriString(organization.Name)}@dev.azure.com/{Uri.EscapeUriString(organization.Name)}/" + $"{Uri.EscapeUriString(project.Name)}/_git/{Uri.EscapeUriString(repository.Name)}", path, cloneOptions)); } } } }
private async void btnRun_Click(object sender, EventArgs e) { var userName = tbUserName.Text; if (string.IsNullOrEmpty(userName)) { return; } if (Directory.Exists("repos") == false) { Directory.CreateDirectory("repos"); } var github = new GitHubClient(new ProductHeaderValue("GitHubBackTester")); var repositories = await github.Repository.GetAllForUser(userName); foreach (var githubRepository in repositories) { var path = Path.Combine("repos", githubRepository.Name); Repository.Clone(githubRepository.HtmlUrl, path); } }
private string GetLocalRepoFolder(Models.Repository repo, string personalAccessKey) { var checkOutFolder = GetLocalFolder(repo); string logMessage = ""; if (Repository.IsValid(checkOutFolder) == false) { checkOutFolder = Repository.Clone(repo.CloneUrl, checkOutFolder, getCloneOptions(personalAccessKey)); } else { using (var tmpRepo = new Repository(checkOutFolder)) { var remote = tmpRepo.Network.Remotes["origin"]; var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification); Commands.Fetch(tmpRepo, remote.Name, refSpecs, getFetchOptions(personalAccessKey), logMessage); } } return(checkOutFolder); }
/// <summary> /// Ensure that the repository exists on disk and its origin remote points to the correct url /// </summary> /// <param name="repo"></param> private void EnsureRepository(List <RepositoryInfo> repos) { foreach (var repo in repos) { var repoPath = repo.Path; s_logger.Info($"Verifying repository {repo} at {repo.Path}"); if (!Directory.Exists(repoPath) || !Repository.IsValid(repoPath)) { if (Directory.Exists(repoPath)) { Directory.Delete(repoPath, true); } s_logger.Info($"Cloning the repo from {repo.CloneUrl}"); Repository.Clone(repo.CloneUrl, repoPath); } using (var repository = new Repository(repoPath)) { var remote = repository.Network.Remotes["origin"]; if (remote == null) { repository.Network.Remotes.Add("origin", repo.CloneUrl); } else if (remote.Url != repo.CloneUrl) { repository.Network.Remotes.Update("origin", u => u.Url = repo.CloneUrl); } var master = repository.Branches["master"] ?? repository.CreateBranch("master"); repository.Branches.Update(master, b => b.Remote = "origin", b => b.UpstreamBranch = "refs/heads/master"); remote = repository.Network.Remotes["upstream"]; if (remote == null) { repository.Network.Remotes.Add("upstream", @"https://github.com/" + repo.UpstreamOwner + @"/" + repo.Name + ".git"); } } } }
public override int Execute(UpdateSettings settings, ILookup <string, string> remaining) { // Get the user. var client = new GitHubClient(new ProductHeaderValue("Cake-Addin-Updater")) { Credentials = new Octokit.Credentials(settings.Token) }; // Validate the provided version. if (!System.Version.TryParse(settings.Version, out var _)) { _log.Error("The provided version is not valid."); return(1); } // Get the root. var root = settings.WorkingDirectory ?? new DirectoryPath("."); root = root.MakeAbsolute(_environment); // Get the user. var user = client.User.Get(settings.User).Result; var userEmail = GetUserEmail(client); // Get the repository parts. var info = GetRepositoryInfo(settings); // Does the directory contains anything? var path = CreateRepositoryDirectory(root, info); if (_filesystem.Directory.GetFiles(path, "*.*", SearchScope.Current).Any() || _filesystem.Directory.GetDirectories(path, "*.*", SearchScope.Current).Any()) { _log.Error($"Repository '{path}' already exist on disk."); _log.Write("Remove it and try again."); return(1); } // Fork the repository. var repository = ForkRepository(client, info); if (string.IsNullOrWhiteSpace(repository?.Name)) { _log.Error("Could not fork repository."); return(1); } // Get the default branch. var defaultBranch = repository.DefaultBranch; if (string.IsNullOrWhiteSpace(defaultBranch)) { _log.Error("Could not get default branch for repository."); return(1); } // Clone the repository at the specified path. _log.Write("Cloning repository..."); GitRepository.Clone($"https://github.com/{settings.User}/{repository.Name}", path.FullPath, new CloneOptions { Checkout = true }); using (var gitRepository = new GitRepository(path.FullPath)) { // Create a new branch in the repository. _log.Write("Creating branch..."); gitRepository.CreateBranch($"feature/cake-{settings.Version}"); _log.Write("Checking out branch..."); GitCommands.Checkout(gitRepository, $"feature/cake-{settings.Version}"); // Update all package references in project. var processed = _processor.Process(root, path, settings.Version); if (processed == 0) { _log.Error("Nothing was updated. Probably a newer repository."); return(1); } // Commit? if (settings.Commit) { _log.Write("Staging changes..."); GitCommands.Stage(gitRepository, "*"); var status = gitRepository.RetrieveStatus(); if (status.Any()) { _log.Write("Committing changes..."); var author = new GitSignature(user.Name, userEmail, DateTime.Now); gitRepository.Commit($"Updated to Cake {settings.Version}.", author, author); // Push? if (settings.Push) { // Build everything first. if (!BuildProject(path)) { return(1); } // Push the commit. if (!Push(settings, path)) { return(1); } // Create a pull request? if (settings.OpenPullRequest) { CreatePullRequest(client, settings, info); } } } else { _log.Error("No changes in repository. Already updated?"); } } } return(0); }
/// <summary> /// Adds the standard .NET targets to the build. /// </summary> /// <param name="build">The build to which to add targets.</param> /// <param name="settings">The build settings.</param> public static void AddDotNetTargets(this BuildApp build, DotNetBuildSettings?settings = null) { settings ??= new DotNetBuildSettings(); var buildOptions = settings.BuildOptions ?? (settings.BuildOptions = new DotNetBuildOptions()); var configurationOption = buildOptions.ConfigurationOption ?? (buildOptions.ConfigurationOption = build.AddOption("-c|--configuration <name>", "The configuration to build (default Release)", "Release")); var platformOption = buildOptions.PlatformOption ?? (buildOptions.PlatformOption = build.AddOption("-p|--platform <name>", "The solution platform to build")); var versionSuffixOption = buildOptions.VersionSuffixOption ?? (buildOptions.VersionSuffixOption = build.AddOption("--version-suffix <suffix>", "Generates a prerelease package")); var nugetOutputOption = buildOptions.NuGetOutputOption ?? (buildOptions.NuGetOutputOption = build.AddOption("--nuget-output <path>", "Directory for generated package (default release)", "release")); var triggerOption = buildOptions.TriggerOption ?? (buildOptions.TriggerOption = build.AddOption("--trigger <name>", "The git branch or tag that triggered the build")); var buildNumberOption = buildOptions.BuildNumberOption ?? (buildOptions.BuildNumberOption = build.AddOption("--build-number <number>", "The automated build number")); var noTestFlag = buildOptions.NoTestFlag ?? (buildOptions.NoTestFlag = build.AddFlag("--no-test", "Skip the unit tests")); var solutionName = settings.SolutionName; var nugetSource = settings.NuGetSource ?? "https://api.nuget.org/v3/index.json"; var msbuildSettings = settings.MSBuildSettings; var dotNetTools = settings.DotNetTools ?? new DotNetTools(Path.Combine("tools", "bin")); var xmlDocMarkdownVersion = settings.DocsSettings?.ToolVersion ?? "2.0.1"; var packagePaths = new List <string>(); string?trigger = null; var ignoreIfAlreadyPushed = false; build.Target("clean") .Describe("Deletes all build output") .Does(() => { var findDirectoriesToDelete = settings.CleanSettings?.FindDirectoriesToDelete ?? (() => FindDirectories("{src,tests}/**/{bin,obj}", "tools/XmlDocTarget/{bin,obj}")); foreach (var directoryToDelete in findDirectoriesToDelete()) { deleteDirectory(directoryToDelete); } var extraProperties = getExtraProperties("clean"); if (msbuildSettings == null) { RunDotNet(new[] { "clean", solutionName, "-c", configurationOption.Value, getPlatformArg(), "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { solutionName, "-t:Clean", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("restore") .Describe("Restores NuGet packages") .Does(() => { var extraProperties = getExtraProperties("restore"); if (msbuildSettings == null) { RunDotNet(new[] { "restore", solutionName, getPlatformArg(), "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { solutionName, "-t:Restore", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("build") .DependsOn("restore") .Describe("Builds the solution") .Does(() => { var buildNumberArg = buildNumberOption.Value == null ? null : $"-p:BuildNumber={buildNumberOption.Value}"; var extraProperties = getExtraProperties("build"); if (msbuildSettings == null) { RunDotNet(new[] { "build", solutionName, "-c", configurationOption.Value, getPlatformArg(), buildNumberArg, "--no-restore", "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { solutionName, $"-p:Configuration={configurationOption.Value}", getPlatformArg(), buildNumberArg, "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("test") .DependsOn("build") .Describe("Runs the unit tests") .Does(() => { if (noTestFlag.Value) { Console.WriteLine("Skipping unit tests due to --no-test."); } else { var extraProperties = getExtraProperties("test").ToList(); var findTestAssemblies = settings.TestSettings?.FindTestAssemblies; if (findTestAssemblies != null) { foreach (var testAssembly in findTestAssemblies()) { if (settings.TestSettings?.RunTests != null) { settings.TestSettings.RunTests(testAssembly); } else { RunDotNet(new AppRunnerSettings { Arguments = new[] { "vstest", Path.GetFileName(testAssembly) }.Concat(extraProperties), WorkingDirectory = Path.GetDirectoryName(testAssembly) }); } } } else { var testProjects = new List <string?>(); var findTestProjects = settings.TestSettings?.FindProjects; if (findTestProjects != null) { testProjects.AddRange(findTestProjects()); } else { testProjects.Add(solutionName); } foreach (var testProject in testProjects) { if (settings.TestSettings?.RunTests != null) { settings.TestSettings.RunTests(testProject); } else { RunDotNet(new[] { "test", testProject, "-c", configurationOption.Value, getPlatformArg(), "--no-build", getMaxCpuCountArg() }.Concat(extraProperties)); } } } } }); build.Target("package") .DependsOn("clean", "test") .Describe("Builds NuGet packages") .Does(() => { trigger = triggerOption.Value; if (trigger == "detect") { using var repository = new Repository("."); var headSha = repository.Head.Tip.Sha; var autoTrigger = GetBestTriggerFromTags(repository.Tags.Where(x => x.Target.Sha == headSha).Select(x => x.FriendlyName).ToList()); if (autoTrigger != null) { trigger = autoTrigger; ignoreIfAlreadyPushed = true; Console.WriteLine($"Detected trigger: {trigger}"); } } var versionSuffix = versionSuffixOption.Value; if (versionSuffix == null && trigger != null) { versionSuffix = GetVersionFromTrigger(trigger) is string triggerVersion ? SplitVersion(triggerVersion).Suffix : null; } var nugetOutputPath = Path.GetFullPath(nugetOutputOption.Value); var tempOutputPath = Path.Combine(nugetOutputPath, $"temp_{Guid.NewGuid():N}"); var packageProjects = new List <string?>(); var findPackageProjects = settings.PackageSettings?.FindProjects; if (findPackageProjects != null) { packageProjects.AddRange(findPackageProjects()); } else { packageProjects.Add(solutionName); } var extraProperties = getExtraProperties("package").ToList(); foreach (var packageProject in packageProjects) { if (msbuildSettings == null) { RunDotNet(new[] { "pack", packageProject, "-c", configurationOption.Value, getPlatformArg(), "--no-build", "--output", tempOutputPath, versionSuffix != null ? "--version-suffix" : null, versionSuffix, getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { packageProject, "-t:Pack", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-p:NoBuild=true", $"-p:PackageOutputPath={tempOutputPath}", versionSuffix != null ? $"-p:VersionSuffix={versionSuffix}" : null, "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } } var tempPackagePaths = FindFilesFrom(tempOutputPath, "*.nupkg"); foreach (var tempPackagePath in tempPackagePaths) { var packagePath = Path.Combine(nugetOutputPath, Path.GetFileName(tempPackagePath) ?? throw new InvalidOperationException()); if (File.Exists(packagePath)) { File.Delete(packagePath); } File.Move(tempPackagePath, packagePath); packagePaths.Add(packagePath); } deleteDirectory(tempOutputPath); if (packagePaths.Count == 0) { throw new ApplicationException("No NuGet packages created."); } }); build.Target("publish") .Describe("Publishes NuGet packages and documentation") .DependsOn("package") .Does(() => { if (packagePaths.Count == 0) { throw new ApplicationException("No NuGet packages found."); } if (trigger == null) { throw new ApplicationException("--trigger option required."); } var triggerParts = trigger.Split('-'); var publishTrigger = triggerParts.Length >= 2 && triggerParts[0] == "publish" ? triggerParts[1] : null; var shouldPublishPackages = publishTrigger == "package" || publishTrigger == "packages" || publishTrigger == "all"; var shouldPublishDocs = publishTrigger == "docs" || publishTrigger == "all"; var triggerVersion = GetVersionFromTrigger(trigger); if (triggerVersion != null) { var mismatches = packagePaths.Where(x => GetPackageInfo(x).Version != triggerVersion).ToList(); if (mismatches.Count != 0) { throw new ApplicationException($"Trigger '{trigger}' doesn't match package version: {string.Join(", ", mismatches.Select(Path.GetFileName))}"); } shouldPublishPackages = true; shouldPublishDocs = triggerVersion.IndexOf('-') == -1; } if (shouldPublishPackages || shouldPublishDocs) { var docsSettings = settings.DocsSettings; var shouldPushDocs = false; string?cloneDirectory = null; string?repoDirectory = null; string?gitBranchName = null; Credentials provideCredentials(string url, string usernameFromUrl, SupportedCredentialTypes types) => new UsernamePasswordCredentials { Username = docsSettings?.GitLogin?.Username ?? throw new ApplicationException("GitLogin has a null Username."), Password = docsSettings?.GitLogin?.Password ?? throw new ApplicationException("GitLogin has a null Password."), }; if (shouldPublishDocs && docsSettings != null) { if (docsSettings.GitLogin == null || docsSettings.GitAuthor == null) { throw new ApplicationException("GitLogin and GitAuthor must be set on DocsSettings."); } var gitRepositoryUrl = docsSettings.GitRepositoryUrl; gitBranchName = docsSettings.GitBranchName; if (gitRepositoryUrl != null) { cloneDirectory = "docs_repo_" + Path.GetRandomFileName(); Repository.Clone(sourceUrl: gitRepositoryUrl, workdirPath: cloneDirectory, options: new CloneOptions { BranchName = gitBranchName, CredentialsProvider = provideCredentials }); repoDirectory = cloneDirectory; } else { repoDirectory = "."; } using var repository = new Repository(repoDirectory); if (gitRepositoryUrl != null) { if (gitBranchName == null) { gitBranchName = repository.Head.FriendlyName; } } else if (gitBranchName != null) { if (gitBranchName != repository.Head.FriendlyName) { var branch = repository.Branches[gitBranchName] ?? repository.CreateBranch(gitBranchName); Commands.Checkout(repository, branch); } } else { var branch = repository.Branches.FirstOrDefault(x => x.IsCurrentRepositoryHead); if (branch == null) { var autoBranchName = Environment.GetEnvironmentVariable("APPVEYOR_REPO_BRANCH"); if (autoBranchName != null) { branch = repository.Branches[autoBranchName] ?? repository.CreateBranch(autoBranchName); } else { branch = repository.Branches.FirstOrDefault(x => x.Tip.Sha == repository.Head.Tip.Sha); } if (branch != null) { Commands.Checkout(repository, branch); } } if (branch == null) { throw new ArgumentException("Could not determine repository branch for publishing docs."); } gitBranchName = branch.FriendlyName; } var projectHasDocs = docsSettings.ProjectHasDocs ?? (_ => true); foreach (var projectName in packagePaths.Select(x => GetPackageInfo(x).Name).Where(projectHasDocs)) { string findAssembly(string name) => FindFiles($"tools/XmlDocTarget/bin/**/{name}.dll").OrderByDescending(File.GetLastWriteTime).FirstOrDefault() ?? FindFiles($"src/{name}/bin/**/{name}.dll").OrderByDescending(File.GetLastWriteTime).FirstOrDefault(); var assemblyPaths = new List <string>(); if (docsSettings.FindAssemblies != null) { assemblyPaths.AddRange(docsSettings.FindAssemblies(projectName)); } else { var assemblyPath = (docsSettings.FindAssembly ?? findAssembly)(projectName); if (assemblyPath != null) { assemblyPaths.Add(assemblyPath); } } if (assemblyPaths.Count != 0) { foreach (var assemblyPath in assemblyPaths) { RunApp(dotNetTools.GetToolPath($"xmldocmd/{xmlDocMarkdownVersion}"), assemblyPath, Path.Combine(repoDirectory, docsSettings.TargetDirectory ?? "docs"), "--source", $"{docsSettings.SourceCodeUrl}/{projectName}", "--newline", "lf", "--clean"); } } else { Console.WriteLine($"Documentation not generated for {projectName}; assembly not found."); } } shouldPushDocs = repository.RetrieveStatus().IsDirty; } if (shouldPublishPackages) { var nugetApiKey = settings.NuGetApiKey; if (string.IsNullOrEmpty(nugetApiKey)) { throw new ApplicationException("NuGetApiKey required to publish."); } if (ignoreIfAlreadyPushed) { var nugetSettings = NuGet.Configuration.Settings.LoadDefaultSettings(root: null); var packageSourceProvider = new PackageSourceProvider(nugetSettings); var sourceRepositoryProvider = new SourceRepositoryProvider(packageSourceProvider, NuGet.Protocol.Core.Types.Repository.Provider.GetCoreV3()); using var sourceCacheContext = new SourceCacheContext(); var nugetRepositories = sourceRepositoryProvider.GetRepositories() .Select(x => x.GetResourceAsync <DependencyInfoResource>().GetAwaiter().GetResult()) .ToList(); foreach (var packagePath in packagePaths.ToList()) { var packageInfo = GetPackageInfo(packagePath); var package = new PackageIdentity(packageInfo.Name, NuGetVersion.Parse(packageInfo.Version)); foreach (var nugetRepository in nugetRepositories) { var dependencyInfo = nugetRepository.ResolvePackage(package, NuGetFramework.AnyFramework, sourceCacheContext, NullLogger.Instance, CancellationToken.None).GetAwaiter().GetResult(); if (dependencyInfo != null) { Console.WriteLine($"Package already pushed: {packageInfo.Name} {packageInfo.Version}"); packagePaths.Remove(packagePath); break; } } } } foreach (var packagePath in packagePaths) { RunDotNet("nuget", "push", packagePath, "--source", nugetSource, "--api-key", nugetApiKey); } } if (shouldPushDocs) { using var repository = new Repository(repoDirectory); Console.WriteLine("Publishing documentation changes."); Commands.Stage(repository, "*"); var author = new Signature(docsSettings !.GitAuthor !.Name, docsSettings !.GitAuthor !.Email, DateTimeOffset.Now); repository.Commit("Documentation updated.", author, author, new CommitOptions()); repository.Network.Push(repository.Network.Remotes["origin"], $"refs/heads/{gitBranchName}", new PushOptions { CredentialsProvider = provideCredentials }); } if (cloneDirectory != null) { // delete the cloned directory foreach (var fileInfo in FindFiles(cloneDirectory, "**").Select(x => new FileInfo(x)).Where(x => x.IsReadOnly)) { fileInfo.IsReadOnly = false; } deleteDirectory(cloneDirectory); } } else { Console.WriteLine("To publish to NuGet, push this tag: v" + GetPackageInfo(packagePaths[0]).Version); } }); string?getPlatformArg() { var platformValue = platformOption?.Value ?? settings?.SolutionPlatform; return(platformValue == null ? null : $"-p:Platform={platformValue}"); } string?getMaxCpuCountArg() { if (settings !.MaxCpuCount != null) { return($"-maxcpucount:{settings.MaxCpuCount}"); }
private static async Task <int> Main(string[] args) { var initialColour = Console.ForegroundColor; var path = args.Length == 0 ? "./output/" : args[0]; try { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } catch (Exception ex) { WriteLines(ConsoleColor.Red, "Invalid output path specified:", ex.ToString()); return(1); } var configuration = new Configuration(); try { new ConfigurationBuilder().AddJsonFile(args.Length == 2 ? args[1] : "appsettings.json").Build().Bind(configuration); if (string.IsNullOrWhiteSpace(configuration.ApiKey)) { throw new ArgumentException($"No {nameof(configuration.ApiKey)} specified.", nameof(configuration.ApiKey)); } if (string.IsNullOrWhiteSpace(configuration.User)) { throw new ArgumentException($"No {nameof(configuration.User)} specified.", nameof(configuration.User)); } if (configuration.ApiPath is null) { throw new ArgumentNullException(nameof(configuration.ApiPath), $"No {nameof(configuration.ApiPath)} specified."); } } catch (Exception ex) { WriteLines(ConsoleColor.Red, "Invalid appsettings.json file:", ex.ToString()); return(1); } var client = new GitHubClient(new Connection( new ProductHeaderValue(configuration.User), configuration.ApiPath, new InMemoryCredentialStore(new Credentials(configuration.ApiKey)))); IReadOnlyDictionary <string, string> repositories; try { var repositoryList = await client.Repository.GetAllForCurrent(); repositoryList = string.IsNullOrWhiteSpace(configuration.GetRepositortiesForOrganization) ? repositoryList.Where(r => r.Owner.Login == configuration.User).ToArray() : repositoryList.Where(r => r.Owner.Login == configuration.GetRepositortiesForOrganization).ToArray(); switch (configuration.Archived) { case Configuration.ArchiveState.NoArchivedRepositories: repositoryList = repositoryList.Where(r => !r.Archived).ToArray(); break; case Configuration.ArchiveState.OnlyArchivedRepositories: repositoryList = repositoryList.Where(r => r.Archived).ToArray(); break; } switch (configuration.Forked) { case Configuration.ForkState.NoForkedRepositories: repositoryList = repositoryList.Where(r => !r.Fork).ToArray(); break; case Configuration.ForkState.OnlyForkedRepositories: repositoryList = repositoryList.Where(r => r.Fork).ToArray(); break; } repositories = repositoryList.ToDictionary(r => r.FullName, r => r.CloneUrl); } catch (Exception ex) { WriteLines(ConsoleColor.Red, $"Failed to get repositories for {(string.IsNullOrWhiteSpace(configuration.GetRepositortiesForOrganization) ? configuration.User : configuration.GetRepositortiesForOrganization)}.", ex.Message); return(1); } if (repositories.Count == 0) { WriteLines(ConsoleColor.Red, "No repositories found."); return(1); } WriteLines(ConsoleColor.Green, $"Found the following {repositories.Count} repositories:", string.Join(Environment.NewLine, repositories.Keys.Select(r => $" - {r}")), string.Empty); LibGit2Sharp.Credentials CredentialsProvider(string _, string __, SupportedCredentialTypes ___) => new UsernamePasswordCredentials { Username = configuration.ApiKey, Password = string.Empty, }; var issues = new Dictionary <string, string>(); Parallel.ForEach(repositories, r => { var(name, url) = r; WriteLines(initialColour, $"Checking whether {name} has already been cloned."); try { var repoPath = Path.Combine(path, name); if (Directory.Exists(Path.Combine(repoPath, ".git"))) { WriteLines(initialColour, $"{name} has been cloned; fetching to get the latest changes."); var repository = new Repository(repoPath); Commands.Fetch( repository, "origin", repository.Refs.Select(r => r.CanonicalName), new FetchOptions { CredentialsProvider = CredentialsProvider }, null); WriteLines(ConsoleColor.Green, $"{name} was updated successfully."); } else { WriteLines(initialColour, $"{name} has not been cloned; cloning into new folder."); Repository.Clone( url, repoPath, new CloneOptions { CredentialsProvider = CredentialsProvider }); WriteLines(ConsoleColor.Green, $"{name} was cloned successfully."); } } catch (Exception ex) { WriteLines(ConsoleColor.Red, $"Failed to clone or update {name}:", ex.ToString()); issues[name] = ex.ToString(); } }); if (issues.Count == 0) { return(0); } WriteLines(ConsoleColor.Red, string.Empty, "The following repositories had issues:", string.Join(Environment.NewLine, issues.Select(i => $"{i.Key}: {i.Value}{Environment.NewLine}"))); return(1); }
/// <summary> /// Adds the standard .NET targets to the build. /// </summary> /// <param name="build">The build to which to add targets.</param> /// <param name="settings">The build settings.</param> public static void AddDotNetTargets(this BuildApp build, DotNetBuildSettings?settings = null) { settings ??= new DotNetBuildSettings(); var buildOptions = settings.BuildOptions ?? (settings.BuildOptions = new DotNetBuildOptions()); var configurationOption = buildOptions.ConfigurationOption ?? (buildOptions.ConfigurationOption = build.AddOption("-c|--configuration <name>", "The configuration to build (default Release)", "Release")); var platformOption = buildOptions.PlatformOption ?? (buildOptions.PlatformOption = build.AddOption("-p|--platform <name>", "The solution platform to build")); var verbosityOption = buildOptions.VerbosityOption ?? (buildOptions.VerbosityOption = build.AddOption("-v|--verbosity <level>", "The build verbosity (q[uiet], m[inimal], n[ormal], d[etailed])")); var versionSuffixOption = buildOptions.VersionSuffixOption ?? (buildOptions.VersionSuffixOption = build.AddOption("--version-suffix <suffix>", "Generates a prerelease package")); var nugetOutputOption = buildOptions.NuGetOutputOption ?? (buildOptions.NuGetOutputOption = build.AddOption("--nuget-output <path>", "Directory for generated package (default release)", "release")); var triggerOption = buildOptions.TriggerOption ?? (buildOptions.TriggerOption = build.AddOption("--trigger <name>", "The git branch or tag that triggered the build")); var buildNumberOption = buildOptions.BuildNumberOption ?? (buildOptions.BuildNumberOption = build.AddOption("--build-number <number>", "The automated build number")); var noTestFlag = buildOptions.NoTestFlag ?? (buildOptions.NoTestFlag = build.AddFlag("--no-test", "Skip the unit tests")); var solutionName = settings.SolutionName; var nugetSource = settings.NuGetSource ?? "https://api.nuget.org/v3/index.json"; var msbuildSettings = settings.MSBuildSettings; var packagePaths = new List <string>(); string?trigger = null; var ignoreIfAlreadyPushed = false; build.Target("clean") .Describe("Deletes all build output") .Does(() => { var findDirectoriesToDelete = settings.CleanSettings?.FindDirectoriesToDelete ?? (() => FindDirectories("{src,tests,tools}/**/{bin,obj}").Except(FindDirectories("tools/bin")).ToList()); foreach (var directoryToDelete in findDirectoriesToDelete()) { DeleteDirectory(directoryToDelete); } var verbosity = GetVerbosity(); var extraProperties = GetExtraProperties("clean"); if (msbuildSettings == null) { RunDotNet(new[] { "clean", solutionName, "-c", configurationOption.Value, GetPlatformArg(), "--verbosity", verbosity, GetMaxCpuCountArg() }.Concat(extraProperties)); } else { MSBuild(new[] { solutionName, "-t:Clean", $"-p:Configuration={configurationOption.Value}", GetPlatformArg(), $"-v:{verbosity}", GetMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("restore") .Describe("Restores NuGet packages") .Does(() => { var verbosity = GetVerbosity(); var extraProperties = GetExtraProperties("restore"); if (msbuildSettings == null) { RunDotNet(new[] { "restore", solutionName, GetPlatformArg(), "--verbosity", verbosity, GetMaxCpuCountArg() }.Concat(extraProperties)); } else { MSBuild(new[] { solutionName, "-t:Restore", $"-p:Configuration={configurationOption.Value}", GetPlatformArg(), $"-v:{verbosity}", GetMaxCpuCountArg() }.Concat(extraProperties)); } if (DotNetLocalTool.Any()) { RunDotNet("tool", "restore"); } }); build.Target("build") .DependsOn("restore") .Describe("Builds the solution") .Does(() => { var buildNumberArg = GetBuildNumberArg(); var verbosity = GetVerbosity(); var extraProperties = GetExtraProperties("build"); if (msbuildSettings == null) { RunDotNet(new[] { "build", solutionName, "-c", configurationOption.Value, GetPlatformArg(), buildNumberArg, "--no-restore", "--verbosity", verbosity, GetMaxCpuCountArg() }.Concat(extraProperties)); } else { MSBuild(new[] { solutionName, $"-p:Configuration={configurationOption.Value}", GetPlatformArg(), buildNumberArg, $"-v:{verbosity}", GetMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("test") .DependsOn("build") .Describe("Runs the unit tests") .Does(() => { if (noTestFlag.Value) { Console.WriteLine("Skipping unit tests due to --no-test."); } else { var extraProperties = GetExtraProperties("test").ToList(); var findTestAssemblies = settings.TestSettings?.FindTestAssemblies; if (findTestAssemblies != null) { foreach (var testAssembly in findTestAssemblies()) { if (settings.TestSettings?.RunTests != null) { settings.TestSettings.RunTests(testAssembly); } else { RunDotNet(new AppRunnerSettings { Arguments = new[] { "vstest", Path.GetFileName(testAssembly) }.Concat(extraProperties), WorkingDirectory = Path.GetDirectoryName(testAssembly) }); } } } else { var testProjects = new List <string?>(); var findTestProjects = settings.TestSettings?.FindProjects; if (findTestProjects != null) { testProjects.AddRange(findTestProjects()); } else { testProjects.Add(solutionName); } foreach (var testProject in testProjects) { if (settings.TestSettings?.RunTests != null) { settings.TestSettings.RunTests(testProject); } else { RunDotNet(new[] { "test", testProject, "-c", configurationOption.Value, GetPlatformArg(), "--no-build", GetMaxCpuCountArg() }.Concat(extraProperties)); } } } } }); build.Target("package") .DependsOn("clean", "test") .Describe("Builds NuGet packages") .Does(() => { trigger = triggerOption.Value; if (trigger == "detect") { using var repository = new Repository("."); var headSha = repository.Head.Tip.Sha; var autoTrigger = GetBestTriggerFromTags(repository.Tags.Where(x => x.Target.Sha == headSha).Select(x => x.FriendlyName).ToList()); if (autoTrigger != null) { trigger = autoTrigger; ignoreIfAlreadyPushed = true; Console.WriteLine($"Detected trigger: {trigger}"); } } var versionSuffix = versionSuffixOption.Value; if (versionSuffix == null && trigger != null) { versionSuffix = GetVersionFromTrigger(trigger) is string triggerVersion ? SplitVersion(triggerVersion).Suffix : null; } var nugetOutputPath = Path.GetFullPath(nugetOutputOption.Value !); var tempOutputPath = Path.Combine(nugetOutputPath, Path.GetRandomFileName()); var packageProjects = new List <string?>(); var findPackageProjects = settings.PackageSettings?.FindProjects; if (findPackageProjects != null) { packageProjects.AddRange(findPackageProjects()); } else { packageProjects.Add(solutionName); } var extraProperties = GetExtraProperties("package").ToList(); foreach (var packageProject in packageProjects) { if (msbuildSettings == null) { RunDotNet(new[] { "pack", packageProject, "-c", configurationOption.Value, GetPlatformArg(), "--no-build", "--output", tempOutputPath, versionSuffix != null ? "--version-suffix" : null, versionSuffix, GetMaxCpuCountArg(), }.Concat(extraProperties)); } else { MSBuild(new[] { packageProject, "-t:Pack", $"-p:Configuration={configurationOption.Value}", GetPlatformArg(), "-p:NoBuild=true", $"-p:PackageOutputPath={tempOutputPath}", versionSuffix != null ? $"-p:VersionSuffix={versionSuffix}" : null, $"-v:{GetVerbosity()}", GetMaxCpuCountArg(), }.Concat(extraProperties)); } } var tempPackagePaths = FindFilesFrom(tempOutputPath, "*.nupkg"); foreach (var tempPackagePath in tempPackagePaths) { var packagePath = Path.Combine(nugetOutputPath, Path.GetFileName(tempPackagePath) ?? throw new InvalidOperationException()); if (File.Exists(packagePath)) { File.Delete(packagePath); } File.Move(tempPackagePath, packagePath); packagePaths.Add(packagePath); Console.WriteLine($"NuGet package: {packagePath}"); } DeleteDirectory(tempOutputPath); if (packagePaths.Count == 0) { throw new BuildException("No NuGet packages created."); } }); build.Target("publish") .Describe("Publishes NuGet packages and documentation") .DependsOn("package") .Does(() => { if (packagePaths.Count == 0) { throw new BuildException("No NuGet packages found."); } if (trigger is null) { if (packagePaths.Any(x => GetPackageInfo(x).Version == "0.0.0")) { Console.WriteLine("Not publishing package with version 0.0.0. Change package version to publish."); return; } trigger = "publish-all"; } var triggerParts = trigger.Split('-'); var publishTrigger = triggerParts.Length >= 2 && triggerParts[0] == "publish" ? triggerParts[1] : null; var shouldPublishPackages = publishTrigger == "package" || publishTrigger == "packages" || publishTrigger == "all"; var shouldPublishDocs = publishTrigger == "docs" || publishTrigger == "all"; var shouldSkipDuplicates = publishTrigger == "all"; var triggerVersion = GetVersionFromTrigger(trigger); if (triggerVersion != null) { var mismatches = packagePaths.Where(x => GetPackageInfo(x).Version != triggerVersion).ToList(); if (mismatches.Count != 0) { throw new BuildException($"Trigger '{trigger}' doesn't match package version: {string.Join(", ", mismatches.Select(Path.GetFileName))}"); } shouldPublishPackages = true; shouldPublishDocs = triggerVersion.IndexOf('-') == -1; } if (shouldPublishPackages || shouldPublishDocs) { var docsSettings = settings.DocsSettings; var shouldPushDocs = false; string?cloneDirectory = null; string?repoDirectory = null; string?gitBranchName = null; if (shouldPublishDocs && docsSettings != null) { if (docsSettings.GitLogin == null || docsSettings.GitAuthor == null) { throw new BuildException("GitLogin and GitAuthor must be set on DocsSettings."); } var gitRepositoryUrl = docsSettings.GitRepositoryUrl; gitBranchName = docsSettings.GitBranchName; if (gitRepositoryUrl != null) { cloneDirectory = "docs_repo_" + Path.GetRandomFileName(); Repository.Clone(sourceUrl: gitRepositoryUrl, workdirPath: cloneDirectory, options: new CloneOptions { BranchName = gitBranchName, CredentialsProvider = ProvideCredentials }); repoDirectory = cloneDirectory; } else { repoDirectory = "."; } using var repository = new Repository(repoDirectory); if (gitRepositoryUrl != null) { gitBranchName ??= repository.Head.FriendlyName; } else if (gitBranchName != null) { if (gitBranchName != repository.Head.FriendlyName) { var branch = repository.Branches[gitBranchName] ?? repository.CreateBranch(gitBranchName); Commands.Checkout(repository, branch); } } else { var branch = repository.Branches.FirstOrDefault(x => x.IsCurrentRepositoryHead); if (branch == null) { var autoBranchName = Environment.GetEnvironmentVariable("APPVEYOR_REPO_BRANCH"); if (autoBranchName == null) { var gitRef = Environment.GetEnvironmentVariable("GITHUB_REF"); const string prefix = "refs/heads/"; if (gitRef != null && gitRef.StartsWith(prefix, StringComparison.Ordinal)) { autoBranchName = gitRef.Substring(prefix.Length); } } if (autoBranchName != null) { branch = repository.Branches[autoBranchName] ?? repository.CreateBranch(autoBranchName); } else { branch = repository.Branches.FirstOrDefault(x => x.Tip.Sha == repository.Head.Tip.Sha); } if (branch != null) { Commands.Checkout(repository, branch); } } if (branch == null) { throw new BuildException("Could not determine repository branch for publishing docs."); } gitBranchName = branch.FriendlyName; } var docsPath = Path.Combine(repoDirectory, docsSettings.TargetDirectory ?? "docs"); string?xmlDocGenPath = null; var xmlDocGenProject = FindFiles("tools/XmlDocGen/XmlDocGen.csproj").FirstOrDefault(); if (xmlDocGenProject != null) { RunDotNet("publish", xmlDocGenProject, "--output", Path.Combine("tools", "bin", "XmlDocGen"), "--nologo", "--verbosity", "quiet"); xmlDocGenPath = Path.Combine("tools", "bin", "XmlDocGen", "XmlDocGen.dll"); } var projectHasDocs = docsSettings.ProjectHasDocs ?? (_ => true); foreach (var projectName in packagePaths.Select(x => GetPackageInfo(x).Name).Where(projectHasDocs)) { if (xmlDocGenPath != null) { RunDotNet(new[] { xmlDocGenPath }.Concat(GetXmlDocArgs(projectName))); } else { var assemblyPaths = new List <string>(); if (docsSettings.FindAssemblies != null) { assemblyPaths.AddRange(docsSettings.FindAssemblies(projectName)); } else { var assemblyPath = (docsSettings.FindAssembly ?? FindAssembly)(projectName); if (assemblyPath != null) { assemblyPaths.Add(assemblyPath); } } if (assemblyPaths.Count != 0) { if (DotNetLocalTool.TryCreate("xmldocmd") is DotNetLocalTool xmldocmd) { foreach (var assemblyPath in assemblyPaths) { xmldocmd.Run(GetXmlDocArgs(assemblyPath)); } } else { var dotNetTools = settings.DotNetTools ?? new DotNetTools(Path.Combine("tools", "bin")); var xmlDocMarkdownVersion = settings.DocsSettings?.ToolVersion ?? "2.0.1"; foreach (var assemblyPath in assemblyPaths) { RunApp(dotNetTools.GetToolPath($"xmldocmd/{xmlDocMarkdownVersion}"), GetXmlDocArgs(assemblyPath)); } } } else { Console.WriteLine($"Documentation not generated for {projectName}; assembly not found."); }