16

継続的インテグレーション環境で構成変換を利用しようとしています。

TFSビルドエージェントに変換を実行するように指示する方法が必要です。構成変換ファイル(web.qa-release.config、web.production-release.configなど)を検出した後、それが機能することを期待していました。しかし、そうではありません。

適切な構成(qa-release、production-releaseなど)をビルドするTFSビルド定義があり、これらの定義内にビルドされる特定の.projファイルがあり、それらには環境固有のパラメーターが含まれています。

<PropertyGroup Condition=" '$(Configuration)'=='production-release' ">
    <TargetHost Condition=" '$(TargetHost)'=='' ">qa.web</TargetHost>
    ...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)'=='qa-release' ">
    <TargetHost Condition=" '$(TargetHost)'=='' ">production.web</TargetHost>
    ...
</PropertyGroup>

出力から、正しい構成が構築されていることがわかります。ここで、構成変換をトリガーする方法を学ぶ必要があります。ビルドの最後の.projに追加して、変換を開始し、個々の変換ファイルを吹き飛ばすことができるいくつかのホーカスポカスはありますか?

4

6 に答える 6

11

カスタムアクティビティを作成する代わりに、これを実現する別の方法を見つけました。ビルド中のWebアプリケーションのVisualStudioプロジェクトファイルを変更するだけです。

以下を追加します(「AfterBuild」ターゲットのプレースホルダーは、プロジェクトファイルの最後にあります)。

<Target Name="AfterBuild" Condition="$(IsAutoBuild)=='True'"> 
  <ItemGroup> 
         <DeleteAfterBuild Include="$(WebProjectOutputDir)\Web.*.config" /> 
  </ItemGroup> 
  <TransformXml Source="Web.config" Transform="$(ProjectConfigTransformFileName)" Destination="$(WebProjectOutputDir)\Web.config"/> 
  <Delete Files="@(DeleteAfterBuild)" />
</Target> 

/p:IsAutoBuild="True"次に、ビルド定義の「詳細」セクションにある「MSBuild引数」フィールドに追加する必要があります。

これにより、TFSがビルドを実行するときに、TFS2010がweb.configで変換を実行するように強制されます。

詳細については、KevinDalyのブログをご覧ください。

于 2011-02-10T17:59:18.127 に答える
6

私はついにこれを機能させることができました。私はTFS2008を使用していますが、MSBuild 4.0も使用しているので、うまくいくはずです。

まず、このインポートをTFSBuild.projに追加します。

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

次に、BeforeDropBuildターゲットを追加します。

<Target Name="BeforeDropBuild">
  <TransformXml Source="$(SolutionRoot)\MySite\Web.config"
    Transform="$(SolutionRoot)\MySite\Web.QA.config"
    Destination="$(OutDir)\_PublishedWebsites\MySite\Web.QA.config.transformed" />
</Target>

次に、Web.QA.config.transformedを必要な場所にコピーできます。

于 2010-05-12T02:00:16.353 に答える
6

Visual Studio 2010のWebサイトプロジェクトに追加されたweb.config変換機能は、コマンドラインおよびTFSビルドではデフォルトで無効になっています。

2つの比較的簡単な解決策があります。

オプション1:ビルド定義を編集し、[MSBuild引数]フィールドに以下を追加します。

/p:UseWPP_CopyWebApplication=true /p:PipelineDependsOnBuild=false

UseWPP_CopyWebApplicationにより、ビルド用に新しいWeb Publishing Pipeline(WPP)がアクティブ化されます。WPPはweb.config変換を実行し、.PDBファイルなどがbinフォルダーにコピーされるのをブロックするためにも使用できます。

オプション2:MSBuildとWPPの両方が完全に拡張可能です。プロジェクトと同じディレクトリに新しいXMLファイルを作成し、「。targets」拡張子を使用します(たとえば、ProjectName.custom.targets)。次のMSBuildコードをターゲットファイルに配置します。

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <UseWPP_CopyWebApplication>True</UseWPP_CopyWebApplication>
    <PipelineDependsOnBuild>False</PipelineDependsOnBuild>
  </PropertyGroup>
