Esempio n. 1
0
        internal async Task <ChangeSet> Sync(OneDriveInfo info, IRepository repository)
        {
            ChangeSet     changeSet = null;
            string        cursor    = _settings.GetValue(CursorKey);
            ChangesResult changes   = null;

            // We truncate cursor value in filename but keep it unharmed in the trace content
            using (_tracer.Step("Getting delta changes with cursor: {0}...", cursor.Truncate(5)))
                using (_tracer.Step("cursor: {0}", cursor))
                {
                    changes = await GetChanges(info.TargetChangeset.Id, info.AccessToken, info.RepositoryUrl, cursor);
                }

            if (changes == null || changes.Count == 0)
            {
                _tracer.Trace("No changes need to be applied.");
                LogMessage(Resources.OneDriveNoChangesFound);
                return(changeSet);
            }

            // for simplicity, use file changes as effective total
            _totals = changes.FileChanges.Count > 0 ? changes.FileChanges.Count : changes.Count;

            string hoststarthtml = Path.Combine(_environment.WebRootPath, Constants.HostingStartHtml);

            FileSystemHelpers.DeleteFileSafe(hoststarthtml);

            using (new Timer(UpdateStatusFile, state: info.TargetChangeset.Id, dueTime: TimeSpan.FromSeconds(5), period: TimeSpan.FromSeconds(5)))
                using (_tracer.Step("Applying {0} changes ...", _totals))
                {
                    LogMessage(Resources.OneDriveApplyingChanges, _totals);

                    // perform action seperately, so that can ensure timestamp on directory
                    // e.g two changes:
                    //  (new) file /a/b/c.txt
                    //  (new) dir  /a/b
                    //  if created dir first then create file. file creation will trigger folder timestamp change.
                    //  which will result in "/a/b" has timestamp from the monent of file creation instead of the timestamp value from server, where value supposed to be set by code specifically.
                    await ApplyChangesParallel(changes.DeletionChanges, info.AccessToken, maxParallelCount : 1, countSuccess : changes.FileChanges.Count == 0);
                    await ApplyChangesParallel(changes.FileChanges, info.AccessToken, maxParallelCount : MaxConcurrentRequests, countSuccess : true);

                    // apply folder changes at last to maintain same timestamp as in OneDrive
                    await ApplyChangesParallel(changes.DirectoryChanges, info.AccessToken, maxParallelCount : 1, countSuccess : changes.FileChanges.Count == 0);

                    _tracer.Trace("{0} succeeded, {1} failed", _successCount, _failedCount);
                    LogMessage(Resources.OneDriveApplyResult, _successCount, _failedCount);

                    string message = _failedCount > 0 ?
                                     string.Format(CultureInfo.CurrentCulture, Resources.OneDrive_SynchronizedWithFailure, _successCount, _totals, _failedCount) :
                                     string.Format(CultureInfo.CurrentCulture, Resources.OneDrive_Synchronized, _totals);

                    // Commit anyway even partial change
                    if (repository.Commit(message, info.AuthorName, info.AuthorEmail))
                    {
                        changeSet = repository.GetChangeSet("HEAD");
                    }

                    if (_failedCount > 0)
                    {
                        // signal deployment failied
                        throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.OneDriveApplyResult, _successCount, _failedCount));
                    }
                }

            // finally keep a copy of the new cursor
            _settings.SetValue(CursorKey, changes.Cursor);

            return(changeSet);
        }
