sdk/Sdk/Tasks/ZipDeploy/ZipDeployTask.cs (116 lines of code) (raw):

// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; using System.IO; using System.Linq; using System.Net; using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Microsoft.NET.Sdk.Functions.Http; using Microsoft.NET.Sdk.Functions.MSBuild.Tasks; // IMPORTANT: Do not modify this file directly with major changes // This file is a copy from this project (with minor updates) -- https://github.com/Azure/azure-functions-vs-build-sdk/blob/b0e54a832a92119e00a2b1796258fcf88e0d6109/src/Microsoft.NET.Sdk.Functions.MSBuild/Microsoft.NET.Sdk.Functions.MSBuild.csproj // Please make any changes upstream first. namespace Microsoft.NET.Sdk.Functions.Tasks { #if NET472 [LoadInSeparateAppDomain] public class ZipDeployTask : AppDomainIsolatedTask #else public class ZipDeployTask : Task #endif { private const string UserAgentName = "functions-core-tools"; [Required] public string? ZipToPublishPath { get; set; } [Required] public string? DeploymentUsername { get; set; } [Required] public string? DeploymentPassword { get; set; } [Required] public string? UserAgentVersion { get; set; } public string? PublishUrl { get; set; } public bool UseBlobContainerDeploy { get; set; } /// <summary> /// Our fallback if PublishUrl is not given, which is the case for ZIP Deploy profiles created prior to 15.8 Preview 4. /// Using this will fail if the site is a slot. /// </summary> public string? SiteName { get; set; } public override bool Execute() { using (DefaultHttpClient client = new DefaultHttpClient()) { System.Threading.Tasks.Task<bool> t = ZipDeployAsync(ZipToPublishPath!, DeploymentUsername!, DeploymentPassword!, PublishUrl, SiteName!, UserAgentVersion!, UseBlobContainerDeploy, client, true); t.Wait(); return t.Result; } } internal System.Threading.Tasks.Task<bool> ZipDeployAsync(string zipToPublishPath, string userName, string password, string publishUrl, string siteName, string userAgentVersion, IHttpClient client, bool logMessages) { return ZipDeployAsync(zipToPublishPath, userName, password, publishUrl, siteName, userAgentVersion, useBlobContainerDeploy: false, client, logMessages); } internal async System.Threading.Tasks.Task<bool> ZipDeployAsync(string zipToPublishPath, string userName, string password, string? publishUrl, string? siteName, string userAgentVersion, bool useBlobContainerDeploy, IHttpClient client, bool logMessages) { if (!File.Exists(zipToPublishPath) || client == null) { return false; } string zipDeployPublishUrl; if (!string.IsNullOrEmpty(publishUrl)) { if (!publishUrl!.EndsWith("/")) { publishUrl += "/"; } zipDeployPublishUrl = publishUrl + "api"; } else if (!string.IsNullOrEmpty(siteName)) { zipDeployPublishUrl = $"https://{siteName}.scm.azurewebsites.net/api"; } else { if (logMessages) { Log.LogError(StringMessages.NeitherSiteNameNorPublishUrlGivenError); } return false; } // publish endpoint differs when using a blob storage container var publishUriPath = useBlobContainerDeploy ? "publish?RemoteBuild=false" : "zipdeploy?isAsync=true"; // "<publishUrl>/api/zipdeploy?isAsync=true" or "<publishUrl>/api/publish?RemoteBuild=false" zipDeployPublishUrl = $"{zipDeployPublishUrl}/{publishUriPath}"; if (logMessages) { Log.LogMessage(MessageImportance.High, String.Format(StringMessages.PublishingZipViaZipDeploy, zipToPublishPath, zipDeployPublishUrl)); } Uri uri = new Uri($"{zipDeployPublishUrl}", UriKind.Absolute); string userAgent = $"{UserAgentName}/{userAgentVersion}"; FileStream stream = File.OpenRead(zipToPublishPath); IHttpResponse response = await client.PostRequestAsync(uri, userName, password, "application/zip", userAgent, Encoding.UTF8, stream); if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Accepted) { if (logMessages) { Log.LogError(String.Format(StringMessages.ZipDeployFailureErrorMessage, zipDeployPublishUrl, response.StatusCode)); } return false; } else { if (logMessages) { Log.LogMessage(StringMessages.ZipFileUploaded); } string deploymentUrl = response.GetHeader("Location").FirstOrDefault(); if (!string.IsNullOrEmpty(deploymentUrl)) { ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client, userAgent, Log, logMessages); DeployStatus status = await deploymentStatus.PollDeploymentStatusAsync(deploymentUrl, userName, password); if (status == DeployStatus.Success || status == DeployStatus.PartialSuccess) { Log.LogMessage(MessageImportance.High, StringMessages.ZipDeploymentSucceeded); return true; } else if (status == DeployStatus.Failed || status == DeployStatus.Conflict || status == DeployStatus.Unknown) { Log.LogError(String.Format(StringMessages.ZipDeployFailureErrorMessage, zipDeployPublishUrl, status)); return false; } } } return true; } } }