Esempio n. 1
0
 public ChangeSetViewModel(ChangeSet changeSet)
 {
     Id = changeSet.Id;
     ShortId = changeSet.Id.Substring(0, 12);
     AuthorName = changeSet.AuthorName;
     EmailHash = String.IsNullOrEmpty(changeSet.AuthorEmail) ? null : Hash(changeSet.AuthorEmail);
     Date = changeSet.Timestamp.ToString("u");
     Message = Process(changeSet.Message);
     // Show first line only
     var reader = new StringReader(changeSet.Message);
     Summary = Process(Trim(reader.ReadLine(), 300));
 }
Esempio n. 2
0
        public void GetOrCreateStatusFileUpdatesFileIfItAlreadyExists()
        {
            // Arrange
            var changeSet = new ChangeSet("test-changeset-id", "author", "*****@*****.**", "commit message", DateTimeOffset.UtcNow);
            var status = new Mock<IDeploymentStatusManager>(MockBehavior.Strict);
            var statusFile = new TestDeploymentStatusFile();
            status.Setup(s => s.Open("test-changeset-id")).Returns(statusFile).Verifiable();
            var deploymentManager = CreateDeploymentManager(status: status.Object);
            var tracer = Mock.Of<ITracer>();

            // Act
            deploymentManager.GetOrCreateStatusFile(changeSet, tracer, "test-deployer");

            // Assert
            status.Verify();
            Assert.Equal("test-deployer", statusFile.Deployer);
            Assert.Equal("author", statusFile.Author);
            Assert.Equal("*****@*****.**", statusFile.AuthorEmail);
            Assert.Equal("commit message", statusFile.Message);
        }
Esempio n. 3
0
 public Task DeployAsync(IRepository repository, ChangeSet changeSet, string deployer, bool clean, bool needFileUpdate = true)
 {
     ++DeployCount;
     return Task.FromResult(1);
 }
Esempio n. 4
0
        public void GitRepoParsesCommitDetails(string id, ChangeSet expectedChangeset)
        {
            foreach (Type gitRepoType in new[] { typeof(LibGit2SharpRepository), typeof(GitExeRepository) })
            {
                using (var testRepository = Git.Clone("Mvc3Application_NoSolution"))
                {
                    // Arrange
                    var gitRepo = (IGitRepository)Activator.CreateInstance(gitRepoType, testRepository.Environment, new MockDeploymentSettingsManager(), NullTracerFactory.Instance);

                    // Act
                    var changeset = gitRepo.GetChangeSet(id);

                    // Assert
                    Assert.Equal(expectedChangeset.Id, changeset.Id);
                    Assert.Equal(expectedChangeset.AuthorName, changeset.AuthorName);
                    Assert.Equal(expectedChangeset.AuthorEmail, changeset.AuthorEmail);
                    Assert.Equal(expectedChangeset.Message, changeset.Message.Trim());
                    Assert.Equal(expectedChangeset.Timestamp, changeset.Timestamp);
                }
            }
        }
