2011-11-30 2 views
20

Attualmente sto la creazione di un Team Foundation Server 2010 e ho trovato un comportamento molto strano quando si esegue una generazione:TFS2010 - di modifiche sbagliato che compare alla SourceGetVersion

La situazione ha spiegato: Abbiamo 2 Filiali

  • sviluppo
  • principali

Tutti gli sviluppatori check-in codice in solo il ramo di sviluppo. Una volta al giorno, il gestore di build unisce alcuni changeset al ramo principale. Sullo sviluppo, è in esecuzione una build continua ad ogni check in. Sul ramo principale, una volta al giorno (di notte) viene attivata una build.

Supponiamo ora che i gruppi di modifiche 1-100 vengano uniti nel ramo principale alle 17:00, fornendo il gruppo di modifiche 101 come operazione di unione. Alcuni sviluppatori controllano i changeset 102-106 dopo le 5 nella sezione Sviluppo. Ora alle 23:00, la build giornaliera viene automaticamente attivata e viene eseguita sul ramo principale. L'ultima di modifiche del ramo principale è changeset 101. Tuttavia, i dettagli Costruire mostra changeset 106:

enter image description here

potevo immaginare che questo comportamento è destinato, perché se si estrae changeset 106 sul ramo principale, in effetti otterrai il contenuto del changeset 101. Ma sarebbe molto più leggibile se questo riepilogo di Build mostrasse il numero corretto.

Domanda 1: Esiste un modo per manipolare l'output delle informazioni SourceGetVersion? Forse attraverso il modello di processo di costruzione?

Il secondo scenario, in cui il TFS si comporta in modo strano è ancora peggio: Quando la coda una nuova build, v'è la possibilità di inserire il parametro "Acquista ora", come mostrato nella figura seguente:

enter image description here

Se ora clicco su "coda", la build viene attivato e di nuovo dettaglio accumulo emette il changeset 106 anche se ho impostato appositamente per ottenere changeset 76.

domanda 2: si tratta di un bug? C'è un hotfix o qualcosa per risolvere questo problema? O c'è qualche indicatore di opzione che deve essere impostato?

Spero che qualcuno ne sappia di più. Non credo davvero che questo sia un bug, perché è una funzionalità così vitale che altre persone devono averlo incontrato prima.

Grazie per qualsiasi aiuto !! Christian

EDIT 1

La struttura delle cartelle del progetto Team è:

$ ProjectName

  • BuildProcessTemplates
  • Documentazione
  • SourceCode
    • Sviluppo < - questo è un ramo
      • 3rdParty
      • Fonte
    • principale < - questo è un ramo
      • 3rdParty
      • Fonte

La build tira solo il ramo Principale e tutto quello che si trova sotto.

EDIT 2

Ecco una foto della scheda Area di lavoro nella definizione di compilazione: enter image description here

+0

1) È possibile fornire ulteriori dettagli sulla "modifica della proprietà SourceGetVersion"? Che cosa vuoi fare? 2) Al momento non ho accesso al codice sorgente per vedere cosa è successo in questo scenario, ma la build ottiene la versione corretta e mostra il numero di changeset "sbagliato", oppure la build ottiene la versione sbagliata? –

+0

@DuatLe - Manipolando intendo cambiare il numero che emette, cioè sostituire la "copia innescata di ... per il changeset 106" con "... per il changeset 101". Il codice sorgente in realtà scaricato sembra essere corretto. Sta solo mostrando quello sbagliato. All'interno del database sul server TFS, memorizza anche le informazioni sul changeset errate. – Christian

+0

La tua build tira solo il ramo Main dal controllo del codice sorgente o Main e Development? –

risposta

22

Infine ho scoperto che cosa sta succedendo:

In sostanza l'insieme di modifiche che possono essere visto nella mia foto 1 è sempre l'ultimo changeset dell'intera collezione di progetti . È la proprietà "SourceGetVersion" sull'oggetto "BuildDetails" di tipo "IBuildDetails".

credo che questo sia un bug che può essere aggirato: Se si modifica il BuildDetails.SourceGetVersion (che è una stringa) ad un altro valore, quindi la sintesi di build mostrerà la stringa aggiornata. Inoltre, viene quindi salvato correttamente nel database di raccolta.

Quello che ho fatto per aggiungere il numero corretto di changeset è che ho creato un'attività di build personalizzata che prende il ramo che dovrebbe essere compilato come parametro di input. Emette il changeset corretto. L'attività rileva il changeset corretto connettendosi al TFS e scaricando la cronologia. Quindi guarda tutti gli elementi nella cronologia e restituisce il numero più grande di changeset. Ecco il codice di tale attività:

using System.Activities; 
using System.Collections; 
using System.Net; 
using Microsoft.TeamFoundation.Client; 
using Microsoft.TeamFoundation.VersionControl.Client; 
using Microsoft.TeamFoundation.Build.Client; 

namespace SourceGetVersionActivity 
{ 
    [BuildActivity(HostEnvironmentOption.All)] 
    public sealed class SourceGetVersionActivity : CodeActivity<string> 
    { 
     // Define an activity input argument of type string 
     public InArgument<string> Branch { get; set; } 

     // If your activity returns a value, derive from CodeActivity<TResult> 
     // and return the value from the Execute method. 
     protected override string Execute(CodeActivityContext context) 
     { 
      // Obtain the runtime value of the Text input argument 
      string branch = context.GetValue(this.Branch); 

      ICredentials account = new NetworkCredential("Useranme", "password", "domain"); 

      // connect/authenticate with tfs 
      TeamFoundationServer tfs = new TeamFoundationServer("http://tfs:8080/tfs/CollectionName", account); 
      tfs.Authenticate(); 

      // get the version control service 
      VersionControlServer versionControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer)); 

      IEnumerable changesets = versionControl.QueryHistory(branch, VersionSpec.Latest, 0, RecursionType.Full, 
       null, null, null, int.MaxValue, false, false, false, false); 

      int maxVersion = 0; 

      foreach (Changeset c in changesets) 
      { 
       if (c.ChangesetId > maxVersion) 
       { 
        maxVersion = c.ChangesetId; 
       } 
      } 

      return string.Concat('C', maxVersion.ToString()); 
     } 
    } 
} 

Io chiamo questa attività il più presto possibile (dopo l'attività GetBuild).

Fondamentalmente nel BuildProcessTemplate ho aggiunto un "ramo" di argomento (stringa) che deve essere riempito con una stringa che punta alla cartella principale che si sta creando. L'attività personalizzata lo prende come input e genera una stringa che è l'id del changeset corretto. Il BuildDetail.La proprietà SourceGetVersion verrà quindi sostituita dall'ID changeset corretto.

Trovo davvero strano che nessun altro sembra aver riscontrato questo problema. Non sono riuscito a trovare nessuna persona su Internet con lo stesso problema. Ad ogni modo, spero che questa risposta aiuti qualcun altro anche in futuro.

EDIT - Scrivere il codice di cui sopra direttamente in Workflow Foundation:

Per ottenere l'insieme di modifiche corretto utilizzando il codice più compatto e di evitare attività personalizzate, è anche possibile utilizzare direttamente Workflow Foundation. Di seguito è riportato il "codice" (facendo esattamente ciò che viene fatto nel precedente codice C#):

enter image description here

(1) L'attività GetTeamProjectCollection ottiene la collezione attuale. Lo sto salvando nella variabile TeamProjectCollection (vedi in basso nella figura). Importante: la variabile deve essere definita all'interno di questa sequenza, se la si definisce in ambito esterno, si verificherà un errore: "Impossibile serializzare il tipo 'Microsoft.TeamFoundation.Client.TfsTeamProjectCollection'. Verificare che il tipo sia pubblico e che disponga di costruttore predefinito o descrittore di istanza. "

(2) Foreach "di modifiche" in "TeamProjectCollection.GetService (Of VersionControlServer) .QueryHistory (Branch, VersionSpec.Latest, 0, RecursionType.Full, niente, niente, niente, Integer.MaxValue, False, False, False) .Cast (Of Changeset)() " Il TypeArgument del ciclo Foreach è" Microsoft.TeamFoundation.VersionControl.Client.Changeset ". Questa espressione ottiene l'oggetto controllo versione dalla raccolta, chiama il metodo "QueryHistory" che restituisce un oggetto IEnumerable con tutti i changeset.

(3) Quindi stiamo iterando su tutti i changeset e guardando il changesetid. Quindi salvare il massimo ChangesetId alla variabile "maxId".

(4) Al termine, BuildDetails.SourceGetVersion = "C" + maxId.ToString(). La "C" indica che la versione è un changeset.

Spero che qualcuno trovi utile questo pezzo di "Codice"!

Christian

+1

+1 Ottima spiegazione di questo problema non ovvio. –

+2

Soluzione impressionante (e sì questo è un commento estraneo, ma la soluzione lo garantisce ... –

+2

Ottima spiegazione del problema e buone soluzioni, sebbene funzionino solo per le build del codice più recente. Non funzioneranno per build di Check-in Gated o per build personalizzate, in cui la versione in corso di realizzazione non è la più recente. – Ivan