</Project>

ウェブサイトを右クリックして、[プロジェクトのアンロード]を選択します。アンロードされたプロジェクトを右クリックして、[編集]を選択します。プロジェクトファイルの一番下までスクロールして、次の行を探します。

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

これらの行は、C#とWebプロジェクトのビルドプロセスが接続される場所です。CSharpインポートの直前に、カスタムビルド拡張機能(ターゲットファイル)へのインポートを挿入します。

<Import Project="ProjectName.custom.targets"/>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

それだけです-あなたは行ってもいいです。MSBuildのカスタマイズ方法は、セットアップに少し手間がかかりますが、新しいターゲットファイルを使用してビルドプロセスに「フック」し、サーバーでのビルドの実行方法をより詳細に制御できるという利点があります。たとえば、タスクをフックしてCSSとJSの圧縮を実行できます。

また、「wpptargets」を確認することをお勧めします。「ProjectName.wpp.targets」という特定の名前で別のMSBuildファイルに名前を付けると、Webサイトの公開プロセス全体を制御できます。公開されたWebサイトの出力がコピーされるときに、これを使用して-vsdocjavascriptドキュメントファイルを削除します。

<ItemGroup>
  <ExcludeFromPackageFiles Include="Scripts\**\*-vsdoc.js;Resources\Scripts\**\-vsdoc.js">
    <FromTarget>Project</FromTarget>
  </ExcludeFromPackageFiles>
</ItemGroup>

とはいえ、ビルドから本番Web.configsを完全に除外したほうがよいでしょう。変換を本番デプロイメントマシンに直接配置し、PowerShellを使用してアプリケーションをデプロイするときに変換します。

于 2011-06-02T18:11:43.720 に答える
5

これがあなたにとってより簡単な答えです。:)

http://social.msdn.microsoft.com/Forums/en-US/tfsbuild/thread/d5c6cc7b-fbb1-4299-a8af-ef602bad8898/

リンクから(移動した場合/ 404 / etc):

これが私がこれを解決した方法です。重要なのは、Webサイトの* .csprojファイルを編集し、AfterBuildターゲットに以下を追加することでした(必ずその上に終了コメントを移動してください)。これは、TeamFoundationServerでのWebサイト構築プロジェクト用です。

<Target Name="AfterBuild">
    <TransformXml Condition="Exists('$(OutDir)\_PublishedWebsites\$(TargetName)')"
                  Source="Web.config"
                  Transform="$(ProjectConfigTransformFileName)"
                  Destination="$(OutDir)\_PublishedWebsites\$(TargetName)\Web.config" />
</Target>

web.debug.config、web.release.configなどが公開されないようにするには、各構成変換ファイルのプロパティウィンドウで[ビルドアクション]を[なし]に設定してください。メインのweb.configのみが「コンテンツ」の「ビルドアクション」を持つ必要があります

csprojファイルを編集する簡単な方法の1つは、VisualStudioGalleryから入手できるVisualStudio2010の「PowerCommandsforVisualStudio2010」または「ProductivityPowerTools」拡張機能をロードすることです。ロードしたら、ソリューション内のプロジェクトを右クリックして、[プロジェクトのアンロード]を選択するだけです。次に、もう一度右クリックして[編集...]を選択し、csprojファイルのXMLを直接編集します。次に、完了したら、もう一度右クリックして[プロジェクトの再読み込み]を選択します。

于 2011-03-10T03:36:00.173 に答える
1

実行する必要があるのは、TFSビルド定義内で使用する構成をセットアップすることだけです。

  1. GotoTeamExplorer>ビルド
  2. ビルド定義を編集します(または新しく作成します)
  3. 「プロセス」ステップの下に、「構築する構成」の設定があります。

私の場合、CI専用の構成をセットアップして、正しいweb.config変換を実行しました。「CI」変換ファイルが追加されていることを確認してください。準備が整っているはずです。

