コード例 #1
0
        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"));
            }
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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());
            }
        }
コード例 #4
0
        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());
            }
        }
コード例 #5
0
        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);
        }