How to verify status of API deploy?

I’m very happy about the new command line tool for deployments. I’m using the tool in our CI environment, but it looks like the tool returns immediately instead of waiting for the deployment to complete. What is the best way to automate the verification of the deployment status? My build cannot kick off automated tests until the deployment is complete. Is there a restful http get I could use?

Hi Dave,

The Deployment object that is returned when you get a specific deployment (http://{server}/api/projects/{projectId}/releases/{releaseId}/deployments/{deploymentId}) has a Task url in the Links collection. If you do a get on that url (http://{server}/api/tasks/{taskId}), you should be able to see the State property. Then you can kick off your testing once it says ‘Success’. When Paul adds support for ad-hoc powershell scripts, you’ll be be able to run a powershell script at the end of your deployment automatically so you won’t need to poll that value.

Hope this helps,
Steven

Hey Steven, thanks for replying. I was impatient and ended up implementing a TFS Code Activity that hits the database to determine the status.

In case it helps somebody else out:

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Activities;
using System.Threading;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Build.Workflow.Activities;

namespace SST.BuildTasks.Activities
{

public sealed class DetermineDeploymentState : CodeActivity
{
	// Define an activity input argument of type string
	public InArgument<int> PingInterval { get; set; }
	public InArgument<string> ConnectionString { get; set; }
	public InArgument<int> TimeOut { get; set; }
	public InOutArgument<bool> Succeeded { get; set; }
	public InArgument<string> OctopusProject { get; set; }

	private const string Sql =
		@"SELECT [State]
    FROM 
[Octopus].[Octopus].Project P
INNER JOIN 
[Octopus].[Octopus].[Release] R
ON P.Id = R.Project_Id 
INNER JOIN 
[Octopus].[Octopus].Deployment D
ON R.Id = D.Release_Id
INNER JOIN 
[Octopus].[Octopus].Task T
ON D.Task_Id = T.Id
WHERE Version = @Version
AND P.Name = @ProjectName";

	private const string ErrorSql =
		@"SELECT [ErrorMessage]
   FROM 
[Octopus].[Octopus].Project P
INNER JOIN 
[Octopus].[Octopus].[Release] R
ON P.Id = R.Project_Id 
INNER JOIN 
[Octopus].[Octopus].Deployment D
ON R.Id = D.Release_Id
INNER JOIN 
[Octopus].[Octopus].Task T
ON D.Task_Id = T.Id
WHERE Version = @Version
AND P.Name = @ProjectName";

	// If your activity returns a value, derive from CodeActivity<TResult>
	// and return the value from the Execute method.
	protected override void Execute(CodeActivityContext context)
	{

		var buildDetail = context.GetExtension<IBuildDetail>();
		string buildNumber = buildDetail.BuildNumber;
		int pingInterval = context.GetValue(PingInterval);
		string connectionString = context.GetValue(ConnectionString);
		int timeOut = context.GetValue(TimeOut);
		string project = context.GetValue(OctopusProject);

		try
		{
			using (var cnnc = new SqlConnection(connectionString))
			{
				cnnc.Open();
				using (var cmd = new SqlCommand(Sql, cnnc))
				{
					cmd.Parameters.AddWithValue("@Version", buildNumber);
					cmd.Parameters.AddWithValue("@ProjectName", project);
					int count = 0;
					bool keepPinging = true;
					while (keepPinging & count < timeOut)
					{
						object result = cmd.ExecuteScalar();
						if (result != null)
						{
							string state = result.ToString();
							switch (state)
							{
								case "Success" :
									context.SetValue(Succeeded, true);
									keepPinging = false;
									context.TrackBuildMessage(string.Format("Octopus deploy {0} for {1} successful.", buildNumber, project));
									break;
								case "Failed" :
									context.SetValue(Succeeded, false);
									keepPinging = false;
									cmd.CommandText = ErrorSql;
									result = cmd.ExecuteScalar();
									context.TrackBuildError(result.ToString());
									break;
							}
						}
						// Wait one interval
						Thread.Sleep(pingInterval);
						count += pingInterval;
					}
				}
			}
		}
		catch (Exception ex)
		{
			context.SetValue(Succeeded, false);
			context.TrackBuildError(ex.ToString());
		}

	}
}

}

Hi Dave,

This is now a command line option in Octo.exe:

octo create-release .... --waitfordeployment

Hope that helps,

Paul