Esempio n. 2
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. 3
0
        public HttpResponseMessage MiniDump(int id, int dumpType = 0, string format = null)
        {
            using (_tracer.Step("ProcessController.MiniDump"))
            {
                DumpFormat dumpFormat = ParseDumpFormat(format, DumpFormat.Raw);
                if (dumpFormat != DumpFormat.Raw && dumpFormat != DumpFormat.Zip)
                {
                    return(Request.CreateErrorResponse(HttpStatusCode.BadRequest,
                                                       String.Format(CultureInfo.CurrentCulture, Resources.Error_DumpFormatNotSupported, dumpFormat)));
                }

                string siteSku = _settings.GetWebSiteSku();
                if ((MINIDUMP_TYPE)dumpType == MINIDUMP_TYPE.WithFullMemory && siteSku.Equals(Constants.FreeSKU, StringComparison.OrdinalIgnoreCase))
                {
                    return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError,
                                                       String.Format(CultureInfo.CurrentCulture, Resources.Error_FullMiniDumpNotSupported, siteSku)));
                }

                var process = GetProcessById(id);

                string dumpFile = Path.Combine(_environment.LogFilesPath, "minidump", "minidump.dmp");
                FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(dumpFile));
                FileSystemHelpers.DeleteFileSafe(dumpFile);

                try
                {
                    using (_tracer.Step(String.Format("MiniDump pid={0}, name={1}, file={2}", process.Id, process.ProcessName, dumpFile)))
                    {
                        process.MiniDump(dumpFile, (MINIDUMP_TYPE)dumpType);
                        _tracer.Trace("MiniDump size={0}", new FileInfo(dumpFile).Length);
                    }
                }
                catch (Exception ex)
                {
                    _tracer.TraceError(ex);
                    FileSystemHelpers.DeleteFileSafe(dumpFile);
                    return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message));
                }

                if (dumpFormat == DumpFormat.Raw)
                {
                    string responseFileName = GetResponseFileName(process.ProcessName, "dmp");

                    HttpResponseMessage response = Request.CreateResponse();
                    response.Content = new StreamContent(FileStreamWrapper.OpenRead(dumpFile));
                    response.Content.Headers.ContentType                 = new MediaTypeHeaderValue("application/octet-stream");
                    response.Content.Headers.ContentDisposition          = new ContentDispositionHeaderValue("attachment");
                    response.Content.Headers.ContentDisposition.FileName = responseFileName;
                    return(response);
                }
                else if (dumpFormat == DumpFormat.Zip)
                {
                    string responseFileName = GetResponseFileName(process.ProcessName, "zip");

                    HttpResponseMessage response = Request.CreateResponse();
                    response.Content = ZipStreamContent.Create(responseFileName, _tracer, zip =>
                    {
                        try
                        {
                            zip.AddFile(dumpFile, _tracer, String.Empty);
                        }
                        finally
                        {
                            FileSystemHelpers.DeleteFileSafe(dumpFile);
                        }

                        foreach (var fileName in new[] { "sos.dll", "mscordacwks.dll" })
                        {
                            string filePath = Path.Combine(ProcessExtensions.ClrRuntimeDirectory, fileName);
                            if (FileSystemHelpers.FileExists(filePath))
                            {
                                zip.AddFile(filePath, _tracer, String.Empty);
                            }
                        }
                    });
                    return(response);
                }
                else
                {
                    return(Request.CreateErrorResponse(HttpStatusCode.BadRequest,
                                                       String.Format(CultureInfo.CurrentCulture, Resources.Error_DumpFormatNotSupported, dumpFormat)));
                }
            }
        }
