예제 #1
0
        public async Task Fetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
        {
            var oneDriveInfo = (OneDriveInfo)deploymentInfo;

            _oneDriveHelper.Logger       = logger;
            oneDriveInfo.TargetChangeset = await _oneDriveHelper.Sync(oneDriveInfo, repository, tracer);
        }
예제 #2
0
        public virtual async Task Fetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
        {
            // (A)sync with dropbox
            var dropboxInfo = (DropboxInfo)deploymentInfo;

            _dropBoxHelper.Logger          = logger;
            deploymentInfo.TargetChangeset = await _dropBoxHelper.Sync(dropboxInfo, targetBranch, repository, tracer);
        }
        public void TryParseDeploymentInfoShouldReturnUnknownPayload()
        {
            var                oneDriveHandler = new OneDriveHandler(Mock.Of <ITracer>(), Mock.Of <IDeploymentStatusManager>(), Mock.Of <IDeploymentSettingsManager>(), Mock.Of <IEnvironment>(), Mock.Of <IRepositoryFactory>());
            JObject            payload         = JObject.FromObject(new { });
            DeploymentInfoBase deploymentInfo  = null;

            DeployAction result = oneDriveHandler.TryParseDeploymentInfo(null, payload, null, out deploymentInfo);

            Assert.Equal(DeployAction.UnknownPayload, result);
        }
예제 #4
0
 public static void SetTargetSubDirectoyAndFileNameFromPath(DeploymentInfoBase deploymentInfo, string relativeFilePath)
 {
     // Extract directory path and file name from relativeFilePath
     // Example: path=a/b/c.jar => TargetDirectoryName=a/b and TargetFileName=c.jar
     // Example: path=c.jar => TargetDirectoryName=null and TargetFileName=c.jar
     // Example: path=/c.jar => TargetDirectoryName="" and TargetFileName=c.jar
     // Example: path=null => TargetDirectoryName=null and TargetFileName=null
     deploymentInfo.TargetFileName = Path.GetFileName(relativeFilePath);
     deploymentInfo.TargetSubDirectoryRelativePath = Path.GetDirectoryName(relativeFilePath);
 }
예제 #5
0
        // Extract directory path and file name from relativeFilePath
        // Example: path=a/b/c.jar => TargetSubDirectoryRelativePath=a/b and TargetFileName=c.jar
        // Example: path=c.jar => TargetSubDirectoryRelativePath=null and TargetFileName=c.jar
        // Example: path=/c.jar => TargetSubDirectoryRelativePath="" and TargetFileName=c.jar
        // Example: path=null => TargetSubDirectoryRelativePath=null and TargetFileName=null
        public static void SetTargetSubDirectoyAndFileNameFromRelativePath(DeploymentInfoBase deploymentInfo, string relativeFilePath)
        {
            if (relativeFilePath != null)
            {
                relativeFilePath = relativeFilePath.TrimStart('/');
            }

            deploymentInfo.TargetFileName = Path.GetFileName(relativeFilePath);
            deploymentInfo.TargetSubDirectoryRelativePath = Path.GetDirectoryName(relativeFilePath);
        }
        public void TryParseDeploymentInfoShouldReturnProcessDeployment()
        {
            var                oneDriveHandler = new OneDriveHandler(Mock.Of <ITracer>(), Mock.Of <IDeploymentStatusManager>(), Mock.Of <IDeploymentSettingsManager>(), Mock.Of <IEnvironment>(), Mock.Of <IRepositoryFactory>());
            JObject            payload         = JObject.FromObject(new { RepositoryUrl = "https://api.onedrive.com", AccessToken = "one-drive-access-token" });
            DeploymentInfoBase deploymentInfo  = null;

            DeployAction result = oneDriveHandler.TryParseDeploymentInfo(null, payload, null, out deploymentInfo);

            Assert.Equal(DeployAction.ProcessDeployment, result);
        }
예제 #7
0
        // OneDeploy Fetch handler for non-zip artifacts.
        // For zip files, OneDeploy uses the LocalZipHandler Fetch handler
        // NOTE: Do not access the request stream as it may have been closed during asynchronous scenarios
        private async Task OneDeployFetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
        {
            var artifactDeploymentInfo = (ArtifactDeploymentInfo)deploymentInfo;

            // This is the path where the artifact being deployed is staged, before it is copied to the final target location
            var artifactDirectoryStagingPath = repository.RepositoryPath;

            var targetInfo = FileSystemHelpers.DirectoryInfoFromDirectoryName(artifactDirectoryStagingPath);

            if (targetInfo.Exists)
            {
                // If tempDirPath already exists, rename it so we can delete it later
                var moveTarget = Path.Combine(targetInfo.Parent.FullName, Path.GetRandomFileName());
                using (tracer.Step(string.Format("Renaming ({0}) to ({1})", targetInfo.FullName, moveTarget)))
                {
                    targetInfo.MoveTo(moveTarget);
                }
            }

            // Create artifact staging directory before later use
            Directory.CreateDirectory(artifactDirectoryStagingPath);
            var artifactFileStagingPath = Path.Combine(artifactDirectoryStagingPath, deploymentInfo.TargetFileName);

            // If RemoteUrl is non-null, it means the content needs to be downloaded from the Url source to the staging location
            // Else, it had been downloaded already so we just move the downloaded file to the staging location
            if (!string.IsNullOrWhiteSpace(artifactDeploymentInfo.RemoteURL))
            {
                using (tracer.Step("Saving request content to {0}", artifactFileStagingPath))
                {
                    var content = await DeploymentHelper.GetArtifactContentFromURL(artifactDeploymentInfo, tracer);

                    var copyTask = content.CopyToAsync(artifactFileStagingPath, tracer);

                    // Deletes all files and directories except for artifactFileStagingPath and artifactDirectoryStagingPath
                    var cleanTask = Task.Run(() => DeleteFilesAndDirsExcept(artifactFileStagingPath, artifactDirectoryStagingPath, tracer));

                    // Lets the copy and cleanup tasks to run in parallel and wait for them to finish
                    await Task.WhenAll(copyTask, cleanTask);
                }
            }
            else
            {
                var srcInfo = FileSystemHelpers.DirectoryInfoFromDirectoryName(deploymentInfo.RepositoryUrl);
                using (tracer.Step(string.Format("Moving {0} to {1}", targetInfo.FullName, artifactFileStagingPath)))
                {
                    srcInfo.MoveTo(artifactFileStagingPath);
                }

                // Deletes all files and directories except for artifactFileStagingPath and artifactDirectoryStagingPath
                DeleteFilesAndDirsExcept(artifactFileStagingPath, artifactDirectoryStagingPath, tracer);
            }

            // The deployment flow expects at least 1 commit in the IRepository commit, refer to CommitRepo() for more info
            CommitRepo(repository, artifactDeploymentInfo);
        }
