public async Task <IActionResult> ZipPushDeployViaUrl( [FromBody] JObject requestJson, [FromQuery] bool isAsync = false, [FromQuery] bool syncTriggers = false, [FromQuery] string author = null, [FromQuery] string authorEmail = null, [FromQuery] string deployer = DefaultDeployer, [FromQuery] string message = DefaultMessage) { using (_tracer.Step("ZipPushDeployViaUrl")) { string zipUrl = GetZipURLFromJSON(requestJson); var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory) { AllowDeploymentWhileScmDisabled = true, Deployer = deployer, IsContinuous = false, AllowDeferredDeployment = false, IsReusable = false, TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"), CommitId = null, RepositoryType = RepositoryType.None, Fetch = LocalZipHandler, DoFullBuildByDefault = false, Author = author, AuthorEmail = authorEmail, Message = message, ZipURL = zipUrl, DoSyncTriggers = syncTriggers }; return(await PushDeployAsync(deploymentInfo, isAsync, HttpContext)); } }
private void ExtractTriggers(IRepository repository, ZipDeploymentInfo zipDeploymentInfo) { FileSystemHelpers.EnsureDirectory(zipDeploymentInfo.SyncFunctionsTriggersPath); // Loading the zip file depends on how fast the file system is. // Tested Azure Files share with a zip containing 120k files (160 MBs) // takes 20 seconds to load. On my machine it takes 900 msec. using (var zip = ZipFile.OpenRead(Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName))) { var entries = zip.Entries // Only select host.json, proxies.json, or function.json that are from top level directories only // Tested with a zip containing 120k files, and this took 90 msec // on my machine. .Where(e => e.FullName.Equals(Constants.FunctionsHostConfigFile, StringComparison.OrdinalIgnoreCase) || e.FullName.Equals(Constants.ProxyConfigFile, StringComparison.OrdinalIgnoreCase) || isFunctionJson(e.FullName)); foreach (var entry in entries) { var path = Path.Combine(zipDeploymentInfo.SyncFunctionsTriggersPath, entry.FullName); FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(path)); entry.ExtractToFile(path, overwrite: true); } } CommitRepo(repository, zipDeploymentInfo); bool isFunctionJson(string fullName) { return(fullName.EndsWith(Constants.FunctionsConfigFile) && fullName.Count(c => c == '/' || c == '\\') == 1); } }
public static async Task UpdateSiteVersion(ZipDeploymentInfo deploymentInfo, IEnvironment environment, ILogger logger) { var siteVersionPath = Path.Combine(environment.SitePackagesPath, Constants.SiteVersionTxt); logger.Log($"Updating {siteVersionPath} with deployment {deploymentInfo.ZipName}"); await FileSystemHelpers.WriteAllTextToFileAsync(siteVersionPath, deploymentInfo.ZipName); }
public async Task <HttpResponseMessage> WarPushDeploy( [FromUri] bool isAsync = false, [FromUri] string author = null, [FromUri] string authorEmail = null, [FromUri] string deployer = DefaultDeployer, [FromUri] string message = DefaultMessage) { using (_tracer.Step("WarPushDeploy")) { var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory) { AllowDeploymentWhileScmDisabled = true, Deployer = deployer, TargetPath = Path.Combine("webapps", "ROOT"), WatchedFilePath = Path.Combine("WEB-INF", "web.xml"), IsContinuous = false, AllowDeferredDeployment = false, IsReusable = false, TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed war file"), CommitId = null, RepositoryType = RepositoryType.None, Fetch = LocalZipFetch, DoFullBuildByDefault = false, Author = author, AuthorEmail = authorEmail, Message = message }; return(await PushDeployAsync(deploymentInfo, isAsync)); } }
private async Task WriteSitePackageZip(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer) { var filePath = Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName); // Make sure D:\home\data\SitePackages exists FileSystemHelpers.EnsureDirectory(_environment.SitePackagesPath); using (_tracer.Step("Writing zip file to {0}", filePath)) { if (HttpContext.Request.ContentType.Contains("multipart/form-data", StringComparison.OrdinalIgnoreCase)) { FormValueProvider formModel; using (_tracer.Step("Writing zip file to {0}", filePath)) { using (var file = System.IO.File.Create(filePath)) { formModel = await Request.StreamFile(file); } } } else { using (var file = System.IO.File.Create(filePath)) { await Request.Body.CopyToAsync(file); } } } DeploymentHelper.PurgeBuildArtifactsIfNecessary(_environment.SitePackagesPath, BuildArtifactType.Zip, tracer, _settings.GetMaxZipPackageCount()); }
private static void CommitRepo(IRepository repository, ZipDeploymentInfo zipDeploymentInfo) { // Needed in order for repository.GetChangeSet() to work. // Similar to what OneDriveHelper and DropBoxHelper do. // We need to make to call respository.Commit() since deployment flow expects at // least 1 commit in the IRepository. Even though there is no repo per se in this // scenario, deployment pipeline still generates a NullRepository repository.Commit(zipDeploymentInfo.Message, zipDeploymentInfo.Author, zipDeploymentInfo.AuthorEmail); }
public static async Task UpdateSiteVersion(ZipDeploymentInfo deploymentInfo, IEnvironment environment, ITracer tracer) { var siteVersionPath = Path.Combine(environment.SitePackagesPath, Constants.PackageNameTxt); using (tracer.Step($"Updating {siteVersionPath} with deployment {deploymentInfo.ZipName}")) { await FileSystemHelpers.WriteAllTextToFileAsync(siteVersionPath, deploymentInfo.ZipName); } }
private void ExtractTriggers(IRepository repository, ZipDeploymentInfo zipDeploymentInfo) { FileSystemHelpers.EnsureDirectory(zipDeploymentInfo.SyncFunctionsTriggersPath); // Loading the zip file depends on how fast the file system is. // Tested Azure Files share with a zip containing 120k files (160 MBs) // takes 20 seconds to load. On my machine it takes 900 msec. using (var zip = ZipFile.OpenRead(Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName))) { var entries = zip.Entries // Only select host.json, proxies.json, or top level directories. // Tested with a zip containing 120k files, and this took 90 msec // on my machine. .Where(e => e.FullName.Equals(Constants.FunctionsHostConfigFile, StringComparison.OrdinalIgnoreCase) || e.FullName.Equals(Constants.ProxyConfigFile, StringComparison.OrdinalIgnoreCase) || isTopLevelDirectory(e.FullName)) // If entry is a top level dir, select the function.json in it. // otherwise that must be host.json, or proxies.json. Leave it as is. .Select(e => isTopLevelDirectory(e.FullName) ? zip.GetEntry($"{e.FullName}{Constants.FunctionsConfigFile}") : e ) // if a top level folder wasn't a function, it won't contain a function.json // and GetEntry above will return null .Where(e => e != null); foreach (var entry in entries) { var path = Path.Combine(zipDeploymentInfo.SyncFunctionsTriggersPath, entry.FullName); FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(path)); entry.ExtractToFile(path, overwrite: true); } } CommitRepo(repository, zipDeploymentInfo); bool isTopLevelDirectory(string fullName) { for (var i = 0; i < fullName.Length; i++) { // Zip entries use '/' separators. // If the first '/' we find also the last in the string // It's a top level dir, otherwise it's not if (fullName[i] == '/') { return(i + 1 == fullName.Length); } } // Top level file return(false); } }
private async Task WriteSitePackageZip(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer, HttpContent content) { var filePath = Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName); // Make sure D:\home\data\SitePackages exists FileSystemHelpers.EnsureDirectory(_environment.SitePackagesPath); using (tracer.Step("Saving request content to {0}", filePath)) { await content.CopyToAsync(filePath, tracer); } DeploymentHelper.PurgeZipsIfNecessary(_environment.SitePackagesPath, tracer, _settings.GetMaxZipPackageCount()); }
private async Task <string> DeployZipLocally(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer) { var content = await DeploymentHelper.GetZipContentFromURL(zipDeploymentInfo, tracer); var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip"); var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName); using (_tracer.Step("Downloading content from {0} to {1}", zipDeploymentInfo.ZipURL.Split('?')[0], zipFilePath)) { await content.CopyToAsync(zipFilePath, _tracer); } zipDeploymentInfo.RepositoryUrl = zipFilePath; return(zipFilePath); }
private async Task WriteSitePackageZip(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer) { var filePath = Path.Combine(_environment.SitePackagesPath, zipDeploymentInfo.ZipName); // Make sure D:\home\data\SitePackages exists FileSystemHelpers.EnsureDirectory(_environment.SitePackagesPath); using (tracer.Step("Writing content to {0}", filePath)) { using (var file = FileSystemHelpers.CreateFile(filePath)) { await Request.Content.CopyToAsync(file); } } }
private async Task <string> DeployZipLocally(ZipDeploymentInfo zipDeploymentInfo, ITracer tracer) { var content = await DeploymentHelper.GetZipContentFromURL(zipDeploymentInfo, tracer); var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip"); var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName); using (_tracer.Step("Writing content to {0}", zipFilePath)) { using (var file = FileSystemHelpers.CreateFile(zipFilePath)) { await content.CopyToAsync(file); } } zipDeploymentInfo.RepositoryUrl = zipFilePath; return(zipFilePath); }
public async Task <IActionResult> ZipPushDeploy( [FromQuery] bool isAsync = false, [FromQuery] bool syncTriggers = false, [FromQuery] string author = null, [FromQuery] string authorEmail = null, [FromQuery] string deployer = DefaultDeployer, [FromQuery] string message = DefaultMessage) { using (_tracer.Step("ZipPushDeploy")) { var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory) { AllowDeploymentWhileScmDisabled = true, Deployer = deployer, IsContinuous = false, AllowDeferredDeployment = false, IsReusable = false, TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"), CommitId = null, RepositoryType = RepositoryType.None, Fetch = LocalZipHandler, DoFullBuildByDefault = false, Author = author, AuthorEmail = authorEmail, Message = message, ZipURL = null, DoSyncTriggers = syncTriggers }; if (_settings.RunFromLocalZip()) { // This is used if the deployment is Run-From-Zip // the name of the deployed file in D:\home\data\SitePackages\{name}.zip is the // timestamp in the format yyyMMddHHmmss. deploymentInfo.ZipName = $"{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.zip"; // This is also for Run-From-Zip where we need to extract the triggers // for post deployment sync triggers. deploymentInfo.SyncFunctionsTriggersPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); } ; return(await PushDeployAsync(deploymentInfo, isAsync, HttpContext)); } }
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); } }
public async Task <IActionResult> WarPushDeploy( [FromQuery] bool isAsync = false, [FromQuery] string author = null, [FromQuery] string authorEmail = null, [FromQuery] string deployer = DefaultDeployer, [FromQuery] string message = DefaultMessage) { using (_tracer.Step("WarPushDeploy")) { var appName = HttpContext.Request.Query["name"].ToString(); if (string.IsNullOrWhiteSpace(appName)) { appName = "ROOT"; } var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory) { AllowDeploymentWhileScmDisabled = true, Deployer = deployer, TargetPath = Path.Combine("webapps", appName), WatchedFilePath = Path.Combine("WEB-INF", "web.xml"), IsContinuous = false, AllowDeferredDeployment = false, IsReusable = false, CleanupTargetDirectory = true, // For now, always cleanup the target directory. If needed, make it configurable TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed war file"), CommitId = null, RepositoryType = RepositoryType.None, Fetch = LocalZipFetch, DoFullBuildByDefault = false, Author = author, AuthorEmail = authorEmail, Message = message, ZipURL = null }; return(await PushDeployAsync(deploymentInfo, isAsync, HttpContext)); } }
private async Task <HttpResponseMessage> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync) { var content = Request.Content; var isRequestJSON = content.Headers?.ContentType?.MediaType?.Equals("application/json", StringComparison.OrdinalIgnoreCase); if (isRequestJSON == true) { try { var requestObject = await Request.Content.ReadAsAsync <JObject>(); deploymentInfo.ZipURL = ArmUtils.IsArmRequest(Request) ? GetZipURLFromARMJSON(requestObject) : GetZipURLFromJSON(requestObject); } catch (Exception ex) { return(ArmUtils.CreateErrorResponse(Request, HttpStatusCode.BadRequest, ex)); } } else { if (_settings.RunFromLocalZip()) { await WriteSitePackageZip(deploymentInfo, _tracer, Request.Content); } else { var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip"); var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName); using (_tracer.Step("Saving request content to {0}", zipFilePath)) { await content.CopyToAsync(zipFilePath, _tracer); } deploymentInfo.RepositoryUrl = zipFilePath; } } isAsync = ArmUtils.IsArmRequest(Request) ? true : isAsync; var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD"); var response = Request.CreateResponse(); switch (result) { case FetchDeploymentRequestResult.RunningAynschronously: if (ArmUtils.IsArmRequest(Request)) { DeployResult deployResult = new DeployResult(); response = Request.CreateResponse(HttpStatusCode.Accepted, ArmUtils.AddEnvelopeOnArmRequest(deployResult, Request)); string statusURL = GetStatusUrl(); // Should not happen: If we couldn't make the URL, there must have been an error in the request if (string.IsNullOrEmpty(statusURL)) { var badResponse = Request.CreateResponse(); badResponse.StatusCode = HttpStatusCode.BadRequest; return(badResponse); } // latest deployment keyword reserved to poll till deployment done response.Headers.Location = new Uri(statusURL + String.Format("/deployments/{0}?api-version=2018-02-01&deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ"))); } else if (isAsync) { // latest deployment keyword reserved to poll till deployment done response.Headers.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"))); } response.StatusCode = HttpStatusCode.Accepted; break; case FetchDeploymentRequestResult.ForbiddenScmDisabled: // Should never hit this for zip push deploy response.StatusCode = HttpStatusCode.Forbidden; _tracer.Trace("Scm is not enabled, reject all requests."); break; case FetchDeploymentRequestResult.ConflictAutoSwapOngoing: response.StatusCode = HttpStatusCode.Conflict; response.Content = new StringContent(Resources.Error_AutoSwapDeploymentOngoing); break; case FetchDeploymentRequestResult.Pending: // Shouldn't happen here, as we disallow deferral for this use case response.StatusCode = HttpStatusCode.Accepted; break; case FetchDeploymentRequestResult.RanSynchronously: response.StatusCode = HttpStatusCode.OK; break; case FetchDeploymentRequestResult.ConflictDeploymentInProgress: response.StatusCode = HttpStatusCode.Conflict; response.Content = new StringContent(Resources.Error_DeploymentInProgress); break; case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured: response.StatusCode = HttpStatusCode.Conflict; response.Content = new StringContent(Resources.Error_RunFromRemoteZipConfigured); break; default: response.StatusCode = HttpStatusCode.BadRequest; break; } return(response); }
public async Task <HttpResponseMessage> ZipPushDeploy( HttpRequestMessage request, [FromUri] bool isAsync = false, [FromUri] string author = null, [FromUri] string authorEmail = null, [FromUri] string deployer = DefaultDeployer, [FromUri] string message = DefaultMessage) { using (_tracer.Step("ZipPushDeploy")) { var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip"); var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName); using (_tracer.Step("Writing zip file to {0}", zipFilePath)) { using (var file = FileSystemHelpers.CreateFile(zipFilePath)) { await request.Content.CopyToAsync(file); } } var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory) { AllowDeploymentWhileScmDisabled = true, Deployer = deployer, IsContinuous = false, AllowDeferredDeployment = false, IsReusable = false, RepositoryUrl = zipFilePath, TargetChangeset = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"), CommitId = null, RepositoryType = RepositoryType.None, Fetch = LocalZipFetch, DoFullBuildByDefault = false, Author = author, AuthorEmail = authorEmail, Message = message }; var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD"); var response = request.CreateResponse(); switch (result) { case FetchDeploymentRequestResult.RunningAynschronously: if (isAsync) { // latest deployment keyword reserved to poll till deployment done response.Headers.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"))); } response.StatusCode = HttpStatusCode.Accepted; break; case FetchDeploymentRequestResult.ForbiddenScmDisabled: // Should never hit this for zip push deploy response.StatusCode = HttpStatusCode.Forbidden; _tracer.Trace("Scm is not enabled, reject all requests."); break; case FetchDeploymentRequestResult.ConflictAutoSwapOngoing: response.StatusCode = HttpStatusCode.Conflict; response.Content = new StringContent(Resources.Error_AutoSwapDeploymentOngoing); break; case FetchDeploymentRequestResult.Pending: // Shouldn't happen here, as we disallow deferral for this use case response.StatusCode = HttpStatusCode.Accepted; break; case FetchDeploymentRequestResult.RanSynchronously: response.StatusCode = HttpStatusCode.OK; break; case FetchDeploymentRequestResult.ConflictDeploymentInProgress: response.StatusCode = HttpStatusCode.Conflict; response.Content = new StringContent(Resources.Error_DeploymentInProgress); break; default: response.StatusCode = HttpStatusCode.BadRequest; break; } return(response); } }
private async Task <HttpResponseMessage> PushDeployAsync( ZipDeploymentInfo deploymentInfo, bool isAsync) { var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip"); var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName); using (_tracer.Step("Writing content to {0}", zipFilePath)) { using (var file = FileSystemHelpers.CreateFile(zipFilePath)) { await Request.Content.CopyToAsync(file); } } deploymentInfo.RepositoryUrl = zipFilePath; var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD"); var response = Request.CreateResponse(); switch (result) { case FetchDeploymentRequestResult.RunningAynschronously: if (isAsync) { // latest deployment keyword reserved to poll till deployment done response.Headers.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"))); } response.StatusCode = HttpStatusCode.Accepted; break; case FetchDeploymentRequestResult.ForbiddenScmDisabled: // Should never hit this for zip push deploy response.StatusCode = HttpStatusCode.Forbidden; _tracer.Trace("Scm is not enabled, reject all requests."); break; case FetchDeploymentRequestResult.ConflictAutoSwapOngoing: response.StatusCode = HttpStatusCode.Conflict; response.Content = new StringContent(Resources.Error_AutoSwapDeploymentOngoing); break; case FetchDeploymentRequestResult.Pending: // Shouldn't happen here, as we disallow deferral for this use case response.StatusCode = HttpStatusCode.Accepted; break; case FetchDeploymentRequestResult.RanSynchronously: response.StatusCode = HttpStatusCode.OK; break; case FetchDeploymentRequestResult.ConflictDeploymentInProgress: response.StatusCode = HttpStatusCode.Conflict; response.Content = new StringContent(Resources.Error_DeploymentInProgress); break; default: response.StatusCode = HttpStatusCode.BadRequest; break; } return(response); }
private async Task <IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync) { var zipFilePath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip"); if (_settings.RunFromLocalZip()) { await WriteSitePackageZip(deploymentInfo, _tracer); } else { using (_tracer.Step("Writing zip file to {0}", zipFilePath)) { if (HttpContext.Request.ContentType.Contains("multipart/form-data", StringComparison.OrdinalIgnoreCase)) { FormValueProvider formModel; using (_tracer.Step("Writing zip file to {0}", zipFilePath)) { using (var file = System.IO.File.Create(zipFilePath)) { formModel = await Request.StreamFile(file); } } } else { using (var file = System.IO.File.Create(zipFilePath)) { await Request.Body.CopyToAsync(file); } } } deploymentInfo.RepositoryUrl = zipFilePath; } 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_AutoSwapDeploymentOngoing)); default: return(BadRequest()); } }
private async Task <IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync, HttpContext context) { var zipFilePath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip"); 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 zip file to {0}", zipFilePath)) { 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}", zipFilePath)) { using (var file = System.IO.File.Create(zipFilePath)) { formModel = await Request.StreamFile(file); } } } else if (deploymentInfo.ZipURL != null) { using (_tracer.Step("Writing zip file from packageUri to {0}", zipFilePath)) { using (var httpClient = new HttpClient()) using (var fileStream = new FileStream(zipFilePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) { var zipUrlRequest = new HttpRequestMessage(HttpMethod.Get, deploymentInfo.ZipURL); var zipUrlResponse = await httpClient.SendAsync(zipUrlRequest); try { zipUrlResponse.EnsureSuccessStatusCode(); } catch (HttpRequestException hre) { _tracer.TraceError(hre, "Failed to get file from packageUri {0}", deploymentInfo.ZipURL); throw; } using (var content = await zipUrlResponse.Content.ReadAsStreamAsync()) { await content.CopyToAsync(fileStream); } } } } else { using (var file = System.IO.File.Create(zipFilePath)) { await Request.Body.CopyToAsync(file); } } } deploymentInfo.RepositoryUrl = zipFilePath; } 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()); } }