Exemplo n.º 1
0
 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;
                }
            }
        }