public void GetRepository_should_return_correct_value_when_called() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); var repo1 = new RepositoryResource { Alias = "repo1", Id = "repo1", Type = "git", }; var repo2 = new RepositoryResource { Alias = "repo2", Id = "repo2", Type = "git", }; var repoSelf = new RepositoryResource { Alias = "self", Id = "repo3", Type = "git", }; Assert.Equal(repo1, RepositoryUtil.GetRepository(new[] { repo1, repo2 }, "repo1")); Assert.Equal(repo2, RepositoryUtil.GetRepository(new[] { repo1, repo2 }, "repo2")); Assert.Equal(repo1, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "repo1")); Assert.Equal(repo2, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "repo2")); Assert.Equal(repoSelf, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "self")); Assert.Equal(null, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "unknown")); } }
private bool TryGetRepositoryInfo(IExecutionContext executionContext, out RepositoryInfo repoInfo) { // Return the matching repository resource and its source provider. Trace.Entering(); repoInfo = new RepositoryInfo(); var extensionManager = HostContext.GetService <IExtensionManager>(); List <ISourceProvider> sourceProviders = extensionManager.GetExtensions <ISourceProvider>(); var primaryRepository = RepositoryUtil.GetRepository(executionContext.Repositories); if (primaryRepository != null) { var sourceProvider = sourceProviders.FirstOrDefault(x => string.Equals(x.RepositoryType, primaryRepository.Type, StringComparison.OrdinalIgnoreCase)); if (sourceProvider != null) { repoInfo.Repository = primaryRepository; repoInfo.SourceProvider = sourceProvider; return(true); } } return(false); }
private void UpdateCheckoutTasksAndVariables(IExecutionContext executionContext, IList <JobStep> steps, RepositoryInfo repoInfo, string pipelineWorkspaceDirectory) { bool?submoduleCheckout = null; // RepoClean may be set from the server, so start with the server value bool?repoClean = executionContext.Variables.GetBoolean(Constants.Variables.Build.RepoClean); foreach (var checkoutTask in steps.Where(x => x.IsCheckoutTask()).Select(x => x as TaskStep)) { if (!checkoutTask.Inputs.TryGetValue(PipelineConstants.CheckoutTaskInputs.Repository, out string repositoryAlias)) { // If the checkout task isn't associated with a repo, just skip it Trace.Info($"Checkout task {checkoutTask.Name} does not have a repository property."); continue; } // Update the checkout "Clean" property for all repos, if the variable was set by the server. if (repoClean != null) { checkoutTask.Inputs[PipelineConstants.CheckoutTaskInputs.Clean] = repoClean.Value.ToString(); } // If this is the primary repository, use it to get the variable values if (RepositoryUtil.IsPrimaryRepositoryName(repositoryAlias)) { submoduleCheckout = checkoutTask.Inputs.ContainsKey(PipelineConstants.CheckoutTaskInputs.Submodules); repoClean = repoClean ?? checkoutTask.Inputs.ContainsKey(PipelineConstants.CheckoutTaskInputs.Clean); } // Update the checkout task display name if not already set if (string.IsNullOrEmpty(checkoutTask.DisplayName) || string.Equals(checkoutTask.DisplayName, "Checkout", StringComparison.OrdinalIgnoreCase)) { var repository = RepositoryUtil.GetRepository(executionContext.Repositories, repositoryAlias); if (repository != null) { string repoName = repository.Properties.Get <string>(RepositoryPropertyNames.Name); string version = RepositoryUtil.TrimStandardBranchPrefix(repository.Properties.Get <string>(RepositoryPropertyNames.Ref)); string path = null; if (checkoutTask.Inputs.ContainsKey(PipelineConstants.CheckoutTaskInputs.Path)) { path = checkoutTask.Inputs[PipelineConstants.CheckoutTaskInputs.Path]; } else { path = IOUtil.MakeRelative(repository.Properties.Get <string>(RepositoryPropertyNames.Path), pipelineWorkspaceDirectory); } checkoutTask.DisplayName = StringUtil.Loc("CheckoutTaskDisplayNameFormat", repoName, version, path); } else { Trace.Info($"Checkout task {checkoutTask.Name} has a repository property {repositoryAlias} that does not match any repository resource."); } } } // Set variables if (submoduleCheckout.HasValue) { executionContext.SetVariable(Constants.Variables.Build.RepoGitSubmoduleCheckout, submoduleCheckout.Value.ToString()); } if (repoClean.HasValue) { executionContext.SetVariable(Constants.Variables.Build.RepoClean, repoClean.Value.ToString()); } }
private void UpdateCheckoutTasksAndVariables(IExecutionContext executionContext, IList <JobStep> steps, string pipelineWorkspaceDirectory) { bool?submoduleCheckout = null; // RepoClean may be set from the server, so start with the server value bool?repoCleanFromServer = executionContext.Variables.GetBoolean(Constants.Variables.Build.RepoClean); // The value for the global clean option will be set in this variable based on Self repository clean input if the global value weren't set by the server bool?repoCleanFromSelf = null; var checkoutTasks = steps.Where(x => x.IsCheckoutTask()).Select(x => x as TaskStep).ToList(); var hasOnlyOneCheckoutTask = checkoutTasks.Count == 1; foreach (var checkoutTask in checkoutTasks) { if (!checkoutTask.Inputs.TryGetValue(PipelineConstants.CheckoutTaskInputs.Repository, out string repositoryAlias)) { // If the checkout task isn't associated with a repo, just skip it Trace.Info($"Checkout task {checkoutTask.Name} does not have a repository property."); continue; } // Update the checkout "Clean" property for all repos, if the variable was set by the server. if (repoCleanFromServer.HasValue) { checkoutTask.Inputs[PipelineConstants.CheckoutTaskInputs.Clean] = repoCleanFromServer.Value.ToString(); } Trace.Info($"Checking repository name {repositoryAlias}"); // If this is the primary repository, use it to get the variable values // A repository is considered the primary one if the name is 'self' or if there is only // one checkout task. This is because Designer builds set the name of the repository something // other than 'self' if (hasOnlyOneCheckoutTask || RepositoryUtil.IsPrimaryRepositoryName(repositoryAlias)) { submoduleCheckout = checkoutTask.Inputs.ContainsKey(PipelineConstants.CheckoutTaskInputs.Submodules); if (!repoCleanFromServer.HasValue && checkoutTask.Inputs.TryGetValue(PipelineConstants.CheckoutTaskInputs.Clean, out string cleanInputValue)) { repoCleanFromSelf = Boolean.TryParse(cleanInputValue, out bool cleanValue) ? cleanValue : true; } } // Update the checkout task display name if not already set if (string.IsNullOrEmpty(checkoutTask.DisplayName) || string.Equals(checkoutTask.DisplayName, "Checkout", StringComparison.OrdinalIgnoreCase) || // this is the default for jobs string.Equals(checkoutTask.DisplayName, checkoutTask.Name, StringComparison.OrdinalIgnoreCase)) // this is the default for deployment jobs { var repository = RepositoryUtil.GetRepository(executionContext.Repositories, repositoryAlias); if (repository != null) { string repoName = repository.Properties.Get <string>(RepositoryPropertyNames.Name); string version = RepositoryUtil.TrimStandardBranchPrefix(repository.Properties.Get <string>(RepositoryPropertyNames.Ref)); string path = null; if (checkoutTask.Inputs.ContainsKey(PipelineConstants.CheckoutTaskInputs.Path)) { path = checkoutTask.Inputs[PipelineConstants.CheckoutTaskInputs.Path]; } else { path = IOUtil.MakeRelative(repository.Properties.Get <string>(RepositoryPropertyNames.Path), pipelineWorkspaceDirectory); } checkoutTask.DisplayName = StringUtil.Loc("CheckoutTaskDisplayNameFormat", repoName, version, path); } else { Trace.Info($"Checkout task {checkoutTask.Name} has a repository property {repositoryAlias} that does not match any repository resource."); } } } // Set variables if (submoduleCheckout.HasValue) { executionContext.SetVariable(Constants.Variables.Build.RepoGitSubmoduleCheckout, submoduleCheckout.Value.ToString()); } if (repoCleanFromSelf.HasValue) { executionContext.SetVariable(Constants.Variables.Build.RepoClean, repoCleanFromSelf.Value.ToString()); } }
public TrackingConfig PrepareDirectory( IExecutionContext executionContext, IList <RepositoryResource> repositories, WorkspaceOptions workspace) { // Validate parameters. Trace.Entering(); ArgUtil.NotNull(executionContext, nameof(executionContext)); ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables)); ArgUtil.NotNull(repositories, nameof(repositories)); // Get the primary repository (self) var primaryRepository = RepositoryUtil.GetRepository(repositories); ArgUtil.NotNull(primaryRepository, nameof(primaryRepository)); // TODO (next PR): We need to modify the Tracking file to handle multiple repositories (currently we are only tracking the self repo) var trackingManager = HostContext.GetService <ITrackingManager>(); // Defer to the source provider to calculate the hash key. Trace.Verbose("Calculating build directory hash key."); string hashKey = primaryRepository.GetSourceDirectoryHashKey(executionContext); Trace.Verbose($"Hash key: {hashKey}"); // Load the existing tracking file if one already exists. string trackingFile = Path.Combine( HostContext.GetDirectory(WellKnownDirectory.Work), Constants.Build.Path.SourceRootMappingDirectory, executionContext.Variables.System_CollectionId, executionContext.Variables.System_DefinitionId, Constants.Build.Path.TrackingConfigFile); Trace.Verbose($"Loading tracking config if exists: {trackingFile}"); TrackingConfigBase existingConfig = trackingManager.LoadIfExists(executionContext, trackingFile); // Check if the build needs to be garbage collected. If the hash key // has changed, then the existing build directory cannot be reused. TrackingConfigBase garbageConfig = null; if (existingConfig != null && !string.Equals(existingConfig.HashKey, hashKey, StringComparison.OrdinalIgnoreCase)) { // Just store a reference to the config for now. It can safely be // marked for garbage collection only after the new build directory // config has been created. Trace.Verbose($"Hash key from existing tracking config does not match. Existing key: {existingConfig.HashKey}"); garbageConfig = existingConfig; existingConfig = null; } // Create a new tracking config if required. TrackingConfig newConfig; if (existingConfig == null) { Trace.Verbose("Creating a new tracking config file."); var agentSetting = HostContext.GetService <IConfigurationStore>().GetSettings(); newConfig = trackingManager.Create( executionContext, primaryRepository, hashKey, trackingFile, primaryRepository.TestOverrideBuildDirectory(agentSetting)); ArgUtil.NotNull(newConfig, nameof(newConfig)); } else { // Convert legacy format to the new format if required. newConfig = ConvertToNewFormat(executionContext, primaryRepository, existingConfig); // Fill out repository type if it's not there. // repository type is a new property introduced for maintenance job if (string.IsNullOrEmpty(newConfig.RepositoryType)) { newConfig.RepositoryType = primaryRepository.Type; } // For existing tracking config files, update the job run properties. Trace.Verbose("Updating job run properties."); trackingManager.UpdateJobRunProperties(executionContext, newConfig, trackingFile); } // Mark the old configuration for garbage collection. if (garbageConfig != null) { Trace.Verbose("Marking existing config for garbage collection."); trackingManager.MarkForGarbageCollection(executionContext, garbageConfig); } // Prepare the build directory. // There are 2 ways to provide build directory clean policy. // 1> set definition variable build.clean or agent.clean.buildDirectory. (on-prem user need to use this, since there is no Web UI in TFS 2016) // 2> select source clean option in definition repository tab. (VSTS will have this option in definition designer UI) BuildCleanOption cleanOption = GetBuildDirectoryCleanOption(executionContext, workspace); CreateDirectory( executionContext, description: "build directory", path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory), deleteExisting: cleanOption == BuildCleanOption.All); CreateDirectory( executionContext, description: "artifacts directory", path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.ArtifactsDirectory), deleteExisting: true); CreateDirectory( executionContext, description: "test results directory", path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.TestResultsDirectory), deleteExisting: true); CreateDirectory( executionContext, description: "binaries directory", path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory, Constants.Build.Path.BinariesDirectory), deleteExisting: cleanOption == BuildCleanOption.Binary); CreateDirectory( executionContext, description: "source directory", path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.SourcesDirectory), deleteExisting: cleanOption == BuildCleanOption.Source); // Set the default clone path for each repository (the Checkout task may override this later) foreach (var repository in repositories) { var repoPath = GetDefaultRepositoryPath(executionContext, repository, newConfig.BuildDirectory, newConfig.SourcesDirectory); Trace.Info($"Set repository path for repository {repository.Alias} to '{repoPath}'"); repository.Properties.Set <string>(RepositoryPropertyNames.Path, repoPath); } return(newConfig); }