예제 #8
0
        private async Task LocalZipFetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
        {
            var zipDeploymentInfo = (ZipDeploymentInfo)deploymentInfo;

            // If this was a request with a Zip URL in the JSON, we need to deploy the zip locally and get the path
            // Otherwise, for this kind of deployment, RepositoryUrl is a local path.
            var sourceZipFile = !string.IsNullOrEmpty(zipDeploymentInfo.ZipURL)
                ? await DeployZipLocally(zipDeploymentInfo, tracer)
                : zipDeploymentInfo.RepositoryUrl;

            var extractTargetDirectory = repository.RepositoryPath;

            var info     = FileSystemHelpers.FileInfoFromFileName(sourceZipFile);
            var sizeInMb = (info.Length / (1024f * 1024f)).ToString("0.00", CultureInfo.InvariantCulture);

            var message = String.Format(
                CultureInfo.InvariantCulture,
                "Cleaning up temp folders from previous zip deployments and extracting pushed zip file {0} ({1} MB) to {2}",
                info.FullName,
                sizeInMb,
                extractTargetDirectory);

            logger.Log(message);

            using (tracer.Step(message))
            {
                // If extractTargetDirectory already exists, rename it so we can delete it concurrently with
                // the unzip (along with any other junk in the folder)
                var targetInfo = FileSystemHelpers.DirectoryInfoFromDirectoryName(extractTargetDirectory);
                if (targetInfo.Exists)
                {
                    var moveTarget = Path.Combine(targetInfo.Parent.FullName, Path.GetRandomFileName());
                    using (tracer.Step(string.Format("Renaming extractTargetDirectory({0}) to tempDirectory({1})", targetInfo.FullName, moveTarget)))
                    {
                        targetInfo.MoveTo(moveTarget);
                    }
                }

                var cleanTask   = Task.Run(() => DeleteFilesAndDirsExcept(sourceZipFile, extractTargetDirectory, tracer));
                var extractTask = Task.Run(() =>
                {
                    FileSystemHelpers.CreateDirectory(extractTargetDirectory);

                    using (var file = info.OpenRead())
                        using (var zip = new ZipArchive(file, ZipArchiveMode.Read))
                        {
                            zip.Extract(extractTargetDirectory, tracer, _settings.GetZipDeployDoNotPreserveFileTime());
                        }
                });

                await Task.WhenAll(cleanTask, extractTask);
            }

            CommitRepo(repository, zipDeploymentInfo);
        }
예제 #9
0
 private async Task LocalZipHandler(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
 {
     if (_settings.RunFromLocalZip() && deploymentInfo is ZipDeploymentInfo)
     {
         // If this is a Run-From-Zip deployment, then we need to extract function.json
         // from the zip file into path zipDeploymentInfo.SyncFunctionsTrigersPath
         ExtractTriggers(repository, deploymentInfo as ZipDeploymentInfo);
     }
     else
     {
         await LocalZipFetch(repository, deploymentInfo, targetBranch, logger, tracer);
     }
 }
예제 #10
0
        private Task LocalZipFetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch,
                                   ILogger logger, ITracer tracer)
        {
            var zipDeploymentInfo = (ZipDeploymentInfo)deploymentInfo;

            // For this kind of deployment, RepositoryUrl is a local path.
            var sourceZipFile          = zipDeploymentInfo.RepositoryUrl;
            var extractTargetDirectory = repository.RepositoryPath;

            var info     = FileSystemHelpers.FileInfoFromFileName(sourceZipFile);
            var sizeInMb = (info.Length / (1024f * 1024f)).ToString("0.00", CultureInfo.InvariantCulture);

            var message = String.Format(
                CultureInfo.InvariantCulture,
                "Cleaning up temp folders from previous zip deployments and extracting pushed zip file {0} ({1} MB) to {2}",
                info.FullName,
                sizeInMb,
                extractTargetDirectory);

            logger.Log(message);

            using (tracer.Step(message))
            {
                // If extractTargetDirectory already exists, rename it so we can delete it concurrently with
                // the unzip (along with any other junk in the folder)
                var targetInfo = FileSystemHelpers.DirectoryInfoFromDirectoryName(extractTargetDirectory);
                if (targetInfo.Exists)
                {
                    var moveTarget = Path.Combine(targetInfo.Parent.FullName, Path.GetRandomFileName());
                    targetInfo.MoveTo(moveTarget);
                }

                DeleteFilesAndDirsExcept(sourceZipFile, extractTargetDirectory, tracer);

                FileSystemHelpers.CreateDirectory(extractTargetDirectory);

                using (var file = info.OpenRead())

                    using (var zip = new ZipArchive(file, ZipArchiveMode.Read))
                    {
                        deploymentInfo.repositorySymlinks = zip.Extract(extractTargetDirectory, preserveSymlinks: ShouldPreserveSymlinks());

                        CreateZipSymlinks(deploymentInfo.repositorySymlinks, extractTargetDirectory);

                        PermissionHelper.ChmodRecursive("777", extractTargetDirectory, tracer, TimeSpan.FromMinutes(1));
                    }
            }

            CommitRepo(repository, zipDeploymentInfo);
            return(Task.CompletedTask);
        }