Esempio n. 5
0
        // key goal is to create background tracer that is independent of request.
        public static void PerformBackgroundDeployment(DeploymentInfo deployInfo, IEnvironment environment, IDeploymentSettingsManager settings, TraceLevel traceLevel, Uri uri, IDisposable tempDeployment, IAutoSwapHandler autoSwapHandler, ChangeSet tempChangeSet)
        {
            var tracer = traceLevel <= TraceLevel.Off ? NullTracer.Instance : new XmlTracer(environment.TracePath, traceLevel);
            var traceFactory = new TracerFactory(() => tracer);

            var backgroundTrace = tracer.Step(XmlTracer.BackgroundTrace, new Dictionary<string, string>
            {
                {"url", uri.AbsolutePath},
                {"method", "POST"}
            });

            Task.Run(() =>
            {
                try
                {
                    // lock related
                    string lockPath = Path.Combine(environment.SiteRootPath, Constants.LockPath);
                    string deploymentLockPath = Path.Combine(lockPath, Constants.DeploymentLockFile);
                    string statusLockPath = Path.Combine(lockPath, Constants.StatusLockFile);
                    string hooksLockPath = Path.Combine(lockPath, Constants.HooksLockFile);
                    var statusLock = new LockFile(statusLockPath, traceFactory);
                    var hooksLock = new LockFile(hooksLockPath, traceFactory);
                    var deploymentLock = new DeploymentLockFile(deploymentLockPath, traceFactory);

                    var analytics = new Analytics(settings, new ServerConfiguration(), traceFactory);
                    var deploymentStatusManager = new DeploymentStatusManager(environment, analytics, statusLock);
                    var repositoryFactory = new RepositoryFactory(environment, settings, traceFactory);
                    var siteBuilderFactory = new SiteBuilderFactory(new BuildPropertyProvider(), environment);
                    var webHooksManager = new WebHooksManager(tracer, environment, hooksLock);
                    var functionManager = new FunctionManager(environment, traceFactory);
                    var deploymentManager = new DeploymentManager(siteBuilderFactory, environment, traceFactory, analytics, settings, deploymentStatusManager, deploymentLock, NullLogger.Instance, webHooksManager, autoSwapHandler, functionManager);
                    var fetchHandler = new FetchHandler(tracer, deploymentManager, settings, deploymentStatusManager, deploymentLock, environment, null, repositoryFactory, null);

                    // Perform deployment
                    var acquired = deploymentLock.TryLockOperation(() =>
                    {
                        fetchHandler.PerformDeployment(deployInfo, tempDeployment, tempChangeSet).Wait();
                    }, TimeSpan.Zero);

                    if (!acquired)
                    {
                        if (tempDeployment != null)
                        {
                            tempDeployment.Dispose();
                        }

                        using (tracer.Step("Update pending deployment marker file"))
                        {
                            // REVIEW: This makes the assumption that the repository url is the same.
                            // If it isn't the result would be buggy either way.
                            FileSystemHelpers.SetLastWriteTimeUtc(fetchHandler._markerFilePath, DateTime.UtcNow);
                        }
                    }
                }
                catch (Exception ex)
                {
                    tracer.TraceError(ex);
                }
                finally
                {
                    backgroundTrace.Dispose();
                }
            });
        }
