Pergunta

Estou usando o CCNET em um projeto de exemplo com SVN como meu controle de origem.CCNET está configurado para criar uma compilação em cada check-in.CCNET usa MSBuild para construir o código-fonte.

Eu gostaria de usar o número de revisão mais recente para gerar AssemblyInfo.cs durante a compilação.Como posso recuperar a revisão mais recente do Subversion e usar o valor no CCNET?

Editar:Não estou usando o NAnt - apenas o MSBuild.

Foi útil?

Solução

CruiseControl.Net 1.4.4 agora tem um Rotulador de versão de montagem, que gera números de versão compatíveis com as propriedades do assembly .Net.

No meu projeto eu configurei como:

<labeller type="assemblyVersionLabeller" incrementOnFailure="true" major="1" minor="2"/>

(Embargo: assemblyVersionLabeller não começará a gerar rótulos baseados em revisão svn até que ocorra uma compilação real acionada por commit.)

e depois consumir isso dos meus projetos MSBuild com MSBuildCommunityTasks.AssemblyInfo :

<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<Target Name="BeforeBuild">
  <AssemblyInfo Condition="'$(CCNetLabel)' != ''" CodeLanguage="CS" OutputFile="Properties\AssemblyInfo.cs" 
  AssemblyTitle="MyTitle" AssemblyCompany="MyCompany" AssemblyProduct="MyProduct"
  AssemblyCopyright="Copyright ©  2009" ComVisible="false" Guid="some-random-guid"
  AssemblyVersion="$(CCNetLabel)" AssemblyFileVersion="$(CCNetLabel)"/>
</Target>

Para fins de integridade, é igualmente fácil para projetos que usam NAnt em vez de MSBuild:

<target name="setversion" description="Sets the version number to CruiseControl.Net label.">
    <script language="C#">
        <references>
            <include name="System.dll" />
        </references>
        <imports>
            <import namespace="System.Text.RegularExpressions" />
        </imports>
        <code><![CDATA[
             [TaskName("setversion-task")]
             public class SetVersionTask : Task
             {
              protected override void ExecuteTask()
              {
               StreamReader reader = new StreamReader(Project.Properties["filename"]);
               string contents = reader.ReadToEnd();
               reader.Close();
               string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["CCNetLabel"] + "\")]";
               string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);
               StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
               writer.Write(newText);
               writer.Close();
              }
             }
             ]]>
        </code>
    </script>
    <foreach item="File" property="filename">
        <in>
            <items basedir="..">
                <include name="**\AssemblyInfo.cs"></include>
            </items>
        </in>
        <do>
            <setversion-task />
        </do>
    </foreach>
</target>

Outras dicas

Você tem basicamente duas opções.Ou você escreve um script simples que iniciará e analisará a saída de

svn.exe informações --revisão HEAD

para obter o número de revisão (então gerar AssemblyInfo.cs é bastante simples) ou apenas usar o plugin para CCNET.Aqui está:

Rotulador de revisão SVN é um plug -in para o CruiseControl.net que permite gerar etiquetas CruiseControl para suas construções, com base no número de revisão da sua cópia de trabalho de subversão.Isso pode ser personalizado com um prefixo e/ou números de versão maior/menor.

http://code.google.com/p/svnrevisionlabeller/

Prefiro a primeira opção porque tem apenas cerca de 20 linhas de código:

using System;
using System.Diagnostics;

namespace SvnRevisionNumberParserSample
{
    class Program
    {
        static void Main()
        {
            Process p = Process.Start(new ProcessStartInfo()
                {
                    FileName = @"C:\Program Files\SlikSvn\bin\svn.exe", // path to your svn.exe
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    Arguments = "info --revision HEAD",
                    WorkingDirectory = @"C:\MyProject" // path to your svn working copy
                });

            // command "svn.exe info --revision HEAD" will produce a few lines of output
            p.WaitForExit();

            // our line starts with "Revision: "
            while (!p.StandardOutput.EndOfStream)
            {
                string line = p.StandardOutput.ReadLine();
                if (line.StartsWith("Revision: "))
                {
                    string revision = line.Substring("Revision: ".Length);
                    Console.WriteLine(revision); // show revision number on screen                       
                    break;
                }
            }

            Console.Read();
        }
    }
}