예제 #11
0
        private async Task LocalZipFetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
        {
            var zipDeploymentInfo = (ZipDeploymentInfo)deploymentInfo;

            // For this kind of deployment, RepositoryUrl is a local path.
            var sourceZipFile          = zipDeploymentInfo.RepositoryUrl;
            var extractTargetDirectory = repository.RepositoryPath;

            var info     = FileSystemHelpers.FileInfoFromFileName(sourceZipFile);
            var sizeInMb = (info.Length / (1024f * 1024f)).ToString("0.00", CultureInfo.InvariantCulture);

            var message = String.Format(
                CultureInfo.InvariantCulture,
                "Cleaning up temp folders from previous zip deployments and extracting pushed zip file {0} ({1} MB) to {2}",
                info.FullName,
                sizeInMb,
                extractTargetDirectory);

            logger.Log(message);

            using (tracer.Step(message))
            {
                // If extractTargetDirectory already exists, rename it so we can delete it concurrently with
                // the unzip (along with any other junk in the folder)
                var targetInfo = FileSystemHelpers.DirectoryInfoFromDirectoryName(extractTargetDirectory);
                if (targetInfo.Exists)
                {
                    var moveTarget = Path.Combine(targetInfo.Parent.FullName, Path.GetRandomFileName());
                    targetInfo.MoveTo(moveTarget);
                }

                var cleanTask   = Task.Run(() => DeleteFilesAndDirsExcept(sourceZipFile, extractTargetDirectory, tracer));
                var extractTask = Task.Run(() =>
                {
                    FileSystemHelpers.CreateDirectory(extractTargetDirectory);

                    using (var file = info.OpenRead())
                        using (var zip = new ZipArchive(file, ZipArchiveMode.Read))
                        {
                            zip.Extract(extractTargetDirectory);
                        }
                });

                await Task.WhenAll(cleanTask, extractTask);
            }

            // Needed in order for repository.GetChangeSet() to work.
            // Similar to what OneDriveHelper and DropBoxHelper do.
            repository.Commit(zipDeploymentInfo.Message, zipDeploymentInfo.Author, zipDeploymentInfo.AuthorEmail);
        }
예제 #12
0
        private void SetTargetFromPath(DeploymentInfoBase deploymentInfo, string path)
        {
            // Extract directory path and file name from 'path'
            // Example: path=a/b/c.jar => TargetDirectoryName=a/b and TargetFileName=c.jar
            deploymentInfo.TargetFileName = Path.GetFileName(path);

            var relativeDirectoryPath = Path.GetDirectoryName(path);

            // Translate /foo/bar to foo/bar
            // Translate \foo\bar to foo\bar
            // That way, we can combine it with %HOME% to get the absolute path
            relativeDirectoryPath = relativeDirectoryPath.TrimStart('/', '\\');
            var absoluteDirectoryPath = Path.Combine(_environment.RootPath, relativeDirectoryPath);

            deploymentInfo.TargetDirectoryPath = absoluteDirectoryPath;
        }
예제 #13
0
        public static void SetRepositoryUrl(DeploymentInfoBase deploymentInfo, string url)
        {
            string commitId = null;
            int    index    = url.LastIndexOf('#');

            if (index >= 0)
            {
                if (index + 1 < url.Length)
                {
                    commitId = url.Substring(index + 1);
                }
                url = url.Substring(0, index);
            }

            deploymentInfo.RepositoryUrl = url;
            deploymentInfo.CommitId      = commitId;
        }