Esempio n. 6
0
        public async Task PerformDeployment(DeploymentInfo deploymentInfo, IDisposable tempDeployment = null, ChangeSet tempChangeSet = null)
        {
            DateTime currentMarkerFileUTC;
            DateTime nextMarkerFileUTC = FileSystemHelpers.GetLastWriteTimeUtc(_markerFilePath);

            do
            {
                // save the current marker
                currentMarkerFileUTC = nextMarkerFileUTC;

                string targetBranch = _settings.GetBranch();

                using (_tracer.Step("Performing fetch based deployment"))
                {
                    // create temporary deployment before the actual deployment item started
                    // this allows portal ui to readily display on-going deployment (not having to wait for fetch to complete).
                    // in addition, it captures any failure that may occur before the actual deployment item started
                    tempDeployment = tempDeployment ?? _deploymentManager.CreateTemporaryDeployment(
                                                    Resources.ReceivingChanges,
                                                    out tempChangeSet,
                                                    deploymentInfo.TargetChangeset,
                                                    deploymentInfo.Deployer);

                    ILogger innerLogger = null;
                    try
                    {
                        ILogger logger = _deploymentManager.GetLogger(tempChangeSet.Id);

                        // Fetch changes from the repository
                        innerLogger = logger.Log(Resources.FetchingChanges);

                        IRepository repository = _repositoryFactory.EnsureRepository(deploymentInfo.RepositoryType);

                        try
                        {
                            await deploymentInfo.Handler.Fetch(repository, deploymentInfo, targetBranch, innerLogger);
                        }
                        catch (BranchNotFoundException)
                        {
                            // mark no deployment is needed
                            deploymentInfo.TargetChangeset = null;
                        }

                        // set to null as Deploy() below takes over logging
                        innerLogger = null;

                        // The branch or commit id to deploy
                        string deployBranch = !String.IsNullOrEmpty(deploymentInfo.CommitId) ? deploymentInfo.CommitId : targetBranch;

                        // In case the commit or perhaps fetch do no-op.
                        if (deploymentInfo.TargetChangeset != null && ShouldDeploy(repository, deploymentInfo, deployBranch))
                        {
                            // Perform the actual deployment
                            var changeSet = repository.GetChangeSet(deployBranch);

                            if (changeSet == null && !String.IsNullOrEmpty(deploymentInfo.CommitId))
                            {
                                throw new InvalidOperationException(String.Format("Invalid revision '{0}'!", deploymentInfo.CommitId));
                            }

                            // Here, we don't need to update the working files, since we know Fetch left them in the correct state
                            // unless for GenericHandler where specific commitId is specified
                            bool deploySpecificCommitId = !String.IsNullOrEmpty(deploymentInfo.CommitId);

                            await _deploymentManager.DeployAsync(repository, changeSet, deploymentInfo.Deployer, clean: false, needFileUpdate: deploySpecificCommitId);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (innerLogger != null)
                        {
                            innerLogger.Log(ex);
                        }

                        // In case the commit or perhaps fetch do no-op.
                        if (deploymentInfo.TargetChangeset != null)
                        {
                            IDeploymentStatusFile statusFile = _status.Open(deploymentInfo.TargetChangeset.Id);
                            if (statusFile != null)
                            {
                                statusFile.MarkFailed();
                            }
                        }

                        throw;
                    }

                    // only clean up temp deployment if successful
                    tempDeployment.Dispose();
                }

                // check marker file and, if changed (meaning new /deploy request), redeploy.
                nextMarkerFileUTC = FileSystemHelpers.GetLastWriteTimeUtc(_markerFilePath);
            } while (deploymentInfo.IsReusable && currentMarkerFileUTC != nextMarkerFileUTC);
        }
Esempio n. 7
0
 public void Clean()
 {
     _latestChangeSet = null;
 }
Esempio n. 8
0
        internal IDeploymentStatusFile GetOrCreateStatusFile(ChangeSet changeSet, ITracer tracer, string deployer)
        {
            string id = changeSet.Id;

            using (tracer.Step("Collecting changeset information"))
            {
                // Check if the status file already exists. This would happen when we're doing a redeploy
                IDeploymentStatusFile statusFile = _status.Open(id);
                if (statusFile == null)
                {
                    // Create the status file and store information about the commit
                    statusFile = _status.Create(id);
                }
                statusFile.Message = changeSet.Message;
                statusFile.Author = changeSet.AuthorName;
                statusFile.Deployer = deployer;
                statusFile.AuthorEmail = changeSet.AuthorEmail;
                statusFile.IsReadOnly = changeSet.IsReadOnly;
                statusFile.Save();

                return statusFile;
            }
        }
Esempio n. 9
0
        public async Task DeployAsync(IRepository repository, ChangeSet changeSet, string deployer, bool clean, bool needFileUpdate = true)
        {
            using (var deploymentAnalytics = new DeploymentAnalytics(_analytics, _settings))
            {
                Exception exception = null;
                ITracer tracer = _traceFactory.GetTracer();
                IDisposable deployStep = null;
                ILogger innerLogger = null;
                string targetBranch = null;

                // If we don't get a changeset, find out what branch we should be deploying and get the commit ID from it
                if (changeSet == null)
                {
                    targetBranch = _settings.GetBranch();

                    changeSet = repository.GetChangeSet(targetBranch);

                    if (changeSet == null)
                    {
                        throw new InvalidOperationException(String.Format("The current deployment branch is '{0}', but nothing has been pushed to it", targetBranch));
                    }
                }

                string id = changeSet.Id;
                IDeploymentStatusFile statusFile = null;
                try
                {
                    deployStep = tracer.Step("DeploymentManager.Deploy(id)");
                    // Remove the old log file for this deployment id
                    string logPath = GetLogPath(id);
                    FileSystemHelpers.DeleteFileSafe(logPath);

                    statusFile = GetOrCreateStatusFile(changeSet, tracer, deployer);
                    statusFile.MarkPending();

                    ILogger logger = GetLogger(changeSet.Id);

                    if (needFileUpdate)
                    {
                        using (tracer.Step("Updating to specific changeset"))
                        {
                            innerLogger = logger.Log(Resources.Log_UpdatingBranch, targetBranch ?? id);

                            using (var writer = new ProgressWriter())
                            {
                                // Update to the specific changeset or branch
                                repository.Update(targetBranch ?? id);
                            }
                        }
                    }

                    if (_settings.ShouldUpdateSubmodules())
                    {
                        using (tracer.Step("Updating submodules"))
                        {
                            innerLogger = logger.Log(Resources.Log_UpdatingSubmodules);

                            repository.UpdateSubmodules();
                        }
                    }

                    if (clean)
                    {
                        tracer.Trace("Cleaning {0} repository", repository.RepositoryType);

                        innerLogger = logger.Log(Resources.Log_CleaningRepository, repository.RepositoryType);

                        repository.Clean();
                    }

                    // set to null as Build() below takes over logging
                    innerLogger = null;

                    // Perform the build deployment of this changeset
                    await Build(changeSet, tracer, deployStep, repository, deploymentAnalytics);
                }
                catch (Exception ex)
                {
                    exception = ex;

                    if (innerLogger != null)
                    {
                        innerLogger.Log(ex);
                    }

                    if (statusFile != null)
                    {
                        MarkStatusComplete(statusFile, success: false);
                    }

                    tracer.TraceError(ex);

                    deploymentAnalytics.Error = ex.ToString();

                    if (deployStep != null)
                    {
                        deployStep.Dispose();
                    }
                }

                // Reload status file with latest updates
                statusFile = _status.Open(id);
                if (statusFile != null)
                {
                    await _hooksManager.PublishEventAsync(HookEventTypes.PostDeployment, statusFile);
                }

                if (exception != null)
                {
                    throw new DeploymentFailedException(exception);
                }
            }
        }
Esempio n. 10
0
        public void Deploy(IRepository repository, ChangeSet changeSet, string deployer, bool clean)
        {
            ITracer tracer = _traceFactory.GetTracer();
            IDisposable deployStep = null;
            var deploymentRepository = new DeploymentRepository(repository);

            // If we don't get a changeset, find out what branch we should be deploying and update the repo to it
            if (changeSet == null)
            {
                string targetBranch = _settings.GetValue(SettingsKeys.Branch);
                deploymentRepository.Update(targetBranch);

                changeSet = deploymentRepository.GetChangeSet(repository.CurrentId);
            }

            string id = changeSet.Id;
            try
            {
                deployStep = tracer.Step("DeploymentManager.Deploy(id)");

                // Remove the old log file for this deployment id
                string logPath = GetLogPath(id);
                FileSystemHelpers.DeleteFileSafe(logPath);

                ILogger logger = GetOrCreateStatusFile(changeSet, tracer, deployer);

                using (tracer.Step("Updating to specific changeset"))
                {
                    // Update to the the specific changeset
                    deploymentRepository.Update(id);
                }

                using (tracer.Step("Updating submodules"))
                {

                    deploymentRepository.UpdateSubmodules();
                }

                if (clean)
                {
                    tracer.Trace("Cleaning {0} repository", repository.RepositoryType);

                    logger.Log(Resources.Log_CleaningRepository, repository.RepositoryType);

                    deploymentRepository.Clean();
                }

                // Perform the build deployment of this changeset
                Build(id, tracer, deployStep);
            }
            catch (Exception ex)
            {
                tracer.TraceError(ex);

                if (deployStep != null)
                {
                    deployStep.Dispose();
                }

                throw;
            }
        }
Esempio n. 11
0
        public bool Commit(string message, string authorName, string emailAddress)
        {
            var tracer = _traceFactory.GetTracer();
            using (tracer.Step("None repository commit"))
            {
                var changeSet = new ChangeSet(Guid.NewGuid().ToString("N"),
                                              !string.IsNullOrEmpty(authorName) ? authorName : Resources.Deployment_UnknownValue,
                                              !string.IsNullOrEmpty(emailAddress) ? emailAddress : Resources.Deployment_UnknownValue,
                                              message ?? Resources.Deployment_UnknownValue,
                                              DateTimeOffset.UtcNow);

                // Does not support rollback
                changeSet.IsReadOnly = true;

                // The lifetime is per request
                _httpContext.Items[_changeSetKey] = changeSet;

                tracer.Trace("Commit id: " + changeSet.Id, new Dictionary<string, string>
                {
                    { "Messsage", changeSet.Message },
                    { "AuthorName", changeSet.AuthorName },
                    { "AuthorEmail", changeSet.AuthorEmail }
                });
            }

            return true;
        }
Esempio n. 12
0
        public bool Commit(string message, string authorName)
        {
            var tracer = _traceFactory.GetTracer();
            using (tracer.Step("None repository commit"))
            {
                string[] parts = String.IsNullOrEmpty(authorName) ? new string[0] : authorName.Split(new[] { '<', '>' }, StringSplitOptions.RemoveEmptyEntries);

                var changeSet = new ChangeSet(Guid.NewGuid().ToString("N"),
                                              parts.Length > 0 ? parts[0].Trim() : Resources.Deployment_UnknownValue,
                                              parts.Length > 1 ? parts[1].Trim() : Resources.Deployment_UnknownValue,
                                              message ?? Resources.Deployment_UnknownValue,
                                              DateTimeOffset.UtcNow);

                // Does not support rollback
                changeSet.IsReadOnly = true;

                // The lifetime is per request
                _httpContext.Items[_changeSetKey] = changeSet;

                tracer.Trace("Commit id: " + changeSet.Id, new Dictionary<string, string>
                {
                    { "Messsage", changeSet.Message },
                    { "AuthorName", changeSet.AuthorName },
                    { "AuthorEmail", changeSet.AuthorEmail }
                });
            }

            return true;
        }
Esempio n. 13
0
        public IDisposable CreateTemporaryDeployment(string statusText, ChangeSet changeSet = null, string deployedBy = null)
        {
            var tracer = _traceFactory.GetTracer();
            using (tracer.Step("Creating temporary deployment"))
            {
                changeSet = changeSet ?? CreateTemporaryChangeSet();
                DeploymentStatusFile statusFile = CreateStatusFile(changeSet.Id);
                statusFile.Id = changeSet.Id;
                statusFile.Message = changeSet.Message;
                statusFile.Author = changeSet.AuthorName;
                statusFile.Deployer = deployedBy;
                statusFile.AuthorEmail = changeSet.AuthorEmail;
                statusFile.Status = DeployStatus.Pending;
                statusFile.StatusText = statusText;
                statusFile.Save(_fileSystem);
            }

            // Return a handle that deletes the deployment on dispose.
            return new DisposableAction(() =>
            {
                if (changeSet.IsTemporary)
                {
                    DeleteTemporaryDeployment(changeSet.Id);
                }
            });
        }
Esempio n. 14
0
 public void Deploy(IRepository repository, ChangeSet changeSet, string deployer, bool clean, bool needFileUpdate = true)
 {
     ++DeployCount;
 }
Esempio n. 15
0
 public IDisposable CreateTemporaryDeployment(string statusText, out ChangeSet tempChangeSet, ChangeSet changeset = null, string deployedBy = null)
 {
     tempChangeSet = GetChangeSet();
     return new NoopDisposable();
 }
Esempio n. 16
0
        private ILogger GetOrCreateStatusFile(ChangeSet changeSet, ITracer tracer, string deployer)
        {
            string id = changeSet.Id;
            ILogger logger = GetLogger(id);

            using (tracer.Step("Collecting changeset information"))
            {
                // Remove any old instance of a temporary deployment if exists
                DeleteTemporaryDeployment();

                // Check if the status file already exists. This would happen when we're doing a redeploy
                DeploymentStatusFile statusFile = OpenStatusFile(id);
                if (statusFile == null)
                {
                    // Create the status file and store information about the commit
                    statusFile = CreateStatusFile(id);
                    statusFile.Message = changeSet.Message;
                    statusFile.Author = changeSet.AuthorName;
                    statusFile.Deployer = deployer;
                    statusFile.AuthorEmail = changeSet.AuthorEmail;
                    statusFile.Save(_fileSystem);
                }
            }

            return logger;
        }
Esempio n. 17
0
        public void GitRepoParsesCommitDetails(string id, ChangeSet expectedChangeset)
        {
            using (var testRepository = Git.Clone("Mvc3Application_NoSolution"))
            {
                // Arrange
                var gitRepo = new GitExeRepository(testRepository.Environment, new MockDeploymentSettingsManager(), NullTracerFactory.Instance);

                // Act
                var changeset = gitRepo.GetChangeSet(id);

                // Assert
                Assert.Equal(expectedChangeset.Id, changeset.Id);
                Assert.Equal(expectedChangeset.AuthorName, changeset.AuthorName);
                Assert.Equal(expectedChangeset.AuthorEmail, changeset.AuthorEmail);
                Assert.Equal(expectedChangeset.Message, changeset.Message.Trim());
                Assert.Equal(expectedChangeset.Timestamp, changeset.Timestamp);
            }
        }
Esempio n. 18
0
        public IDisposable CreateTemporaryDeployment(string statusText, ChangeSet changeSet = null, string deployedBy = null)
        {
            var tracer = _traceFactory.GetTracer();
            string unknown = Resources.Deployment_UnknownValue;
            using (tracer.Step("Creating temporary deployment"))
            {
                changeSet = changeSet ?? new ChangeSet(TemporaryDeploymentId, unknown, unknown, unknown, DateTimeOffset.MinValue);
                DeploymentStatusFile statusFile = CreateStatusFile(TemporaryDeploymentId);
                statusFile.Id = changeSet.Id;
                statusFile.Message = changeSet.Message;
                statusFile.Author = changeSet.AuthorName;
                statusFile.Deployer = deployedBy;
                statusFile.AuthorEmail = changeSet.AuthorEmail;
                statusFile.Status = DeployStatus.Pending;
                statusFile.StatusText = statusText;
                statusFile.Save(_fileSystem);
            }

            // Return a handle that deletes the deployment on dispose.
            return new DisposableAction(DeleteTemporaryDeployment);
        }
Esempio n. 19
0
        public IDisposable CreateTemporaryDeployment(string statusText, out ChangeSet tempChangeSet, ChangeSet changeSet = null, string deployedBy = null)
        {
            var tracer = _traceFactory.GetTracer();
            using (tracer.Step("Creating temporary deployment"))
            {
                changeSet = changeSet != null && changeSet.IsTemporary ? changeSet : CreateTemporaryChangeSet();
                IDeploymentStatusFile statusFile = _status.Create(changeSet.Id);
                statusFile.Id = changeSet.Id;
                statusFile.Message = changeSet.Message;
                statusFile.Author = changeSet.AuthorName;
                statusFile.Deployer = deployedBy;
                statusFile.AuthorEmail = changeSet.AuthorEmail;
                statusFile.Status = DeployStatus.Pending;
                statusFile.StatusText = statusText;
                statusFile.IsTemporary = changeSet.IsTemporary;
                statusFile.IsReadOnly = changeSet.IsReadOnly;
                statusFile.Save();
            }

            tempChangeSet = changeSet;

            // Return a handle that deletes the deployment on dispose.
            return new DisposableAction(() =>
            {
                if (changeSet.IsTemporary)
                {
                    _status.Delete(changeSet.Id);
                }
            });
        }
Esempio n. 20
0
        public void Deploy(IRepository repository, ChangeSet changeSet, string deployer, bool clean)
        {
            ITracer tracer = _traceFactory.GetTracer();
            IDisposable deployStep = null;
            ILogger innerLogger = null;
            string targetBranch = null;
            var deploymentRepository = new DeploymentRepository(repository);

            // If we don't get a changeset, find out what branch we should be deploying and get the commit ID from it
            if (changeSet == null)
            {
                targetBranch = _settings.GetBranch();

                changeSet = deploymentRepository.GetChangeSet(targetBranch);
            }

            string id = changeSet.Id;
            IDeploymentStatusFile statusFile = null;
            try
            {
                deployStep = tracer.Step("DeploymentManager.Deploy(id)");

                // Remove the old log file for this deployment id
                string logPath = GetLogPath(id);
                FileSystemHelpers.DeleteFileSafe(logPath);

                statusFile = GetOrCreateStatusFile(changeSet, tracer, deployer);
                statusFile.MarkPending();

                ILogger logger = GetLogger(changeSet.Id);

                using (tracer.Step("Updating to specific changeset"))
                {
                    innerLogger = logger.Log(Resources.Log_UpdatingBranch, targetBranch ?? id);

                    using (var writer = new ProgressWriter())
                    {
                        // Update to the the specific changeset
                        deploymentRepository.Update(id);
                    }
                }

                using (tracer.Step("Updating submodules"))
                {
                    innerLogger = logger.Log(Resources.Log_UpdatingSubmodules);

                    deploymentRepository.UpdateSubmodules();
                }

                if (clean)
                {
                    tracer.Trace("Cleaning {0} repository", repository.RepositoryType);

                    innerLogger = logger.Log(Resources.Log_CleaningRepository, repository.RepositoryType);

                    deploymentRepository.Clean();
                }

                // set to null as Build() below takes over logging
                innerLogger = null;

                // Perform the build deployment of this changeset
                Build(id, tracer, deployStep);
            }
            catch (Exception ex)
            {
                if (innerLogger != null)
                {
                    innerLogger.Log(ex);
                }

                if (statusFile != null)
                {
                    statusFile.MarkFailed();
                }

                tracer.TraceError(ex);

                if (deployStep != null)
                {
                    deployStep.Dispose();
                }

                throw;
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Builds and deploys a particular changeset. Puts all build artifacts in a deployments/{id}
        /// </summary>
        private async Task Build(ChangeSet changeSet, ITracer tracer, IDisposable deployStep, IFileFinder fileFinder, DeploymentAnalytics deploymentAnalytics)
        {
            if (changeSet == null || String.IsNullOrEmpty(changeSet.Id))
            {
                throw new ArgumentException("The changeSet.Id parameter is null or empty", "changeSet.Id");
            }

            ILogger logger = null;
            IDeploymentStatusFile currentStatus = null;
            string buildTempPath = null;
            string id = changeSet.Id;

            try
            {
                logger = GetLogger(id);
                ILogger innerLogger = logger.Log(Resources.Log_PreparingDeployment, TrimId(id));

                currentStatus = _status.Open(id);
                currentStatus.Complete = false;
                currentStatus.StartTime = DateTime.UtcNow;
                currentStatus.Status = DeployStatus.Building;
                currentStatus.StatusText = String.Format(CultureInfo.CurrentCulture, Resources.Status_BuildingAndDeploying, id);
                currentStatus.Save();

                ISiteBuilder builder = null;

                string repositoryRoot = _environment.RepositoryPath;
                var perDeploymentSettings = DeploymentSettingsManager.BuildPerDeploymentSettingsManager(repositoryRoot, _settings);

                try
                {
                    using (tracer.Step("Determining deployment builder"))
                    {
                        builder = _builderFactory.CreateBuilder(tracer, innerLogger, perDeploymentSettings, fileFinder);
                        deploymentAnalytics.ProjectType = builder.ProjectType;
                        tracer.Trace("Builder is {0}", builder.GetType().Name);
                    }
                }
                catch (Exception ex)
                {
                    // If we get a TargetInvocationException, use the inner exception instead to avoid
                    // useless 'Exception has been thrown by the target of an invocation' messages
                    var targetInvocationException = ex as System.Reflection.TargetInvocationException;
                    if (targetInvocationException != null)
                    {
                        ex = targetInvocationException.InnerException;
                    }

                    _globalLogger.Log(ex);

                    innerLogger.Log(ex);

                    MarkStatusComplete(currentStatus, success: false);

                    FailDeployment(tracer, deployStep, deploymentAnalytics, ex);

                    return;
                }

                // Create a directory for the script output temporary artifacts
                // Use tick count (in hex) instead of guid to keep the path for getting to long
                buildTempPath = Path.Combine(_environment.TempPath, DateTime.UtcNow.Ticks.ToString("x"));
                FileSystemHelpers.EnsureDirectory(buildTempPath);

                var context = new DeploymentContext
                {
                    NextManifestFilePath = GetDeploymentManifestPath(id),
                    PreviousManifestFilePath = GetActiveDeploymentManifestPath(),
                    Tracer = tracer,
                    Logger = logger,
                    GlobalLogger = _globalLogger,
                    OutputPath = GetOutputPath(_environment, perDeploymentSettings),
                    BuildTempPath = buildTempPath,
                    CommitId = id,
                    Message = changeSet.Message
                };

                if (context.PreviousManifestFilePath == null)
                {
                    // this file (/site/firstDeploymentManifest) capture the last active deployment when disconnecting SCM
                    context.PreviousManifestFilePath = Path.Combine(_environment.SiteRootPath, Constants.FirstDeploymentManifestFileName);
                    if (!FileSystemHelpers.FileExists(context.PreviousManifestFilePath))
                    {
                        // In the first deployment we want the wwwroot directory to be cleaned, we do that using a manifest file
                        // That has the expected content of a clean deployment (only one file: hostingstart.html)
                        // This will result in KuduSync cleaning this file.
                        context.PreviousManifestFilePath = Path.Combine(_environment.ScriptPath, Constants.FirstDeploymentManifestFileName);
                    }
                }

                PreDeployment(tracer);

                using (tracer.Step("Building"))
                {
                    try
                    {
                        await builder.Build(context);
                        builder.PostBuild(context);
                        await _functionManager.SyncTriggersAsync();

                        if (_settings.TouchWebConfigAfterDeployment())
                        {
                            TryTouchWebConfig(context);
                        }

                        FinishDeployment(id, deployStep);

                        deploymentAnalytics.Result = DeployStatus.Success.ToString();
                    }
                    catch (Exception ex)
                    {
                        MarkStatusComplete(currentStatus, success: false);

                        FailDeployment(tracer, deployStep, deploymentAnalytics, ex);

                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                FailDeployment(tracer, deployStep, deploymentAnalytics, ex);
            }
            finally
            {
                // Clean the temp folder up
                CleanBuild(tracer, buildTempPath);
            }
        }
Esempio n. 22
0
 public ChangeSetDetail(ChangeSet changeSet)
 {
     ChangeSet = changeSet;
     Files = new Dictionary<string, FileInfo>(StringComparer.OrdinalIgnoreCase);
 }