Plugin Template

Examples of programs integrating with Vault and Fortress API. Also, information on integrating with NAnt, CruiseControl.Net and other third-party tools

Moderator: SourceGear

jeremy_sg
Posts: 1821
Joined: Thu Dec 18, 2003 11:39 am
Location: Sourcegear
Contact:

Plugin Template

Post by jeremy_sg » Wed Feb 06, 2008 2:48 pm

This post includes an updated version of the VaultPluginTemplate which originated at http://weblogs.asp.net/jeremy_sheeley/a ... 09102.aspx
We've had lots of requests from customers who want to be able to hook into the Vault server to catch events. Since Sourcegear can't meet everyone's need's exactly, I wanted to provide a small example plugin, which could be modified to do more useful work, such as notifying an email address, or starting an automated build. Two things to note:

1. Sourcegear still plans on writing plugins to ship with Vault and those will be fully supported. We're not going to ask everyone to write their own email plugin, for example. This is just a kick start for those Vault users who know what they want and want it now.
2. As we write our plugins, we may change the plugin API and architecture. Don't count on this API staying constant. When or if we do change the API, expect me to update this example with the new way of doing things.

The template can be found at here.

Setting this up is a bit complicated, as it is a Web Service.

1. Unzip the template to somewhere on disk.
2. In IIS Manager, create a virtual directory named PluginServiceTemplate that points to the directory that holds the PluginServiceTemplate.asmx file.
3. Load the solution file. Build the solution. If there are any problems building, verify that the references point to the correct locations on disk. By default, the VaultPluginLib reference points to c:\inetpub\wwwroot\VaultService\bin, and all others point to c:\program files\Sourcegear\Vault Client.
4. Start debugging. When the Web Service page comes up, click on UpdateVaultConnectionInformation. Fill in the hostname, username, and password that you wish to use to connect to your Vault server. Hit the Invoke button will set the connection information.
5. Go back to the Web Service page. Click on UpdateRepositoryInformation. Fill out the repositoryName and pathToWatch fields. Hit Invoke again.
6. Go back to the Web Service page. Click on RegisterWithServer. Type in the password for the user "admin" on the Vault Server that you specified above. Hit Invoke. If no longer wish to have the Vault server call the plugin, you must call UnRegisterWithServer.

Now that you're set up, you should be able to put a breakpoint in the OnEndTx method in PluginServiceTemplate.asmx.cs, and when a change is made to the repository that you're watching while you're debugging, the breakpoint should be hit. There are four methods that a plugin can define.

* OnLogin
* OnLogout
* OnBeginTx
* OnEndTx

The example only overrides OnEndTx, since that's the most interesting of the four. When the plugin is informed that a transaction has finished, OnEndTx walks through the following steps.

1. Log in to the Vault server and refresh the tree cache.
2. Use FindFolderRecursive (Remember that from last time?) to find the path to watch.
3. If the version number on that object is different that the last version number we saw, run a history query to find out what changed in the last transaction.
4. Loop through all of the VaultHistoryItems. Right now that loop is empty.

Note that if all you want is a plugin that kicks off a new build, you can probably skip the history query.
EDIT: removed the period.

EDIT: updated the plugin code with the URL fix discussed below.
Attachments
VaultPluginTemplate.zip
A template for creating custom plugins.
(14.28 KiB) Downloaded 1895 times
Last edited by jeremy_sg on Fri Jun 06, 2008 2:07 pm, edited 2 times in total.
Subscribe to the Fortress/Vault blog

andrews
Posts: 55
Joined: Tue Feb 05, 2008 7:40 pm

Post by andrews » Mon Feb 11, 2008 6:29 pm

Jeremy, quick questions - what do you enter in the "path to watch" field? What is it used for?

Edit: In the UpdateRepositoryInformation step, I enter the name of the repository & have taken various guesses at pathToWatch, but whatever I do, hitting invoke produces the following error:-

Code: Select all

System.Exception: The connection to the server failed: server cannot be contacted or uses a protocol that is not supported by this client. Invalid URI: The format of the URI could not be determined. ---> System.UriFormatException: Invalid URI: The format of the URI could not be determined.
   at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
   at System.Uri..ctor(String uriString)
   at System.Web.Services.Protocols.WebClientProtocol.set_Url(String value)
   at VaultClientNetLib.VaultConnection.Login(String strURLBase, String strUserLogin, String strPassword)
   at VaultClientOperationsLib.ClientInstance.Login(String urlbase, String username, String password)
   at VaultClientIntegrationLib.ServerOperations.Login(AccessLevelType altCommand, Boolean bAllowAuto, Boolean bSaveSession)
   --- End of inner exception stack trace ---
   at VaultClientIntegrationLib.ServerOperations.Login(AccessLevelType altCommand, Boolean bAllowAuto, Boolean bSaveSession)
   at VaultClientIntegrationLib.ServerOperations.Login()
   at VaultPluginTemplate.PluginServiceTemplate.UpdateRepositoryInformation(String repositoryName, String pathToWatch) in C:\lansadev\VSCTESTING\Installers\VaultPluginTemplate\PluginServiceTemplate.asmx.cs:line 485