Esempio n. 4
0
        public void Delete(int deleteWebRoot = 0, int ignoreErrors = 0)
        {
            // Fail if a deployment is in progress
            bool acquired = _deploymentLock.TryLockOperation(() =>
            {
                using (_tracer.Step("Deleting repository"))
                {
                    string repositoryPath = Path.Combine(_environment.SiteRootPath, Constants.RepositoryPath);
                    if (String.Equals(repositoryPath, _environment.RepositoryPath, StringComparison.OrdinalIgnoreCase))
                    {
                        // Delete the repository
                        FileSystemHelpers.DeleteDirectorySafe(_environment.RepositoryPath, ignoreErrors != 0);
                    }
                    else
                    {
                        // Just delete .git folder
                        FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.RepositoryPath, ".git"), ignoreErrors != 0);

                        FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.RepositoryPath, ".hg"), ignoreErrors != 0);
                    }
                }

                using (_tracer.Step("Deleting ssh key"))
                {
                    // Delete the ssh key
                    FileSystemHelpers.DeleteDirectorySafe(_environment.SSHKeyPath, ignoreErrors != 0);
                }

                if (deleteWebRoot != 0)
                {
                    using (_tracer.Step("Deleting web root"))
                    {
                        // Delete the wwwroot folder
                        FileSystemHelpers.DeleteDirectoryContentsSafe(_environment.WebRootPath, ignoreErrors != 0);
                    }

                    using (_tracer.Step("Deleting diagnostics"))
                    {
                        // Delete the diagnostic log. This is a slight abuse of deleteWebRoot, but the
                        // real semantic is more to reset the site to a fully clean state
                        FileSystemHelpers.DeleteDirectorySafe(_environment.DiagnosticsPath, ignoreErrors != 0);
                    }

                    // Delete first deployment manifest since it is no longer needed
                    FileSystemHelpers.DeleteFileSafe(Path.Combine(_environment.SiteRootPath, Constants.FirstDeploymentManifestFileName));
                }
                else
                {
                    using (_tracer.Step("Updating initial deployment manifest"))
                    {
                        // The active deployment manifest becomes the baseline initial deployment manifest
                        // When SCM is reconnected, the new deployment will use this manifest to clean the wwwroot
                        SaveInitialDeploymentManifest();
                    }
                }

                using (_tracer.Step("Deleting deployment cache"))
                {
                    // Delete the deployment cache
                    FileSystemHelpers.DeleteDirectorySafe(_environment.DeploymentsPath, ignoreErrors != 0);
                }
            }, TimeSpan.Zero);

            if (!acquired)
            {
                HttpResponseMessage response = Request.CreateErrorResponse(HttpStatusCode.Conflict, Resources.Error_DeploymentInProgess);
                throw new HttpResponseException(response);
            }
        }
Esempio n. 5
0
        private void WriteEndTrace()
        {
            bool isOutgoingResponse = false;
            bool zeroInfos          = false;

            try
            {
                var info    = _infos.Pop();
                var elapsed = DateTime.UtcNow - info.StartTime;
                var strb    = new StringBuilder();
                if (_isStartElement)
                {
                    strb.Append("/>");
                }
                else
                {
                    strb.Append(new String(' ', _infos.Count * 2));
                    strb.Append("</step>");
                }

                strb.AppendLine(String.Format("<!-- duration: {0:0}ms -->", elapsed.TotalMilliseconds));

                FileSystemHelpers.AppendAllTextToFile(_file, strb.ToString());
                log.Debug(Regex.Replace(strb.ToString(), @"\t|\n|\r", ""));
                _isStartElement = false;

                // adjust filename with statusCode
                if (info.Title == XmlTracer.OutgoingResponseTrace &&
                    _file.EndsWith(PendingXml, StringComparison.OrdinalIgnoreCase))
                {
                    if (!Int32.TryParse(info.Attributes["statusCode"], out _statusCode))
                    {
                        _statusCode = 0;
                    }

                    isOutgoingResponse = true;
                }

                if (_infos.Count == 0)
                {
                    // avoid spamming the traces
                    if (!ShouldTrace(_level, info, _statusCode))
                    {
                        FileSystemHelpers.DeleteFileSafe(_file);
                    }
                    else
                    {
                        var file = _file;
                        if (_file.EndsWith(PendingXml, StringComparison.OrdinalIgnoreCase))
                        {
                            file = file.Replace(PendingXml,
                                                _statusCode <= 0 ? ".xml" : String.Format("_{0}.xml", _statusCode));
                        }

                        file = file.Replace(".xml", String.Format("_{0:0}s.xml", elapsed.TotalSeconds));
                        FileSystemHelpers.MoveFile(_file, file);
                    }

                    _file     = null;
                    zeroInfos = true;
                }
            }
            catch (Exception ex)
            {
                WriteUnexpectedException(ex);
            }
            finally
            {
                if (isOutgoingResponse && zeroInfos)
                {
                    startTagAdded = false;
                    log.Debug("@@@EndTrace@@@\n\n\n");
                }
            }
        }
