Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Customizing deployment #112

Closed
wants to merge 3 commits into from

2 participants

David Fowler David Ebbo
David Fowler
Collaborator

If the repository has a deploy.cmd at the root, we will call into this instead of doing our own build/deployment. When using this, the user takes over the entire process, with full control.

When the batch file is called, some settings are made available to it via env variable:

  • SOURCE has the path to the sources (which is the repo folder)
  • TARGET has the path to where the deployment needs to go (which is the wwwroot folder)
David Ebbo davidebbo commented on the diff
Kudu.Core/Deployment/CustomBuilder.cs
((13 lines not shown))
+
+ private const string SourcePath = "SOURCE";
+ private const string TargetPath = "TARGET";
+ private const string DeployCmd = "deploy.cmd";
+
+ public CustomBuilder(string repositoryPath, string targetFile)
+ {
+ _repositoryPath = repositoryPath;
+ _targetFile = targetFile;
+ }
+
+ public Task Build(DeploymentContext context)
+ {
+ var tcs = new TaskCompletionSource<object>();
+
+ ILogger customLogger = context.Logger.Log("Running custom deployment..");
David Ebbo Owner

Should be 1 or 3 periods. Two is weird :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
David Ebbo davidebbo commented on the diff
Kudu.Core/Deployment/CustomBuilder.cs
((60 lines not shown))
+ {
+ string targetFile = Path.Combine(repositoryRoot, DeployCmd);
+ customDeploymentFile = null;
+
+ if (File.Exists(targetFile))
+ {
+ customDeploymentFile = targetFile;
+ return true;
+ }
+
+ return false;
+ }
+
+ private Executable GetExecutable()
+ {
+ // Creates an executable poiting to Deploy.cmd and the working directory being
David Ebbo Owner

typo: 'pointing'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
David Ebbo davidebbo commented on the diff
Kudu.Core/Deployment/CustomBuilder.cs
((18 lines not shown))
+ public CustomBuilder(string repositoryPath, string targetFile)
+ {
+ _repositoryPath = repositoryPath;
+ _targetFile = targetFile;
+ }
+
+ public Task Build(DeploymentContext context)
+ {
+ var tcs = new TaskCompletionSource<object>();
+
+ ILogger customLogger = context.Logger.Log("Running custom deployment..");
+
+ Executable exe = GetExecutable();
+ exe.EnvironmentVariables[SourcePath] = _repositoryPath;
+ exe.EnvironmentVariables[TargetPath] = context.OutputPath;
+
David Ebbo Owner

Should put msbuild on path, but we can add that logic in a later commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
David Ebbo davidebbo commented on the diff
Kudu.FunctionalTests/GitRepositoryManagementTests.cs
((7 lines not shown))
+ string repositoryName = "WapWithCustomDeploymentScript";
+ string appName = KuduUtils.GetRandomWebsiteName("WapWithCustomDeploymentScript");
+ string cloneUrl = "https://github.com/KuduApps/CustomBuildScript.git";
+
+ using (var repo = Git.Clone(repositoryName, cloneUrl))
+ {
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ GitDeploymentResult deployResult = appManager.GitDeploy(repo.PhysicalPath);
+ var results = appManager.DeploymentManager.GetResultsAsync().Result.ToList();
+
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ KuduAssert.VerifyUrl(appManager.SiteUrl, "DEBUG");
David Ebbo Owner

Where does "DEBUG" string come from? Something returned by the root of the site when you hit it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
David Ebbo
Owner

Looks good

David Fowler davidfowl closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 20, 2012
  1. David Fowler

    Added support for overriding deployment via custom script.

    davidfowl authored
    - Detect deploy.cmd in the repository and run that instead.
    - Added test that verifies the custom deploy.cmd scenario.
  2. David Fowler
  3. David Fowler
This page is out of date. Refresh to see the latest.
80 Kudu.Core/Deployment/CustomBuilder.cs
View
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Kudu.Contracts.Tracing;
+using Kudu.Core.Infrastructure;
+
+namespace Kudu.Core.Deployment
+{
+ public class CustomBuilder : ISiteBuilder
+ {
+ private readonly string _targetFile;
+ private readonly string _repositoryPath;
+
+ private const string SourcePath = "SOURCE";
+ private const string TargetPath = "TARGET";
+ private const string DeployCmd = "deploy.cmd";
+
+ public CustomBuilder(string repositoryPath, string targetFile)
+ {
+ _repositoryPath = repositoryPath;
+ _targetFile = targetFile;
+ }
+
+ public Task Build(DeploymentContext context)
+ {
+ var tcs = new TaskCompletionSource<object>();
+
+ ILogger customLogger = context.Logger.Log("Running custom deployment..");
David Ebbo Owner

Should be 1 or 3 periods. Two is weird :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ Executable exe = GetExecutable();
+ exe.EnvironmentVariables[SourcePath] = _repositoryPath;
+ exe.EnvironmentVariables[TargetPath] = context.OutputPath;
+
David Ebbo Owner

Should put msbuild on path, but we can add that logic in a later commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ try
+ {
+ string output = exe.ExecuteWithConsoleOutput(context.Tracer, String.Empty).Item1;
+
+ customLogger.Log(output);
+
+ tcs.SetResult(null);
+ }
+ catch (Exception ex)
+ {
+ context.Tracer.TraceError(ex);
+
+ // HACK: Log an empty error to the global logger (post receive hook console output).
+ // The reason we don't log the real exception is because the 'live output' running
+ // msbuild has already been captured.
+ context.GlobalLogger.LogError();
+
+ customLogger.Log(ex);
+
+ tcs.SetException(ex);
+ }
+
+ return tcs.Task;
+ }
+
+ public static bool TryGetCustomDeploymentFile(string repositoryRoot, out string customDeploymentFile)
+ {
+ string targetFile = Path.Combine(repositoryRoot, DeployCmd);
+ customDeploymentFile = null;
+
+ if (File.Exists(targetFile))
+ {
+ customDeploymentFile = targetFile;
+ return true;
+ }
+
+ return false;
+ }
+
+ private Executable GetExecutable()
+ {
+ // Creates an executable poiting to Deploy.cmd and the working directory being
David Ebbo Owner

typo: 'pointing'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ // the repository root
+ return new Executable(_targetFile, _repositoryPath);
+ }
+ }
+}
7 Kudu.Core/Deployment/SiteBuilderFactory.cs
View
@@ -23,6 +23,13 @@ public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger)
{
string repositoryRoot = _environment.DeploymentRepositoryPath;
+ // If there's a custom deployment file then let that take over.
+ string customDeploymentFile;
+ if (CustomBuilder.TryGetCustomDeploymentFile(repositoryRoot, out customDeploymentFile))
+ {
+ return new CustomBuilder(repositoryRoot, customDeploymentFile);
+ }
+
var configuration = new DeploymentConfiguration(repositoryRoot);
// If the repository has an explicit pointer to a project path to be deployed
1  Kudu.Core/Kudu.Core.csproj
View
@@ -70,6 +70,7 @@
</Compile>
<Compile Include="Commands\CommandExecutor.cs" />
<Compile Include="Deployment\CascadeLogger.cs" />
+ <Compile Include="Deployment\CustomBuilder.cs" />
<Compile Include="Deployment\DeploymentConfiguration.cs" />
<Compile Include="Deployment\DeploymentContext.cs" />
<Compile Include="Deployment\DeploymentHelper.cs" />
51 Kudu.FunctionalTests/GitRepositoryManagementTests.cs
View
@@ -62,6 +62,57 @@ public void PushRepoWithMultipleProjectsShouldDeploy()
}
[Fact]
+ public void PushSimpleWapWithCustomDeploymentScript()
+ {
+ // Arrange
+ string repositoryName = "WapWithCustomDeploymentScript";
+ string appName = KuduUtils.GetRandomWebsiteName("WapWithCustomDeploymentScript");
+ string cloneUrl = "https://github.com/KuduApps/CustomBuildScript.git";
+
+ using (var repo = Git.Clone(repositoryName, cloneUrl))
+ {
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ GitDeploymentResult deployResult = appManager.GitDeploy(repo.PhysicalPath);
+ var results = appManager.DeploymentManager.GetResultsAsync().Result.ToList();
+
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ KuduAssert.VerifyUrl(appManager.SiteUrl, "DEBUG");
David Ebbo Owner

Where does "DEBUG" string come from? Something returned by the root of the site when you hit it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ });
+ }
+ }
+
+ [Fact]
+ public void PushSimpleWapWithFailingCustomDeploymentScript()
+ {
+ // Arrange
+ string repositoryName = "WapWithFailingCustomDeploymentScript";
+ string appName = KuduUtils.GetRandomWebsiteName("WapWithFailingCustomDeploymentScript");
+ string cloneUrl = "https://github.com/KuduApps/CustomBuildScript.git";
+
+ using (var repo = Git.Clone(repositoryName, cloneUrl))
+ {
+ repo.WriteFile("deploy.cmd", "bogus");
+ Git.Commit(repo.PhysicalPath, "Updated the deploy file.");
+
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ GitDeploymentResult deployResult = appManager.GitDeploy(repo.PhysicalPath);
+ var results = appManager.DeploymentManager.GetResultsAsync().Result.ToList();
+
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Failed, results[0].Status);
+ KuduAssert.VerifyLogOutput(appManager, results[0].Id, "'bogus' is not recognized as an internal or external command");
+ });
+ }
+ }
+
+ [Fact]
public void WarningsAsErrors()
{
// Arrange
Something went wrong with that request. Please try again.