I note this happened to someone else back in 2006, but there's no answers to their questions... http://support.sourcegear.com/viewtopic.php?t=6504

MattTrinder
Posts: 24
Joined: Tue Feb 12, 2008 8:07 am

Post by MattTrinder » Tue Feb 12, 2008 8:08 am

You may want to remove the period from the end of the link - it doesn't work if you dont 8)

jeremy_sg
Posts: 1821
Joined: Thu Dec 18, 2003 11:39 am
Location: Sourcegear
Contact:

Post by jeremy_sg » Tue Feb 12, 2008 10:13 am

andrews,

There's a bug in the template. If you look for the spots where ServerOperations.client.LoginOptions.URL is set, one is converting it to a URL and the other spot isn't. You'll need to standardize those two lines, and set the right data using the web service call.

andrews
Posts: 55
Joined: Tue Feb 05, 2008 7:40 pm

Post by andrews » Tue Feb 12, 2008 6:09 pm

The bug's in line 481 of PluginServiceTemplate.asmx.cs - change it to:-

Code: Select all

ServerOperations.client.LoginOptions.URL = "http://" + hostname + "/VaultService";
... and then the sample template's installation/registration process works. I put a value of $ in pathToWatch - is this ok?

Of course, the sample doesn't actually _do_ anything. I added the following lines in the OnEndTx procedure (the first C# code I've ever worked with as it happens)...

Code: Select all

                StreamWriter asw = new StreamWriter("d:/changes.txt");

                foreach (VaultHistoryItem item in arrHistoryItems)
                {
                    //If this were going to do something, this is the place to do it.
                    //The things of interest inside item are:
                    //item.Name -- The path to the item that was modified
                    //item.MiscInfo1 -- An english description of what happened.  This 
                    //					is generated by the LoadHistory method, so you 
                    //					can change it if you want.

                    string changestr;
                    changestr = String.Format("{0}^{1}^{2}^{3}^{4}^{5}^{6}^{7}", item.Name, item.TxDate, item.TxID, item.Type, item.UserLogin, item.Version, item.MiscInfo1);
                    asw.WriteLine(changestr);
                }
                asw.Close();
I then committed a few changed files, and ... no d:\changes.txt was created. I then added some code writing a line to a file at the start of OnEndTx ... and again, nothing happens on a commit.

Any ideas as to what I'm doing wrong?

jeremy_sg
Posts: 1821
Joined: Thu Dec 18, 2003 11:39 am
Location: Sourcegear
Contact:

Post by jeremy_sg » Wed Feb 13, 2008 10:22 am

Look at your server log file to see if it's logging an attempt or failure to connect to your plugin.

andrews
Posts: 55
Joined: Tue Feb 05, 2008 7:40 pm

Post by andrews » Wed Feb 13, 2008 11:57 pm

Hmm ok, I'm seeing the following:-

"Exception in plugin thread : The request failed with HTTP status 401: Unauthorized."

jeremy_sg
Posts: 1821
Joined: Thu Dec 18, 2003 11:39 am
Location: Sourcegear
Contact:

Post by jeremy_sg » Thu Feb 14, 2008 9:41 am

You need to make sure that IIS is allowing anonymous access to the Plugin virtual directory. If you created the Virtual Directory in any automated way (through VS 2005), I find it's best to bring up IIS Manager, delete the virtual directory and readd it from there.

andrews
Posts: 55
Joined: Tue Feb 05, 2008 7:40 pm

Post by andrews » Thu Feb 14, 2008 5:59 pm

I'd created it manually through IIS as per the instructions and yes it had anonymous access. Just to be sure, I've deleted and created the virtual directory again - still the same error happening.

I then loaded the file http://xx.xx.xx.xx/VaultService/PluginS ... plate.asmx
directly from a browser ... and was given a 401.2 error.

The only info I can find on 401.2 errors is here - http://support.microsoft.com/kb/253667/ - which basically says to turn on anonymous access. As you can see in the screenshot below, that's what I've done yet still have the error.

Image

jeremy_sg
Posts: 1821
Joined: Thu Dec 18, 2003 11:39 am
Location: Sourcegear
Contact:

Post by jeremy_sg » Fri Feb 15, 2008 9:22 am

This is probably because you put it underneath the VaultService directory on disc. Move it to another directory outside the VaultService hierarchy.

andrews
Posts: 55
Joined: Tue Feb 05, 2008 7:40 pm

Post by andrews » Sun Feb 17, 2008 3:32 pm

I've now moved it somewhere totally separate - still the same error I'm afraid.

jeremy_sg
Posts: 1821
Joined: Thu Dec 18, 2003 11:39 am
Location: Sourcegear
Contact:

Post by jeremy_sg » Sun Feb 17, 2008 4:24 pm

