poniedziałek, 1 lutego 2010

Integracja SVN i BugNET krok drugi [PL]

Promuj

Tym razem w ramach rozwinięcia tematyki integracji SVN z systemem BugNET pokażę trochę bardziej zaawansowane rozwiązanie.

Integracja oparta jest o stabilną (nie beta i nie RC) wersję BugNET: 0.7.921. Niestety w tej wersji BugNet nie jest wyposażony w żadne mechanizmy (np. web-serwisy), które mogą zapewnić integrację (zgodnie z zapewnieniami autora BugNet jakieś web-serwisy pozwalające na integrację mają być dodane od wersji 0.8). Ten post proponuje, jaki web-serwis można dodać do BugNet by umożliwić integracje z SVN polegającą na automatycznym dodawaniu komentarza do problemu, po wykonaniu commit w subversion.

Informacja, którą chcemy umieścić jako komentarz w BugNet:

  • Nr rewizji

  • Autor

  • Data

  • Wiadomość danego commit’a

  • Lista katalogów w których nastąpiły zmiany

Konfiguracja i modyfikacja po stronie BugNET:

Dodajemy możliwość by BugNET miał web service obsługujący dodawanie komentarzy, czyli należy pobrać kod źródłowy, a następnie dodać następujące pliki do katalogu: BugNET-0.7.921\src\BugNET_WAP\Bugs:

  • CommentAdder.asmx

    <%@ WebService Language="C#" CodeBehind="CommentAdder.asmx.cs" Class="BugNET.Bugs.CommentAdder" %>
    

  • CommentAdder.asmx.cs

    using System;
    using System.Data;
    using System.Web;
    using System.Collections;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.ComponentModel;
    using BugNET.BusinessLogicLayer;
    
    namespace BugNET.Bugs
    {
      /// <summary>
      /// Summary description for CommentAdder
      /// </summary>
      [WebService(Namespace = "http://BugNetServer/")]
      [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
      [ToolboxItem(false)]
      public class CommentAdder : System.Web.Services.WebService
      {
        // Web Service method to add comment
        // bugid - issue identifier
     // comment - comment to be added
     // username - the name of the user that is adding the comment
        [WebMethod]
        public bool AddComment(int bugid, string comment, string username)
        {
          try
          {
         // creation of the new Comment object 
            Comment newComment = new Comment(bugid, comment.Trim(), username);
      // it is time to save the comment 
            newComment.Save();
            return true;
          }
          catch
          {
            return false;
          }
        }
      }
    }
    
    

Otrzymujemy więc następujący serwis:

Konfiguracja i modyfikacja po stronie Subversion (SVN)

Po stronie Subversion trzeba stworzyć pewien skrypt/program, który zostanie wykonany po commit’cie (czyli należy dodać tzw. Post-commit Hook), można to zrobić wieloma sposobami, ja wykorzystam oprogramowanie Captain Hook for Subversion, by stworzyć (w C#) odpowiednią aplikację dodającą komentarz. W tym celu należy zaimplementować klasę dziedziczącą po: PostCommitHook

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Net.Mail;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using CaptainHook.Subversion;
using CaptainHook.Subversion.Hook;

namespace Hook.Plugins
{
  public class PostCommitBugnetLink: PostCommitHook
  {
    /// <summary>
    /// Handles the post commit hook by sending out an email.
    /// </summary>
    /// <param name="commitInfo">commit information prepared by Captain Hook</param>
    protected override bool HandleHookEvent( IRevisionInfo commitInfo )
    {
      //creating a list of changed directories during commit:
      string[] changedDirectories = this.HostApplication.SubversionApplication.GetChangedDirectories( commitInfo.Revision );
      string modifiedPaths = string.Empty;
      if ( changedDirectories != null && changedDirectories.Length > 0 )
      {
     //each changed directory is in new line, separated by <br />
        modifiedPaths = String.Join( Environment.NewLine + "<br/>", changedDirectories ); 
      }

      // message to be stored as comment to particular issue 
      string message = String.Format( "<p>Rev: <strong>{0}</strong>, author: <strong>{1}</strong> date:{2}</p>" +
        "<p>SVN log message:</p>" +
        "<p><span class=\"Code\">{3}</span></p>" +
        "<p>Modified paths:</p>" +
        "<p><span class=\"Code\">{4}</span></p>",
        commitInfo.Revision, 
        commitInfo.Author, 
        commitInfo.DateStamp, 
        commitInfo.LogMessage.Replace(Environment.NewLine,Environment.NewLine+"<br/>"), 
        modifiedPaths );

      // comment should is added by particular use
   // in this example the user name is taken from application settings
   // the setting name is bugnet user
      string bugnetuser = ConfigurationManager.AppSettings[ "bugnetuser" ];
   // if bugnetuser setting is empty or null (not set) we can utilise the "admin"  user
      if ( String.IsNullOrEmpty( bugnetuser ) )
        bugnetuser = "admin";
      int bugid = 0;
      // now it is time to call BugNet web service to establish a connection
      BugNetLink.BugNETCommentAdder.CommentAdder remoteobj;
      try
      {
        remoteobj = new BugNetLink.BugNETCommentAdder.CommentAdder();
      }
      catch ( Exception ex )
      {
        System.Console.WriteLine( "Problem with creating remote object: " + ex.ToString() );
        return false;
      }

      // now it is time to get a bug identifier (ID) from commit message.
   // to do it we have to get number after string "Issue #:"
      try
      {
        Regex pattern = new Regex( "Issue #: [0-9]+" );
        string bugid_str = pattern.Match( commitInfo.LogMessage ).Value;
        pattern = new Regex( "[0-9]+" );
        bugid_str = pattern.Match( bugid_str ).Value;
        bugid = System.Convert.ToInt32( bugid_str );
      }
      catch
      {
        System.Console.WriteLine( "Bug ID not found" );
        return false;
      }
   // if the issue idetifier is found we can call a web service and add a comment
      if ( bugid > 0 )
      {
        try
        {
          return remoteobj.AddComment( bugid, message, bugnetuser ); 
        }
        catch ( Exception ex )
        {
          System.Console.WriteLine( "Problem with calling remote object: " + ex.ToString() );
        }
      }
      return false;//PostCommit hooks ignore this anyways.
    }

  }
}

Oczywiście należy pamiętać że wywołanie: BugNetLink.BugNETCommentAdder.CommentAdder, to odwołanie do referencji do serwisu CommentAdded.asmx (więc w projekcie w Visual Studio należy dodać odpowiednią referencję do web serwisu (przykład pokazujący jak to zrobić, choć dla innego web serwisu))

Konfiguracja po stronie repozytorium i TortoiseSVN:

Należy dodać odpowiednie właściwości tak jak to było opisane w poprzednim post’cie.

Podsumowanie

W niniejszym opisie wskazałem co należy zrobić, by informacja o wykonanym commit (w repozytorium) automatycznie była dodawana do informacji o pewnym problemie. Rozwiązanie te zdaje się być funkcjonalne, aczkolwiek można je pod paroma względami usprawnić i rozwiązać następujące problemy:

  • Trzeba ręcznie zmodyfikować kod BugNET (ma się to zmienić od nowej linii BugNet’a: 0.8)

  • Nie ma żadnego zabezpieczenia web serwisu,

  • Web serwis może się podszyć pod dowolnego użytkownika (być może jako nazwa użytkownika który dodaje komentarz, powinien być pobrana nazwa użytkownika wykonującego commit w SVN)

  • Commit’a można powiązać tylko z jednym "issue" (należałoby dać użytkownikowi możliwość wprowadzenia kilku numerów "issue” poprzez oddzielanie ich przecinkami

  • Opis problemu w komentarzu musi mieć konkretny format (np.: Issue #:1234) (ale w większości przypadków pilnuje tego TortoiseSVN



Promuj

1 komentarz:

Posty powiązane / Related posts