Esempio n. 6
0
        private void EnsureMaxXmlFiles()
        {
            // _lastCleanup ensures we only check (iterate) the log directory every certain period.
            // _cleanupPending ensures there is one cleanup thread at a time.
            lock (_cleanupLock)
            {
                if (_cleanupPending)
                {
                    return;
                }

                var now = DateTime.UtcNow;
                if (_lastCleanup.AddSeconds(CleanUpIntervalSecs) > now)
                {
                    return;
                }

                _lastCleanup    = now;
                _cleanupPending = true;
            }

            try
            {
                ITracer tracer = this;
                using (tracer.Step("Cleanup Xml Logs"))
                {
                    try
                    {
                        var files = FileSystemHelpers.GetFiles(_path, "*.xml");
                        if (files.Length < MaxXmlFiles)
                        {
                            return;
                        }

                        var toCleanup = files.Length - (MaxXmlFiles * 80) / 100;
                        var attribs   = new Dictionary <string, string>
                        {
                            { "totalFiles", files.Length.ToString() },
                            { "totalCleanup", toCleanup.ToString() }
                        };
                        using (tracer.Step("Cleanup Infos", attribs))
                        {
                            foreach (var file in files.OrderBy(n => n).Take(toCleanup))
                            {
                                if (file.IndexOf("default", StringComparison.OrdinalIgnoreCase) >= 0)
                                {
                                    FileSystemHelpers.DeleteFileSafe(file);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        tracer.TraceError(ex);
                    }
                }
            }
            finally
            {
                _cleanupPending = false;
            }
        }
Esempio n. 7
0
        public static async Task UpdateLocalPackage(this SourceRepository srcRepo, SourceRepository localRepo, PackageIdentity identity, string destinationFolder, string pathToLocalCopyOfNupkg, ITracer tracer)
        {
            tracer.Trace("Performing incremental package update for {0}", identity.Id);
            using (Stream newPackageStream = await srcRepo.GetPackageStream(identity))
            {
                // update file
                var localPackage = await localRepo.GetLatestPackageByIdFromSrcRepo(identity.Id);
                if (localPackage == null)
                {
                    throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, "Package {0} not found from local repo.", identity.Id));
                }
                using (Stream oldPackageStream = await localRepo.GetPackageStream(localPackage.Identity))
                using (ZipFile oldPackageZip = ZipFile.Read(oldPackageStream))
                using (ZipFile newPackageZip = ZipFile.Read(newPackageStream))
                {
                    // we only care about stuff under "content" folder
                    IEnumerable<ZipEntry> oldContentEntries = oldPackageZip.Entries.Where(e => e.FileName.StartsWith(@"content/", StringComparison.InvariantCultureIgnoreCase));
                    IEnumerable<ZipEntry> newContentEntries = newPackageZip.Entries.Where(e => e.FileName.StartsWith(@"content/", StringComparison.InvariantCultureIgnoreCase));
                    List<ZipEntry> filesNeedToUpdate = new List<ZipEntry>();
                    Dictionary<string, ZipEntry> indexedOldFiles = new Dictionary<string, ZipEntry>();
                    foreach (var item in oldContentEntries)
                    {
                        indexedOldFiles.Add(item.FileName.ToLowerInvariant(), item);
                    }

                    foreach (var newEntry in newContentEntries)
                    {
                        var fileName = newEntry.FileName.ToLowerInvariant();
                        if (indexedOldFiles.ContainsKey(fileName))
                        {
                            // file name existed, only update if file has been touched
                            ZipEntry oldEntry = indexedOldFiles[fileName];
                            if (oldEntry.LastModified != newEntry.LastModified)
                            {
                                filesNeedToUpdate.Add(newEntry);
                            }

                            // remove from old index files buffer, the rest will be files that need to be deleted
                            indexedOldFiles.Remove(fileName);
                        }
                        else
                        {
                            // new files
                            filesNeedToUpdate.Add(newEntry);
                        }
                    }

                    int substringStartIndex = @"content/".Length;

                    foreach (var entry in filesNeedToUpdate)
                    {
                        string fullPath = Path.Combine(destinationFolder, entry.FileName.Substring(substringStartIndex));

                        if (entry.IsDirectory)
                        {
                            using (tracer.Step("Ensure directory: {0}", fullPath))
                            {
                                FileSystemHelpers.EnsureDirectory(fullPath.Replace('/', '\\'));
                            }

                            continue;
                        }

                        using (tracer.Step("Adding/Updating file: {0}", fullPath))
                        {
                            FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(fullPath));
                            using (Stream writeStream = FileSystemHelpers.OpenWrite(fullPath))
                            {
                                // reset length of file stream
                                writeStream.SetLength(0);

                                // let the thread go with itself, so that once file finishes writing, doesn't need to request thread context from main thread
                                await entry.OpenReader().CopyToAsync(writeStream).ConfigureAwait(false);
                            }
                        }
                    }

                    foreach (var entry in indexedOldFiles.Values)
                    {
                        string fullPath = Path.Combine(destinationFolder, entry.FileName.Substring(substringStartIndex));

                        if (entry.IsDirectory)
                        {
                            // in case the two zip file was created from different tool. some tool will include folder as seperate entry, some don`t.
                            // to be sure that foder is meant to be deleted, double check there is no files under it
                            var entryNameInLower = entry.FileName.ToLower();
                            if (!string.Equals(destinationFolder, fullPath, StringComparison.OrdinalIgnoreCase)
                                && newContentEntries.FirstOrDefault(e => e.FileName.ToLowerInvariant().StartsWith(entryNameInLower)) == null)
                            {
                                using (tracer.Step("Deleting directory: {0}", fullPath))
                                {
                                    FileSystemHelpers.DeleteDirectorySafe(fullPath);
                                }
                            }
                            continue;
                        }

                        using (tracer.Step("Deleting file: {0}", fullPath))
                        {
                            FileSystemHelpers.DeleteFileSafe(fullPath);
                        }
                    }
                }

                // update nupkg
                newPackageStream.Position = 0;
                using (tracer.Step("Updating nupkg file."))
                {
                    WriteStreamToFile(newPackageStream, pathToLocalCopyOfNupkg);
                    if (!identity.Version.Equals(localPackage.Identity.Version))
                    {
                        using (tracer.Step("New package has difference version {0} from old package {1}. Remove old nupkg file.", identity.Version, localPackage.Identity.Version))
                        {
                            // if version is difference, nupkg file name will be difference. will need to clean up the old one.
                            var oldNupkg = pathToLocalCopyOfNupkg.Replace(
                                string.Format(CultureInfo.InvariantCulture, "{0}.{1}.nupkg", identity.Id, identity.Version.ToNormalizedString()),
                                string.Format(CultureInfo.InvariantCulture, "{0}.{1}.nupkg", localPackage.Identity.Id, localPackage.Identity.Version.ToNormalizedString()));

                            FileSystemHelpers.DeleteFileSafe(oldNupkg);
                        }
                    }
                }
            }
        }