Just to clarify, did you move the disk location and the virtual directory (URL) location?

andrews
Posts: 55
Joined: Tue Feb 05, 2008 7:40 pm

Post by andrews » Sun Feb 17, 2008 4:32 pm

I'd moved the on-disk directory and then edited the Virtual directory to point to the new location.

Just now I've removed the virtual & created a new one under "Default Web Site" instead of being under "VaultService". Is this what you meant? I can now open the page ok in a browser ...

Edit: I'm going through the plugin configuration process again. In "updateRepositoryInformation", hitting Invoke is getting me this error:-

Code: Select all

System.UnauthorizedAccessException: Access to the path 'C:\Documents and Settings\Default User.WINDOWS\Local Settings\Application Data\Sourcegear\Vault_1\Client\032D3A49-5FF0-4187-8D1E-2AAEE7869EEE\admin' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Directory.InternalCreateDirectory(String fullPath, String path, DirectorySecurity dirSecurity)
   at System.IO.Directory.CreateDirectory(String path, DirectorySecurity directorySecurity)
   at VaultClientOperationsLib.CacheMember_Repository.SerializeCacheMember(Object o, VaultDateTime& lastSyncTime)
   at VaultClientOperationsLib.CacheMember.SaveObjectToDisk(Object o)
   at VaultClientOperationsLib.CacheMember_Repository.SaveIfNewer()
   at VaultClientOperationsLib.TreeCache.Save()
   at VaultClientOperationsLib.ClientInstance.SetActiveRepositoryID(Int32 id, String username, String uniqueRepositoryID, Boolean doRefresh, Boolean updateKnownChangesAll)
   at VaultPluginTemplate.PluginServiceTemplate.UpdateRepositoryInformation(String repositoryName, String pathToWatch) in C:\lansadev\VSCTESTING\Installers\VaultPluginTemplate\PluginServiceTemplate.asmx.cs:line 513
The directory C:\Documents and Settings\Default User.WINDOWS\Local Settings\Application Data\Sourcegear\Vault_1\Client\032D3A49-5FF0-4187-8D1E-2AAEE7869EEE\admin does not exist, in fact there's no "Sourcegear" under Default User.WINDOWS\Local Settings\Application Data.

Edit Again: Got it working - the user group "Users" only had read permissions to that folder. Changing it to "Full Control" got it working ... and the plugin's working too, intercepting events :D

Thanks for your help Jeremy...

andrews
Posts: 55
Joined: Tue Feb 05, 2008 7:40 pm

Post by andrews » Sun Feb 17, 2008 6:37 pm

The sample plugin is not actually listing any changes to files. Looking at the plugin's code, there's the following lines:-

Code: Select all

lastversion = long.Parse((string)System.Configuration.ConfigurationSettings.AppSettings[WebConfigLastVersionKey]);  
VaultClientFolder vcfolder = ServerOperations.client.ClientInstance.TreeCache.Repository.Root.FindFolderRecursive(pathToWatch);
long currentversion = 0;
if (vcfolder == null)
{
   VaultClientFile vcfile = ServerOperations.client.ClientInstance.TreeCache.Repository.Root.FindFileRecursive(pathToWatch);
   if (vcfile != null)
     currentversion = vcfile.Version;
}
else
   currentversion = vcfolder.Version;

if (currentversion != lastversion) ...
In my testing, lastversion is always the same as currentversion - it seems to get set to the latest value before execution reaches OnEndTx.

Removing the if (currentversion != lastversion) test, and then filtering the list by item.TxID == currentversion seems to work properly.

robe070
Posts: 176
Joined: Wed Feb 06, 2008 7:42 pm

Error compiling sample plugin

Post by robe070 » Tue Mar 25, 2008 11:23 pm

Firstly, we've had the plugin running fine. We haven't used it for 4 weeks or so, or at least checked if it was working.

We upgraded from 4.0.6 to 4.1 sometime after.

Previously we had compiled the plugin on a seperate machine and copied it to the Vault server. Now we have installed VS 2005 on the server with SP1.

Now the plugin is not working. The symptom is that the plugin event OnEndTx is executed but control does not return from ServerOperations.Login(); It looks like an exception is thrown. Please excuse my naivety with Web Services.

I get this error in VS 2005 on 64-bit Win 2003 Server when I build the sample: Error 1 C:\Vault\PST\PluginServiceTemplate.asmx: ASP.NET runtime error: '/LM/W3SVC/1/ROOT/VaultPluginTemplate' is not a valid IIS application. C:\Vault\PST\PluginServiceTemplate.asmx 1 1 VaultPluginTemplate

When we attempt to use http://localhost/PluginServiceTemplate/ ... plate.asmx to configure the plugin, no messages are returned. e.g. we think that UpdateVaultConnectionInformation should return the message "Successfully updated Server, User, and Password." Also the Web.Config file is not being created/updated. If we manually modify Web.Config the new information is reflected in our diagnostic messages in OnEndTx.

Can you help us?

Post Reply