예제 #14
0
 private async Task LocalZipHandler(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
 {
     if (_settings.RunFromLocalZip() && deploymentInfo is ZipDeploymentInfo)
     {
         ZipDeploymentInfo zipDeploymentInfo = (ZipDeploymentInfo)deploymentInfo;
         // If this was a request with a Zip URL in the JSON, we first need to get the zip content and write it to the site.
         if (!string.IsNullOrEmpty(zipDeploymentInfo.ZipURL))
         {
             await WriteSitePackageZip(zipDeploymentInfo, tracer, await DeploymentHelper.GetZipContentFromURL(zipDeploymentInfo, tracer));
         }
         // If this is a Run-From-Zip deployment, then we need to extract function.json
         // from the zip file into path zipDeploymentInfo.SyncFunctionsTrigersPath
         ExtractTriggers(repository, zipDeploymentInfo);
     }
     else
     {
         await LocalZipFetch(repository, deploymentInfo, targetBranch, logger, tracer);
     }
 }
        private DeployAction GetRepositoryInfo(
            HttpRequest request,
            JObject payload,
            string targetBranch,
            IEnumerable <IServiceHookHandler> serviceHookHandlers,
            ITracer tracer,
            out DeploymentInfoBase info)
        {
            foreach (var handler in serviceHookHandlers)
            {
                DeployAction result = handler.TryParseDeploymentInfo(request, payload, targetBranch, out info);
                if (result == DeployAction.UnknownPayload)
                {
                    continue;
                }
                if (tracer.TraceLevel >= TraceLevel.Verbose)
                {
                    var attribs = new Dictionary <string, string>
                    {
                        { "type", handler.GetType().FullName }
                    };
                    tracer.Trace("handler", attribs);
                }

                if (result == DeployAction.ProcessDeployment)
                {
                    // Although a payload may be intended for a handler, it might not need to fetch.
                    // For instance, if a different branch was pushed than the one the repository is deploying,
                    // we can no-op it.
                    Debug.Assert(info != null);
                    info.Fetch = handler.Fetch;
                }

                return(result);
            }

            throw new FormatException(Resources.Error_UnsupportedFormat);
        }
 public static Task FakeFetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
 {
     return(Task.FromResult(0));
 }
 public Task DeployAsync(IRepository repository, ChangeSet changeSet, string deployer, bool clean, DeploymentInfoBase deploymentInfo = null, bool needFileUpdate = true, bool fullBuildByDefault = true)
 {
     ++DeployCount;
     return(Task.FromResult(1));
 }
예제 #18
0
        private DeployAction GetRepositoryInfo(HttpRequestBase request, JObject payload, string targetBranch, out DeploymentInfoBase info)
        {
            foreach (var handler in _serviceHookHandlers)
            {
                DeployAction result = handler.TryParseDeploymentInfo(request, payload, targetBranch, out info);
                if (result != DeployAction.UnknownPayload)
                {
                    if (_tracer.TraceLevel >= TraceLevel.Verbose)
                    {
                        TraceHandler(handler);
                    }

                    if (result == DeployAction.ProcessDeployment)
                    {
                        // Although a payload may be intended for a handler, it might not need to fetch.
                        // For instance, if a different branch was pushed than the one the repository is deploying, we can no-op it.
                        Debug.Assert(info != null);
                        info.Fetch = handler.Fetch;
                    }

                    return(result);
                }
            }

            throw new FormatException(Resources.Error_UnsupportedFormat);
        }
예제 #19
0
        public override DeployAction TryParseDeploymentInfo(HttpRequestBase request, JObject payload, string targetBranch, out DeploymentInfoBase deploymentInfo)
        {
            deploymentInfo = null;
            if (request.UserAgent != null &&
                request.UserAgent.StartsWith("Bitbucket-Webhooks/2.0", StringComparison.OrdinalIgnoreCase))
            {
                deploymentInfo = GetDeploymentInfo(payload, targetBranch);
                return(deploymentInfo == null ? DeployAction.NoOp : DeployAction.ProcessDeployment);
            }

            return(DeployAction.UnknownPayload);
        }
예제 #20
0
        public override async Task ProcessRequestAsync(HttpContext context)
        {
            using (_tracer.Step("FetchHandler"))
            {
                // Redirect GET /deploy requests to the Kudu root for convenience when using URL from Azure portal
                if (String.Equals(context.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.Redirect("~/");
                    context.ApplicationInstance.CompleteRequest();
                    return;
                }

                if (!String.Equals(context.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    context.ApplicationInstance.CompleteRequest();
                    return;
                }

                context.Response.TrySkipIisCustomErrors = true;

                DeploymentInfoBase deployInfo = null;

                // We are going to assume that the branch details are already set by the time it gets here. This is particularly important in the mercurial case,
                // since Settings hardcodes the default value for Branch to be "master". Consequently, Kudu will NoOp requests for Mercurial commits.
                string targetBranch = _settings.GetBranch();
                try
                {
                    var          request = new HttpRequestWrapper(context.Request);
                    JObject      payload = GetPayload(request);
                    DeployAction action  = GetRepositoryInfo(request, payload, targetBranch, out deployInfo);
                    if (action == DeployAction.NoOp)
                    {
                        _tracer.Trace("No-op for deployment.");
                        return;
                    }
                }
                catch (FormatException ex)
                {
                    _tracer.TraceError(ex);
                    context.Response.StatusCode = 400;
                    context.Response.Write(ex.Message);
                    context.ApplicationInstance.CompleteRequest();
                    return;
                }

                bool asyncRequested = String.Equals(context.Request.QueryString["isAsync"], "true", StringComparison.OrdinalIgnoreCase);

                var response = await _manager.FetchDeploy(deployInfo, asyncRequested, UriHelper.GetRequestUri(context.Request), targetBranch);

                switch (response)
                {
                case FetchDeploymentRequestResult.RunningAynschronously:
                    // to avoid regression, only set location header if isAsync
                    if (asyncRequested)
                    {
                        // latest deployment keyword reserved to poll till deployment done
                        context.Response.Headers["Location"] = new Uri(UriHelper.GetRequestUri(context.Request),
                                                                       String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deployInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ"))).ToString();
                    }
                    context.Response.StatusCode = (int)HttpStatusCode.Accepted;
                    context.ApplicationInstance.CompleteRequest();
                    return;

                case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                    context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                    context.ApplicationInstance.CompleteRequest();
                    _tracer.Trace("Scm is not enabled, reject all requests.");
                    return;

                case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                    context.Response.StatusCode = (int)HttpStatusCode.Conflict;
                    context.Response.Write(Resources.Error_AutoSwapDeploymentOngoing);
                    context.ApplicationInstance.CompleteRequest();
                    return;

                case FetchDeploymentRequestResult.Pending:
                    // Return a http 202: the request has been accepted for processing, but the processing has not been completed.
                    context.Response.StatusCode = (int)HttpStatusCode.Accepted;
                    context.ApplicationInstance.CompleteRequest();
                    return;

                case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                    context.Response.StatusCode = (int)HttpStatusCode.Conflict;
                    context.Response.Write(Resources.Error_DeploymentInProgress);
                    context.ApplicationInstance.CompleteRequest();
                    break;

                case FetchDeploymentRequestResult.RanSynchronously:
                default:
                    break;
                }
            }
        }
예제 #21
0
        public DeployAction TryParseDeploymentInfo(HttpRequest request, JObject payload, string targetBranch, out DeploymentInfoBase deploymentInfo)
        {
            DropboxInfo dropboxInfo = null;
            string      message     = null;

            if (!String.IsNullOrEmpty(payload.Value <string>("NewCursor")))
            {
                dropboxInfo = DropboxInfo.CreateV1Info(payload, GetRepositoryType(), _repositoryFactory);
                message     = String.Format(CultureInfo.CurrentUICulture, Resources.Dropbox_SynchronizingNChanges, dropboxInfo.DeployInfo.Deltas.Count);
            }
            else if (String.Equals(payload.Value <string>(DropboxVersionKey), "2", StringComparison.OrdinalIgnoreCase))
            {
                string oauthToken = GetValue(payload, DropboxTokenKey),
                       path       = GetValue(payload, DropboxPathKey),
                       userName   = payload.Value <string>("dropbox_username") ?? "Dropbox",
                       email      = payload.Value <string>("dropbox_email");

                dropboxInfo = DropboxInfo.CreateV2Info(path, oauthToken, GetRepositoryType(), _repositoryFactory);
                dropboxInfo.DeployInfo.UserName = userName;
                dropboxInfo.DeployInfo.Email    = email;
                message = String.Format(CultureInfo.CurrentUICulture, Resources.Dropbox_Synchronizing);
            }

            if (dropboxInfo != null)
            {
                deploymentInfo = dropboxInfo;

                // Temporary deployment
                deploymentInfo.TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(
                    authorName: dropboxInfo.DeployInfo.UserName,
                    authorEmail: dropboxInfo.DeployInfo.Email,
                    message: message
                    );

                deploymentInfo.AllowDeploymentWhileScmDisabled = true;

                return(DeployAction.ProcessDeployment);
            }

            deploymentInfo = null;
            return(DeployAction.UnknownPayload);
        }
예제 #22
0
        public DeployAction TryParseDeploymentInfo(HttpRequest request, JObject payload, string targetBranch, out DeploymentInfoBase deploymentInfo)
        {
            deploymentInfo = null;
            string url = payload.Value <string>("RepositoryUrl");

            if (string.IsNullOrWhiteSpace(url) || !url.ToLowerInvariant().Contains("api.onedrive.com"))
            {
                return(DeployAction.UnknownPayload);
            }

            /*
             *   Expecting payload to be:
             *   {
             *      "RepositoryUrl": "xxx",
             *      "AccessToken": "xxx"
             *   }
             */
            string accessToken = payload.Value <string>("AccessToken");

            // keep email and name, so that can be re-used in later commit
            OneDriveInfo oneDriveInfo = new OneDriveInfo(_repositoryFactory)
            {
                Deployer      = "OneDrive",
                RepositoryUrl = url,
                AccessToken   = accessToken,
                AuthorName    = _settings.GetValue("authorName"),
                AuthorEmail   = _settings.GetValue("authorEmail")
            };

            deploymentInfo = oneDriveInfo;

            deploymentInfo.TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(
                authorName: oneDriveInfo.AuthorName,
                authorEmail: oneDriveInfo.AuthorEmail,
                message: String.Format(CultureInfo.CurrentUICulture, Resources.OneDrive_Synchronizing)
                );

            return(DeployAction.ProcessDeployment);
        }
예제 #23
0
        public override DeployAction TryParseDeploymentInfo(HttpRequest request, JObject payload, string targetBranch, out DeploymentInfoBase deploymentInfo)
        {
            deploymentInfo = null;

            if (request.Headers["User-Agent"].ToString().StartsWith("Bitbucket.org", StringComparison.OrdinalIgnoreCase))
            {
                deploymentInfo = GetDeploymentInfo(payload, targetBranch);
                return(deploymentInfo == null ? DeployAction.NoOp : DeployAction.ProcessDeployment);
            }

            return(DeployAction.UnknownPayload);
        }
예제 #24
0
        public override DeployAction TryParseDeploymentInfo(HttpRequestBase request, JObject payload, string targetBranch, out DeploymentInfoBase deploymentInfo)
        {
            deploymentInfo = null;

            var publisherId = payload.Value <string>("publisherId");

            if (String.Equals(publisherId, "tfs", StringComparison.OrdinalIgnoreCase))
            {
                deploymentInfo = GetDeploymentInfo(request, payload, targetBranch);
                return(DeployAction.ProcessDeployment);
            }

            return(DeployAction.UnknownPayload);
        }
        public async Task Invoke(
            HttpContext context,
            ITracer tracer,
            IDeploymentSettingsManager settings,
            IFetchDeploymentManager manager,
            IEnumerable <IServiceHookHandler> serviceHookHandlers)
        {
            using (tracer.Step("FetchHandler"))
            {
                // Redirect GET /deploy requests to the Kudu root for convenience when using URL from Azure portal
                if (string.Equals(context.Request.Method, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.Redirect("/");
                    return;
                }

                if (!string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.StatusCode = StatusCodes.Status404NotFound;
                    return;
                }

                // CORE TODO Need to set up UseDeveloperExceptionPage, UseExceptionHandler or the like in startup
                //context.Response.TrySkipIisCustomErrors = true;

                DeploymentInfoBase deployInfo = null;

                // We are going to assume that the branch details are already set by the time it gets here. This is particularly important in the mercurial case,
                // since Settings hardcodes the default value for Branch to be "master". Consequently, Kudu will NoOp requests for Mercurial commits.
                var targetBranch = settings.GetBranch();
                try
                {
                    JObject      payload = GetPayload(context.Request, tracer);
                    DeployAction action  = GetRepositoryInfo(context.Request, payload, targetBranch, serviceHookHandlers, tracer, out deployInfo);
                    if (action == DeployAction.NoOp)
                    {
                        tracer.Trace("No-op for deployment.");
                        return;
                    }
                }
                catch (FormatException ex)
                {
                    tracer.TraceError(ex);
                    context.Response.StatusCode = StatusCodes.Status400BadRequest;
                    await context.Response.WriteAsync(ex.Message);

                    return;
                }

                // CORE TODO make sure .Query has the same semantics as the old .QueryString (null, empty, etc.)
                bool asyncRequested = String.Equals(context.Request.Query["isAsync"], "true", StringComparison.OrdinalIgnoreCase);

                var response = await manager.FetchDeploy(deployInfo, asyncRequested, UriHelper.GetRequestUri(context.Request), targetBranch);

                switch (response)
                {
                case FetchDeploymentRequestResult.RunningAynschronously:
                    // to avoid regression, only set location header if isAsync
                    if (asyncRequested)
                    {
                        // latest deployment keyword reserved to poll till deployment done
                        context.Response.Headers["Location"] = new Uri(UriHelper.GetRequestUri(context.Request),
                                                                       String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deployInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ"))).ToString();
                    }
                    context.Response.StatusCode = StatusCodes.Status202Accepted;
                    return;

                case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                    context.Response.StatusCode = StatusCodes.Status403Forbidden;
                    tracer.Trace("Scm is not enabled, reject all requests.");
                    return;

                case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                    context.Response.StatusCode = StatusCodes.Status409Conflict;
                    await context.Response.WriteAsync(Resources.Error_AutoSwapDeploymentOngoing);

                    return;

                case FetchDeploymentRequestResult.Pending:
                    // Return a http 202: the request has been accepted for processing, but the processing has not been completed.
                    context.Response.StatusCode = StatusCodes.Status202Accepted;
                    return;

                case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                    context.Response.StatusCode = StatusCodes.Status409Conflict;
                    await context.Response.WriteAsync(Resources.Error_DeploymentInProgress);

                    return;

                case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                    context.Response.StatusCode = StatusCodes.Status409Conflict;
                    await context.Response.WriteAsync(Resources.Error_RunFromRemoteZipConfigured);

                    return;

                case FetchDeploymentRequestResult.RanSynchronously:
                default:
                    context.Response.StatusCode = StatusCodes.Status200OK;
                    break;
                }
            }
        }
예제 #26
0
        public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSettingsManager settings, IRepository repository, DeploymentInfoBase deploymentInfo)
        {
            string repositoryRoot = repository.RepositoryPath;

            // Use the cached vs projects file finder for: a. better performance, b. ignoring solutions/projects under node_modules
            var fileFinder = new CachedVsProjectsFileFinder(repository);

            // If there's a custom deployment file then let that take over.
            var command = settings.GetValue(SettingsKeys.Command);

            if (!String.IsNullOrEmpty(command))
            {
                return(new CustomBuilder(_environment, settings, _propertyProvider, repositoryRoot, command));
            }

            // If the user provided specific generator arguments, that overrides any detection logic
            string scriptGeneratorArgs = settings.GetValue(SettingsKeys.ScriptGeneratorArgs);

            if (!String.IsNullOrEmpty(scriptGeneratorArgs))
            {
                return(new CustomGeneratorCommandSiteBuilder(_environment, settings, _propertyProvider, repositoryRoot, scriptGeneratorArgs));
            }

            // If the repository has an explicit pointer to a project path to be deployed
            // then use it.
            string targetProjectPath = settings.GetValue(SettingsKeys.Project);

            if (!String.IsNullOrEmpty(targetProjectPath))
            {
                tracer.Trace("Specific project was specified: " + targetProjectPath);
                targetProjectPath = Path.GetFullPath(Path.Combine(repositoryRoot, targetProjectPath.TrimStart('/', '\\')));
            }

            if (deploymentInfo != null && deploymentInfo.Deployer == Constants.OneDeploy)
            {
                var projectPath = !String.IsNullOrEmpty(targetProjectPath) ? targetProjectPath : repositoryRoot;
                return(new OneDeployBuilder(_environment, settings, _propertyProvider, repositoryRoot, projectPath, deploymentInfo));
            }

            if (settings.RunFromLocalZip())
            {
                return(new RunFromZipSiteBuilder());
            }

            if (!settings.DoBuildDuringDeployment())
            {
                var projectPath = !String.IsNullOrEmpty(targetProjectPath) ? targetProjectPath : repositoryRoot;
                if (DeploymentHelper.IsDeploymentV2Request())
                {
                    return(new DeploymentV2Builder(_environment, settings, _propertyProvider, repositoryRoot));
                }
                else
                {
                    return(new BasicBuilder(_environment, settings, _propertyProvider, repositoryRoot, projectPath));
                }
            }

            // Check if we really need a builder for this
            // If not, return the NoOpBuilder
            string appFramework = System.Environment.GetEnvironmentVariable("FRAMEWORK");

            if (!string.IsNullOrEmpty(appFramework) && string.Equals(appFramework, "STATICSITE", StringComparison.OrdinalIgnoreCase))
            {
                var projectPath = !String.IsNullOrEmpty(targetProjectPath) ? targetProjectPath : repositoryRoot;
                return(new NoOpBuilder(_environment, settings, _propertyProvider, repositoryRoot, projectPath));
            }

            // If ENABLE_ORYX_BUILD is not set, for function app, we assume it on by default
            string enableOryxBuild = System.Environment.GetEnvironmentVariable("ENABLE_ORYX_BUILD");

            if (!string.IsNullOrEmpty(enableOryxBuild))
            {
                if (StringUtils.IsTrueLike(enableOryxBuild))
                {
                    return(new OryxBuilder(_environment, settings, _propertyProvider, repositoryRoot));
                }
            }
            else if (FunctionAppHelper.LooksLikeFunctionApp())
            {
                return(new OryxBuilder(_environment, settings, _propertyProvider, repositoryRoot));
            }

            string framework = System.Environment.GetEnvironmentVariable("FRAMEWORK");

            if (framework.Equals("ruby", StringComparison.OrdinalIgnoreCase))
            {
                return(new RubySiteBuilder(_environment, settings, _propertyProvider, repositoryRoot, targetProjectPath));
            }

            if (!String.IsNullOrEmpty(targetProjectPath))
            {
                // Try to resolve the project
                return(ResolveProject(repositoryRoot,
                                      targetProjectPath,
                                      settings,
                                      fileFinder,
                                      tryWebSiteProject: true,
                                      searchOption: SearchOption.TopDirectoryOnly));
            }

            // Get all solutions in the current repository path
            var solutions = VsHelper.GetSolutions(repositoryRoot, fileFinder).ToList();

            if (!solutions.Any())
            {
                return(ResolveProject(repositoryRoot,
                                      settings,
                                      fileFinder,
                                      searchOption: SearchOption.AllDirectories));
            }

            // More than one solution is ambiguous
            if (solutions.Count > 1)
            {
                // TODO: Show relative paths in error messages
                ThrowAmbiguousSolutionsError(solutions);
            }

            // We have a solution
            VsSolution solution = solutions[0];

            // We need to determine what project to deploy so get a list of all web projects and
            // figure out with some heuristic, which one to deploy.

            // TODO: Pick only 1 and throw if there's more than one
            // shunTODO need to implement this
            VsSolutionProject project = solution.Projects.Where(p => p.IsWap || p.IsWebSite || p.IsAspNetCore || p.IsFunctionApp).FirstOrDefault();

            if (project == null)
            {
                // Try executable type project
                project = solution.Projects.Where(p => p.IsExecutable).FirstOrDefault();
                if (project != null)
                {
                    return(new DotNetConsoleBuilder(_environment,
                                                    settings,
                                                    _propertyProvider,
                                                    repositoryRoot,
                                                    project.AbsolutePath,
                                                    solution.Path));
                }

                logger.Log(Resources.Log_NoDeployableProjects, solution.Path);

                // we have a solution file, but no deployable project
                // shunTODO how often do we run into this
                return(ResolveNonAspProject(repositoryRoot, null, settings));
            }

            if (project.IsWap)
            {
                return(new WapBuilder(_environment,
                                      settings,
                                      _propertyProvider,
                                      repositoryRoot,
                                      project.AbsolutePath,
                                      solution.Path));
            }

            if (project.IsAspNetCore)
            {
                return(new AspNetCoreBuilder(_environment,
                                             settings,
                                             _propertyProvider,
                                             repositoryRoot,
                                             project.AbsolutePath,
                                             solution.Path));
            }

            if (project.IsWebSite)
            {
                return(new WebSiteBuilder(_environment,
                                          settings,
                                          _propertyProvider,
                                          repositoryRoot,
                                          project.AbsolutePath,
                                          solution.Path));
            }

            return(new FunctionMsbuildBuilder(_environment,
                                              settings,
                                              _propertyProvider,
                                              repositoryRoot,
                                              project.AbsolutePath,
                                              solution.Path));
        }
 public abstract DeployAction TryParseDeploymentInfo(System.Web.HttpRequestBase request, Newtonsoft.Json.Linq.JObject payload, string targetBranch, out DeploymentInfoBase deploymentInfo);
예제 #28
0
        // {
        //   'format':'basic'
        //   'url':'http://host/repository',
        //   'is_hg':true // optional
        // }
        public override DeployAction TryParseDeploymentInfo(HttpRequest request, JObject payload, string targetBranch, out DeploymentInfoBase deploymentInfo)
        {
            deploymentInfo = null;
            if (!String.Equals(payload.Value <string>("format"), "basic", StringComparison.OrdinalIgnoreCase))
            {
                return(DeployAction.UnknownPayload);
            }

            string url = payload.Value <string>("url");

            if (String.IsNullOrEmpty(url))
            {
                return(DeployAction.UnknownPayload);
            }

            string scm = payload.Value <string>("scm");
            bool   is_hg;

            if (String.IsNullOrEmpty(scm))
            {
                // SSH hg@... vs git@...
                is_hg = url.StartsWith("hg@", StringComparison.OrdinalIgnoreCase);
            }
            else
            {
                is_hg = String.Equals(scm, "hg", StringComparison.OrdinalIgnoreCase);
            }

            deploymentInfo = new DeploymentInfo(RepositoryFactory);
            SetRepositoryUrl(deploymentInfo, url);
            deploymentInfo.RepositoryType  = is_hg ? RepositoryType.Mercurial : RepositoryType.Git;
            deploymentInfo.Deployer        = GetDeployerFromUrl(url);
            deploymentInfo.TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(message: "Fetch from " + url);
            deploymentInfo.AllowDeploymentWhileScmDisabled = true;

            return(DeployAction.ProcessDeployment);
        }
예제 #29
0
        public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSettingsManager settings, IRepository repository, DeploymentInfoBase deploymentInfo)
        {
            string repositoryRoot = repository.RepositoryPath;

            // Use the cached vs projects file finder for: a. better performance, b. ignoring solutions/projects under node_modules
            var fileFinder = new CachedVsProjectsFileFinder(repository);

            // If there's a custom deployment file then let that take over.
            var command = settings.GetValue(SettingsKeys.Command);

            if (!String.IsNullOrEmpty(command))
            {
                return(new CustomBuilder(_environment, settings, _propertyProvider, repositoryRoot, command));
            }

            // If the user provided specific generator arguments, that overrides any detection logic
            string scriptGeneratorArgs = settings.GetValue(SettingsKeys.ScriptGeneratorArgs);

            if (!String.IsNullOrEmpty(scriptGeneratorArgs))
            {
                return(new CustomGeneratorCommandSiteBuilder(_environment, settings, _propertyProvider, repositoryRoot, scriptGeneratorArgs));
            }

            // If the repository has an explicit pointer to a project path to be deployed
            // then use it.
            string targetProjectPath = settings.GetValue(SettingsKeys.Project);

            if (!String.IsNullOrEmpty(targetProjectPath))
            {
                tracer.Trace("Specific project was specified: " + targetProjectPath);
                targetProjectPath = Path.GetFullPath(Path.Combine(repositoryRoot, targetProjectPath.TrimStart('/', '\\')));
            }

            if (deploymentInfo != null && deploymentInfo.Deployer == Constants.OneDeploy)
            {
                var projectPath = !String.IsNullOrEmpty(targetProjectPath) ? targetProjectPath : repositoryRoot;
                return(new OneDeployBuilder(_environment, settings, _propertyProvider, repositoryRoot, projectPath, deploymentInfo));
            }

            if (settings.RunFromLocalZip())
            {
                return(new RunFromZipSiteBuilder());
            }

            if (!settings.DoBuildDuringDeployment())
            {
                var projectPath = !String.IsNullOrEmpty(targetProjectPath) ? targetProjectPath : repositoryRoot;
                return(new BasicBuilder(_environment, settings, _propertyProvider, repositoryRoot, projectPath));
            }

            string msbuild16Log = String.Format("UseMSBuild16: {0}", VsHelper.UseMSBuild16().ToString());

            tracer.Trace(msbuild16Log);
            KuduEventSource.Log.GenericEvent(
                ServerConfiguration.GetRuntimeSiteName(),
                msbuild16Log,
                string.Empty,
                string.Empty,
                string.Empty,
                string.Empty
                );

            if (!String.IsNullOrEmpty(targetProjectPath))
            {
                // Try to resolve the project
                return(ResolveProject(repositoryRoot,
                                      targetProjectPath,
                                      settings,
                                      fileFinder,
                                      tryWebSiteProject: true,
                                      searchOption: SearchOption.TopDirectoryOnly));
            }

            // Get all solutions in the current repository path
            var solutions = VsHelper.GetSolutions(repositoryRoot, fileFinder).ToList();

            if (!solutions.Any())
            {
                return(ResolveProject(repositoryRoot,
                                      settings,
                                      fileFinder,
                                      searchOption: SearchOption.AllDirectories));
            }

            // More than one solution is ambiguous
            if (solutions.Count > 1)
            {
                // TODO: Show relative paths in error messages
                ThrowAmbiguousSolutionsError(solutions);
            }

            // We have a solution
            VsSolution solution = solutions[0];

            return(DetermineProjectFromSolution(logger, settings, repository, solution));
        }
 public Task Fetch(IRepository repository, DeploymentInfoBase deploymentInfo, string targetBranch, ILogger logger, ITracer tracer)
 {
     repository.FetchWithoutConflict(deploymentInfo.RepositoryUrl, targetBranch);
     return(_completed);
 }