Esempio n. 8
0
 private void DeleteFunctionArtifacts(string name)
 {
     FileSystemHelpers.DeleteFileSafe(GetFunctionTestDataFilePath(name));
     FileSystemHelpers.DeleteFileSafe(GetFunctionSecretsFilePath(name));
     FileSystemHelpers.DeleteFileSafe(GetFunctionLogPath(name));
 }
Esempio n. 9
0
        public void Deploy(string id, string deployer, bool clean)
        {
            ITracer     tracer     = _traceFactory.GetTracer();
            IDisposable deployStep = null;

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

                // Check to see if we have a deployment with this id already
                string trackingFilePath = GetStatusFilePath(id, ensureDirectory: false);

                if (!_fileSystem.File.Exists(trackingFilePath))
                {
                    // If we don't then throw
                    throw new FileNotFoundException(String.Format(CultureInfo.CurrentCulture, Resources.Error_DeployNotFound, id));
                }

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

                ILogger logger = GetLogger(id);

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

                if (clean)
                {
                    tracer.Trace("Cleaning git repository");

                    logger.Log(Resources.Log_CleaningGitRepository);

                    _serverRepository.Clean();
                }

                if (!String.IsNullOrEmpty(deployer))
                {
                    // Update the deployer
                    DeploymentStatusFile statusFile = OpenStatusFile(id);
                    statusFile.Deployer = deployer;
                    statusFile.Save(_fileSystem);
                }

                // 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. 10
0
        public void Delete(int deleteWebRoot = 0, int ignoreErrors = 0)
        {
            try
            {
                // Fail if a deployment is in progress
                _deploymentLock.LockOperation(() =>
                {
                    using (_tracer.Step("Deleting repository"))
                    {
                        string repositoryPath = Path.Combine(_environment.SiteRootPath, Constants.RepositoryPath);
                        if (String.Equals(repositoryPath, _environment.RepositoryPath, StringComparison.OrdinalIgnoreCase))
                        {
                            // Delete the repository
                            FileSystemHelpers.DeleteDirectorySafe(_environment.RepositoryPath, ignoreErrors != 0);
                        }
                        else
                        {
                            // Just delete .git folder
                            FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.RepositoryPath, ".git"), ignoreErrors != 0);

                            FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.RepositoryPath, ".hg"), ignoreErrors != 0);
                        }
                    }

                    using (_tracer.Step("Delete auto swap lock file"))
                    {
                        FileSystemHelpers.DeleteFileSafe(Path.Combine(_environment.LocksPath, PostDeploymentHelper.AutoSwapLockFile));
                    }

                    using (_tracer.Step("Deleting ssh key"))
                    {
                        // Delete the ssh key
                        FileSystemHelpers.DeleteDirectorySafe(_environment.SSHKeyPath, ignoreErrors != 0);
                    }

                    if (deleteWebRoot != 0)
                    {
                        // This logic is primarily used to help with site reuse during test.
                        // The flag is not documented for general use.

                        using (_tracer.Step("Deleting web root"))
                        {
                            // Delete the wwwroot folder
                            FileSystemHelpers.DeleteDirectoryContentsSafe(_environment.WebRootPath, ignoreErrors != 0);
                        }

                        using (_tracer.Step("Deleting diagnostics"))
                        {
                            // Delete the diagnostic log. This is a slight abuse of deleteWebRoot, but the
                            // real semantic is more to reset the site to a fully clean state
                            FileSystemHelpers.DeleteDirectorySafe(_environment.DiagnosticsPath, ignoreErrors != 0);
                        }

                        using (_tracer.Step("Deleting ASP.NET 5 approot"))
                        {
                            // Delete the approot folder used by ASP.NET 5 apps
                            FileSystemHelpers.DeleteDirectorySafe(Path.Combine(_environment.SiteRootPath, "approot"), ignoreErrors != 0);
                        }

                        // Delete first deployment manifest since it is no longer needed
                        FileSystemHelpers.DeleteFileSafe(Path.Combine(_environment.SiteRootPath, Constants.FirstDeploymentManifestFileName));
                    }
                    else
                    {
                        using (_tracer.Step("Updating initial deployment manifest"))
                        {
                            // The active deployment manifest becomes the baseline initial deployment manifest
                            // When SCM is reconnected, the new deployment will use this manifest to clean the wwwroot
                            SaveInitialDeploymentManifest();
                        }
                    }

                    using (_tracer.Step("Deleting deployment cache"))
                    {
                        // Delete the deployment cache
                        FileSystemHelpers.DeleteDirectorySafe(_environment.DeploymentsPath, ignoreErrors != 0);
                    }
                }, "Deleting repository", TimeSpan.Zero);
            }
            catch (LockOperationException ex)
            {
                HttpResponseMessage response = Request.CreateErrorResponse(HttpStatusCode.Conflict, ex.Message);
                throw new HttpResponseException(response);
            }
        }
