public PushDeploymentController( IEnvironment environment, IFetchDeploymentManager deploymentManager, ITracer tracer, ITraceFactory traceFactory, IDeploymentSettingsManager settings) { _environment = environment; _deploymentManager = deploymentManager; _tracer = tracer; _traceFactory = traceFactory; _settings = settings; }
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; } } }