于 2010-05-11T14:21:10.263 に答える
1

WorkFlowでこれを行うには、カスタムアクティビティを作成する必要があります。ここにそれについてのかなり良い記事があります

この特定のアクティビティについては、アクティビティプロジェクトを作成し(.Net4クライアントプロファイルから.Net4変更) 、GACからMicrosoft.Build.FrameworkMicrosoft.Build.Utilities.v4.0を参照してから、Microsoft.Webを参照する必要があります。 .Publishing.Tasks from %programfiles%\ msbuild \ Microsoft \ VisualStudio \ v10.0 \ WebApplications(64bitシステムを使用している場合は%programfiles(x86)%)。

それが完了したら、次の2つのクラスを追加します。

まず、スタブがあります:

internal class BuildEngineStub : IBuildEngine
{
    public bool BuildProjectFile(string projectFileName, string[] targetNames, System.Collections.IDictionary globalProperties, System.Collections.IDictionary targetOutputs)
    {
        throw new NotImplementedException();
    }

    public int ColumnNumberOfTaskNode
    {
        get { throw new NotImplementedException(); }
    }

    public bool ContinueOnError
    {
        get { throw new NotImplementedException(); }
    }

    public int LineNumberOfTaskNode
    {
        get { throw new NotImplementedException(); }
    }

    public void LogCustomEvent(CustomBuildEventArgs e)
    {
    }

    public void LogErrorEvent(BuildErrorEventArgs e)
    {
    }

    public void LogMessageEvent(BuildMessageEventArgs e)
    {
    }

    public void LogWarningEvent(BuildWarningEventArgs e)
    {
    }

    public string ProjectFileOfTaskNode
    {
        get { throw new NotImplementedException(); }
    }
}

次に、それ自体がアクティビティクラスになります。

[BuildActivity(HostEnvironmentOption.Agent)]
public sealed class WebConfigTransform : CodeActivity
{
    private const string WEB_CONFIG = "Web.config";
    private const string WEB_CONFIG_TRANSFORM_FORMAT = "Web.{0}.config";

    private IBuildEngine _buildEngine { get { return new BuildEngineStub(); } }

    [RequiredArgument]
    public InArgument<string> TransformationName { get; set; }
    [RequiredArgument]
    public InArgument<string> SourceFolder { get; set; }
    [RequiredArgument]
    public InArgument<string> DestinationFolder { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        var transformationName = context.GetValue(this.TransformationName);
        var sourceFolder = context.GetValue(this.SourceFolder);
        var destinationFolder = context.GetValue(this.DestinationFolder);

        var source = Path.Combine(sourceFolder, WEB_CONFIG);
        var destination = Path.Combine(destinationFolder, WEB_CONFIG);
        var destinationbackup = string.Format("{0}.bak", destination);
        var transform = Path.Combine(sourceFolder, string.Format(WEB_CONFIG_TRANSFORM_FORMAT, transformationName));

        if(!File.Exists(source))
            throw new ArgumentException("Web.config file doesn't exist in SourceFolder");
        if (!File.Exists(transform))
            throw new ArgumentException("Web.config transformation doesn't exist in SourceFolder");
        if (File.Exists(destination))
        {
            File.Copy(destination, destinationbackup);
            File.Delete(destination);
        }

        var transformation = new TransformXml();
        transformation.Source = new TaskItem(source);
        transformation.Destination = new TaskItem(destination);
        transformation.Transform = new TaskItem(transform);
        transformation.BuildEngine = _buildEngine;

        if (transformation.Execute())
        {
            File.Delete(destinationbackup);
        }
        else
        {
            File.Copy(destinationbackup, destination);
            File.Delete(destinationbackup);
        }
    }
}

BuildEngineStubの理由は、TransformXmlクラスがそれを使用してロギングを行うためです。

注意する必要があるのは、TransformXml.Execute関数が、ビルドプロセスが完了するまでソース構成ファイルをロックすることだけです。

于 2011-01-04T16:49:18.930 に答える