Esempio n. 11
0
        internal async Task <ChangeSet> Sync(DropboxInfo dropboxInfo, string branch, IRepository repository, ITracer tracer)
        {
            DropboxDeployInfo deployInfo = dropboxInfo.DeployInfo;

            // use incoming tracer since it is background work
            _tracer = tracer;

            ResetStats();

            // for Dropbox OAuth V2, the delta is collected and applied by SCM
            // simply set OldCursoras current.
            if (dropboxInfo.OAuthVersion == 2)
            {
                deployInfo.OldCursor = _settings.GetValue(CursorKey);
            }
            else if (_settings.GetValue(CursorKey) != deployInfo.OldCursor)
            {
                throw new InvalidOperationException(Resources.Error_MismatchDropboxCursor);
            }

            // initial sync, remove default content
            // for simplicity, we do it blindly whether or not in-place
            // given the end result is the same
            if (String.IsNullOrEmpty(deployInfo.OldCursor) && DeploymentHelper.IsDefaultWebRootContent(_environment.WebRootPath))
            {
                string hoststarthtml = Path.Combine(_environment.WebRootPath, Constants.HostingStartHtml);
                FileSystemHelpers.DeleteFileSafe(hoststarthtml);
            }

            if (!repository.IsEmpty())
            {
                // git checkout --force <branch>
                repository.Update(branch);
            }

            ChangeSet changeSet = null;
            string    message   = null;

            try
            {
                using (_tracer.Step("Sync with Dropbox"))
                {
                    if (dropboxInfo.OAuthVersion == 2)
                    {
                        // Fetch the deltas
                        await UpdateDropboxDeployInfo(deployInfo);
                    }

                    // Sync dropbox => repository directory
                    await ApplyChanges(dropboxInfo, useOAuth20 : dropboxInfo.OAuthVersion == 2);
                }

                message = String.Format(CultureInfo.CurrentCulture,
                                        Resources.Dropbox_Synchronized,
                                        deployInfo.Deltas.Count);
            }
            catch (Exception)
            {
                message = String.Format(CultureInfo.CurrentCulture,
                                        Resources.Dropbox_SynchronizedWithFailure,
                                        _successCount,
                                        deployInfo.Deltas.Count,
                                        _failedCount);

                throw;
            }
            finally
            {
                Logger.Log(message);

                Logger.Log(String.Format("{0} downloaded files, {1} successful retries.", _fileCount, _retriedCount));

                IDeploymentStatusFile statusFile = _status.Open(dropboxInfo.TargetChangeset.Id);
                statusFile.UpdateMessage(message);
                statusFile.UpdateProgress(String.Format(CultureInfo.CurrentCulture, Resources.Dropbox_Committing, _successCount));

                // Commit anyway even partial change
                if (repository.Commit(message, deployInfo.UserName, deployInfo.Email ?? deployInfo.UserName))
                {
                    changeSet = repository.GetChangeSet("HEAD");
                }
            }

            // Save new dropboc cursor
            LogInfo("Update dropbox cursor");
            _settings.SetValue(CursorKey, deployInfo.NewCursor);

            return(changeSet);
        }
        public async Task Deploy(IRepository repository, ChangeSet changeSet, string deployer, bool clean, bool needFileUpdate)
        {
            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);
            }

            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);

                repository.ClearLock();

                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 the specific changeset
                            repository.Update(id);
                        }
                    }
                }

                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(id, tracer, deployStep, repository);
            }
            catch (Exception ex)
            {
                if (innerLogger != null)
                {
                    innerLogger.Log(ex);
                }

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

                tracer.TraceError(ex);

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

                throw;
            }
        }
        private async Task <IActionResult> PushDeployAsync(ArtifactDeploymentInfo deploymentInfo, bool isAsync,
                                                           HttpContext context)
        {
            string artifactTempPath;

            if (string.IsNullOrWhiteSpace(deploymentInfo.TargetFileName))
            {
                artifactTempPath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip");
            }
            else
            {
                artifactTempPath = Path.Combine(_environment.ZipTempPath, deploymentInfo.TargetFileName);
            }

            if (_settings.RunFromLocalZip())
            {
                await WriteSitePackageZip(deploymentInfo, _tracer);
            }
            else
            {
                var oryxManifestFile = Path.Combine(_environment.WebRootPath, "oryx-manifest.toml");
                if (FileSystemHelpers.FileExists(oryxManifestFile))
                {
                    _tracer.Step("Removing previous build artifact's manifest file");
                    FileSystemHelpers.DeleteFileSafe(oryxManifestFile);
                }

                try
                {
                    var nodeModulesSymlinkFile       = Path.Combine(_environment.WebRootPath, "node_modules");
                    Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo(nodeModulesSymlinkFile);
                    if (i.FileType == Mono.Unix.FileTypes.SymbolicLink)
                    {
                        _tracer.Step("Removing node_modules symlink");
                        // TODO: Add support to remove Unix Symlink File in DeleteFileSafe
                        // FileSystemHelpers.DeleteFileSafe(nodeModulesSymlinkFile);
                        FileSystemHelpers.RemoveUnixSymlink(nodeModulesSymlinkFile, TimeSpan.FromSeconds(5));
                    }
                }
                catch (Exception)
                {
                    // best effort
                }

                using (_tracer.Step("Writing artifact to {0}", artifactTempPath))
                {
                    if (!string.IsNullOrEmpty(context.Request.ContentType) &&
                        context.Request.ContentType.Contains("multipart/form-data", StringComparison.OrdinalIgnoreCase))
                    {
                        FormValueProvider formModel;
                        using (_tracer.Step("Writing zip file to {0}", artifactTempPath))
                        {
                            using (var file = System.IO.File.Create(artifactTempPath))
                            {
                                formModel = await Request.StreamFile(file);
                            }
                        }
                    }
                    else if (deploymentInfo.RemoteURL != null)
                    {
                        using (_tracer.Step("Writing zip file from packageUri to {0}", artifactTempPath))
                        {
                            using (var httpClient = new HttpClient())
                                using (var fileStream = new FileStream(artifactTempPath,
                                                                       FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
                                {
                                    var zipUrlRequest  = new HttpRequestMessage(HttpMethod.Get, deploymentInfo.RemoteURL);
                                    var zipUrlResponse = await httpClient.SendAsync(zipUrlRequest);

                                    try
                                    {
                                        zipUrlResponse.EnsureSuccessStatusCode();
                                    }
                                    catch (HttpRequestException hre)
                                    {
                                        _tracer.TraceError(hre, "Failed to get file from packageUri {0}", deploymentInfo.RemoteURL);
                                        throw;
                                    }

                                    using (var content = await zipUrlResponse.Content.ReadAsStreamAsync())
                                    {
                                        await content.CopyToAsync(fileStream);
                                    }
                                }
                        }
                    }
                    else
                    {
                        using (var file = System.IO.File.Create(artifactTempPath))
                        {
                            await Request.Body.CopyToAsync(file);
                        }
                    }

                    deploymentInfo.RepositoryUrl = artifactTempPath;
                }
            }

            var result =
                await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    Response.GetTypedHeaders().Location =
                        new Uri(UriHelper.GetRequestUri(Request),
                                String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment,
                                              deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }

                return(Accepted());

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                _tracer.Trace("Scm is not enabled, reject all requests.");
                return(Forbid());

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing));

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                return(Accepted());

            case FetchDeploymentRequestResult.RanSynchronously:
                return(Ok());

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_DeploymentInProgress));

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_RunFromRemoteZipConfigured));

            default:
                return(BadRequest());
            }
        }