Eu escrevi um arquivo de construção NAnt que lida com a análise de informações SVN e a criação de propriedades.Em seguida, uso esses valores de propriedade para diversas tarefas de construção, incluindo a definição do rótulo na construção.Eu uso esse alvo combinado com o SVN Revision Labeller mencionado por lubos hasko com ótimos resultados.

<target name="svninfo" description="get the svn checkout information">
    <property name="svn.infotempfile" value="${build.directory}\svninfo.txt" />
    <exec program="${svn.executable}" output="${svn.infotempfile}">
        <arg value="info" />
    </exec>
    <loadfile file="${svn.infotempfile}" property="svn.info" />
    <delete file="${svn.infotempfile}" />

    <property name="match" value="" />

    <regex pattern="URL: (?'match'.*)" input="${svn.info}" />
    <property name="svn.info.url" value="${match}"/>

    <regex pattern="Repository Root: (?'match'.*)" input="${svn.info}" />
    <property name="svn.info.repositoryroot" value="${match}"/>

    <regex pattern="Revision: (?'match'\d+)" input="${svn.info}" />
    <property name="svn.info.revision" value="${match}"/>

    <regex pattern="Last Changed Author: (?'match'\w+)" input="${svn.info}" />
    <property name="svn.info.lastchangedauthor" value="${match}"/>

    <echo message="URL: ${svn.info.url}" />
    <echo message="Repository Root: ${svn.info.repositoryroot}" />
    <echo message="Revision: ${svn.info.revision}" />
    <echo message="Last Changed Author: ${svn.info.lastchangedauthor}" />
</target>

eu encontrei esse projeto no código do Google.Isso é CCNET plugin para gerar o rótulo em CCNET.

O DLL é testado com CCNET 1.3 mas funciona com CCNET 1.4 para mim.Estou usando este plugin com sucesso para rotular minha construção.

Agora, passando para MSBuild...

Se você preferir fazer isso no MSBuild lado sobre o CCNet configuração, parece com o MSBuild Extensão de tarefas comunitárias SvnVersion tarefa pode resolver o problema.

Atualmente estou fazendo isso "manualmente" por meio de uma tarefa prebuild-exec, usando meu cmdnetsvnrev ferramenta, mas se alguém souber uma maneira melhor integrada ao ccnet de fazer isso, ficarei feliz em saber :-)

Personalizando arquivos csproj para gerar automaticamente AssemblyInfo.cs
http://www.codeproject.com/KB/dotnet/Customizing_csproj_files.aspx

Toda vez que criamos um novo projeto C#, o Visual Studio coloca o arquivo AssemblyInfo.cs para nós.O arquivo define os meta-dados da montagem, como sua versão, configuração ou produtor.

Encontrei a técnica acima para gerar automaticamente AssemblyInfo.cs usando MSBuild.Postarei amostra em breve.

Não tenho certeza se isso funciona com CCNET ou não, mas criei um Plug-in de versão SVN para o Incremento de versão de compilação projeto no CodePlex.Esta ferramenta é bastante flexível e pode ser configurada para criar automaticamente um número de versão para você usando a revisão svn.Não é necessário escrever nenhum código ou editar xml, então, sim!

Espero que isso ajude!

Minha abordagem é usar o plugin mencionado acima para ccnet e uma tarefa nant echo para gerar um VersionInfo.cs arquivo contendo nada além dos atributos da versão.Eu só tenho que incluir o VersionInfo.cs arquivo na compilação

A tarefa echo simplesmente gera a string que eu atribuo a um arquivo.

Se houver uma tarefa semelhante do MSBuild, você poderá usar a mesma abordagem.Aqui está a pequena tarefa que eu uso:

<target name="version" description="outputs version number to VersionInfo.cs">
  <echo file="${projectdir}/Properties/VersionInfo.cs">
    [assembly: System.Reflection.AssemblyVersion("$(CCNetLabel)")]
    [assembly: System.Reflection.AssemblyFileVersion("$(CCNetLabel)")]
  </echo>
</target>

Experimente isto:

<ItemGroup>
    <VersionInfoFile Include="VersionInfo.cs"/>
    <VersionAttributes>
        [assembly: System.Reflection.AssemblyVersion("${CCNetLabel}")]
        [assembly: System.Reflection.AssemblyFileVersion("${CCNetLabel}")]
    </VersionAttributes>
</ItemGroup>
<Target Name="WriteToFile">
    <WriteLinesToFile
        File="@(VersionInfoFile)"
        Lines="@(VersionAttributes)"
        Overwrite="true"/>
</Target>

Observe que não tenho muita intimidade com o MSBuild, então meu script provavelmente não funcionará imediatamente e precisará de correções...

Com base na solução Skolimas, atualizei o script NAnt para atualizar também o AssemblyFileVersion.Obrigado a Skolima pelo código!

<target name="setversion" description="Sets the version number to current label.">
        <script language="C#">
            <references>
                    <include name="System.dll" />
            </references>
            <imports>
                    <import namespace="System.Text.RegularExpressions" />
            </imports>
            <code><![CDATA[
                     [TaskName("setversion-task")]
                     public class SetVersionTask : Task
                     {
                      protected override void ExecuteTask()
                      {
                       StreamReader reader = new StreamReader(Project.Properties["filename"]);
                       string contents = reader.ReadToEnd();
                       reader.Close();                     
                       // replace assembly version
                       string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["label"] + "\")]";
                       contents = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);                                        
                       // replace assembly file version
                       replacement = "[assembly: AssemblyFileVersion(\"" + Project.Properties["label"] + "\")]";
                       contents = Regex.Replace(contents, @"\[assembly: AssemblyFileVersion\("".*""\)\]", replacement);                                        
                       StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
                       writer.Write(contents);
                       writer.Close();
                      }
                     }
                     ]]>
            </code>
        </script>
        <foreach item="File" property="filename">
            <in>
                    <items basedir="${srcDir}">
                            <include name="**\AssemblyInfo.cs"></include>
                    </items>
            </in>
            <do>
                    <setversion-task />
            </do>
        </foreach>
    </target>

Não tenho ideia de onde encontrei isso.Mas encontrei isso na internet "em algum lugar".

Isso atualiza todos os arquivos AssemblyInfo.cs antes que a compilação ocorra.

Funciona como um encanto.Todos os meus exe e dll aparecem como 1.2.3.333 (se "333" fosse a revisão SVN na época.) (E a ​​versão original no arquivo AssemblyInfo.cs estava listada como "1.2.3.0")


$(ProjectDir) (onde reside meu arquivo .sln)

$(SVNToolPath) (aponta para svn.exe)

são minhas variáveis ​​​​personalizadas, suas declarações/definições não estão definidas abaixo.


http://msbuildtasks.tigris.org/e/ouhttps://github.com/loresoft/msbuildtaskstem as tarefas ( FileUpdate e SvnVersion ).


  <Target Name="SubVersionBeforeBuildVersionTagItUp">

    <ItemGroup>
      <AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
    </ItemGroup>

    <SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
      <Output TaskParameter="Revision" PropertyName="MySubVersionRevision" />
    </SvnVersion>

    <FileUpdate Files="@(AssemblyInfoFiles)"
            Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
            ReplacementText="$1.$2.$3.$(MySubVersionRevision)" />
  </Target>

EDITAR ------------------------------------------------- -

O procedimento acima pode começar a falhar depois que o número de revisão do SVN atingir 65534 ou superior.

Ver:

Desligue o aviso CS1607

Aqui está a solução alternativa.

<FileUpdate Files="@(AssemblyInfoFiles)"
Regex="AssemblyFileVersion\(&quot;(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="AssemblyFileVersion(&quot;$1.$2.$3.$(SubVersionRevision)" />

O resultado disso deve ser:

No Windows/Explorer//Arquivo/Propriedades…….

A versão do assembly será 1.0.0.0.

A versão do arquivo será 1.0.0.333 se 333 for a revisão do SVN.

Tome cuidado.A estrutura usada para números de compilação é curta, então você tem um limite de quão alto sua revisão pode ir.

No nosso caso, já ultrapassamos o limite.

Se você tentar inserir o número de compilação 99.99.99.599999, a propriedade da versão do arquivo sairá como 99.99.99.10175.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top