I'm just about to setup teamcity for the first time on my own. Very nice and simple in most ways I have to say. However, I have one issue that I haven't manage to solve and find any information about.
When I wanna publish my artifacts I want to exclude some file types.
example:
%system.agent.work.dir%\trunk\Source\Projects\Webproject.Web/Controllers => Webproject.Web/Controllers
However, I don't want to copy all the .cs files in the folder. I just need the folder.
Is it possible to copy just the folder and not the content, and then copy what ever content I need? Or can I exclude files if I copy a directory?
You can add a MSBUILD target which prepares the "deployment" package for you. I have the following (may need some changes for your project):
<Target Name="Publish" DependsOnTargets="Build" Condition="'$(WebProjectOutputDir)'!=''">
<RemoveDir Directories="$(WebProjectOutputDir)" ContinueOnError="true" />
<!-- Log tasks -->
<Message Text="Publishing web application for $(MSBuildProjectName)" />
<Message Text="WebProjectOutputDir: $(WebProjectOutputDir)" />
<!-- Create the _PublishedWebsites\app\bin folder -->
<MakeDir Directories="$(WebProjectOutputDir)\bin" />
<!-- Copy build outputs to _PublishedWebsites\app\bin folder -->
<Copy SourceFiles="#(IntermediateAssembly)" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" />
<Copy SourceFiles="#(AddModules)" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(IntermediateOutputPath)$(_SGenDllName)" DestinationFolder="$(WebProjectOutputDir)\%(Content.SubFolder)%(Content.RecursiveDir)" SkipUnchangedFiles="true" Condition="'$(_SGenDllCreated)'=='true'" />
<Copy SourceFiles="$(IntermediateOutputPath)$(TargetName).pdb" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" Condition="'$(_DebugSymbolsProduced)'=='true'" />
<Copy SourceFiles="#(DocFileItem)" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" Condition="'$(_DocumentationFileProduced)'=='true'" />
<Copy SourceFiles="#(IntermediateSatelliteAssembliesWithTargetPath)" DestinationFiles="#(IntermediateSatelliteAssembliesWithTargetPath->'$(WebProjectOutputDir)\bin\%(Culture)\$(TargetName).resources.dll')" SkipUnchangedFiles="true" />
<Copy SourceFiles="#(ReferenceComWrappersToCopyLocal); #(ResolvedIsolatedComModules); #(_DeploymentLooseManifestFile); #(NativeReferenceFile)" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" />
<!-- copy any referenced assemblies to _PublishedWebsites\app\bin folder -->
<Copy SourceFiles="#(ReferenceCopyLocalPaths)" DestinationFiles="#(ReferenceCopyLocalPaths->'$(WebProjectOutputDir)\bin\%(DestinationSubDirectory)%(Filename)%(Extension)')" SkipUnchangedFiles="true" />
<!-- Copy content files recursively to _PublishedWebsites\app\ folder -->
<Copy SourceFiles="#(Content)" DestinationFolder="$(WebProjectOutputDir)\%(Content.RelativeDir)" />
<!-- Copy items that have been marked to be copied to the bin folder -->
<Copy SourceFiles="#(_SourceItemsToCopyToOutputDirectory)" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" />
<Copy SourceFiles="#(_SourceItemsToCopyToOutputDirectoryAlways)" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="false" />
</Target>
So, in the TC build, I use the MSBUILD builder like this:
Targets: Rebuild;Publish
Command line parameters: /p:WebProjectOutputDir="%system.teamcity.build.workingDir%\Website"
You can then use the Website directory as your artifact.
Related
I'm trying to get my JS and CSS files to be automatically minified when publishing our Web App, but it only seems to work on a File System publish not a web deploy; using the target CopyAllFilesToSingleFolderForPackage in a .pubxml file.
I've tried running on different targets but the same result.
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\lib\AjaxMinTask.dll" />
<Target Name="CompressJsAndCss" AfterTargets="CopyAllFilesToSingleFolderForPackage">
<ItemGroup>
<JS Include="$(_PackageTempDir)\**\*.js" Exclude="$(_PackageTempDir)\**\*.min.js" />
<CSS Include="$(_PackageTempDir)\**\*.css" Exclude="$(_PackageTempDir)\**\*.min.css" />
</ItemGroup>
<Message Text="Compressing JavaScript and CSS files in $(PublishDir)..." Importance="high" />
<AjaxMin JsKnownGlobalNames="jQuery,$" JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".css" />
</Target>
I'd expect it to minify the files in the temporary package folder, but nothing happens.
So I've managed to solve the problem.
I had to find the right target and folders to do this on:
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\lib\AjaxMinTask.dll" />
<Target Name="CompressJsAndCss" AfterTargets="CopyAllFilesToSingleFolderForAspNetCompileMerge">
<ItemGroup>
<JS Include="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.js" Exclude="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.min.js" />
<CSS Include="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.css" Exclude="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.min.css" />
</ItemGroup>
<Message Text="Compressing JavaScript and CSS files in $(IntermediateOutputPath)..." Importance="high" />
<AjaxMin JsKnownGlobalNames="jQuery,$" JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".css" />
</Target>
Now after the first copy, it will minify the files and use those going forward
How to exclude a file from being copied during maven build process :
<copy todir="target/classes/META-INF/config" overwrite="true" failonerror="false">
<fileset dir="src/main/resources/" />
<!-- something like <fileset dir="src/main/resources/" excludes="fileA.properties" /> for excluding fileA.properties from being copied to the target folder -->
</copy>
I'm using Visual Studio 2013. I'm trying to publish a ClickOnce application from the command-line by passing /target:publish. However, I would like to do a few extra steps after MSBuild is done copying all the files to the publish folder. This is what I have come up so far:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksPath>$(SolutionDir)\.build</MSBuildCommunityTasksPath>
<MSBuildCommunityTasksLib>$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll</MSBuildCommunityTasksLib>
<ClickOnceBuildDirectory>$(ProjectDir)\bin\app.publish</ClickOnceBuildDirectory>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.targets" />
<UsingTask TaskName="FileUpdate" AssemblyFile="$(MSBuildCommunityTasksLib)" />
<Target Name="CustomPostPublishActions" AfterTargets="PublishBuild" >
<!-- Create directory -->
<MakeDir Directories="$(ProjectDir)..\Deploy\Client\Application Files" />
<!-- Copy published website to deployment location -->
<ItemGroup>
<_CopyItems Include="$(ClickOnceBuildDirectory)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(_CopyItems)" DestinationFolder="$(ProjectDir)..\Deploy\Client" />
<!-- Write publish.htm file for ClickOnce -->
<Copy SourceFiles="$(ProjectDir)\..\..\Build\publish.htm" DestinationFiles="$(ProjectDir)..\Deploy\Client\publish.htm" />
<FileUpdate Files="$(ProjectDir)..\Deploy\Client\publish.htm" Regex="{VERSION}" IgnoreCase="true" Multiline="true" Singleline="false" ReplacementText="$(ApplicationVersion)" />
</Target>
</Project>
Unfortunately, this is the order that the targets get run:
CustomPostPublishActions:
Creating directory "C:\MyProject\..\Deploy\Client\Application Files".
Copying file from "C:\MyProject\\bin\app.publish\DeploymentScheduler.exe" to "C:\MyProject\..\Deploy\Client\DeploymentScheduler.exe".
Copying file from "C:\MyProject\\..\..\Build\publish.htm" to "C:\MyProject\..\Deploy\Client\publish.htm".
Updating File "C:\MyProject\..\Deploy\Client\publish.htm".
_CopyFilesToPublishFolder:
Creating directory "bin\app.publish\Application Files\MyApplication_1_0_0_0".
Copying file from "bin\MyProject.exe.manifest" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.exe.manifest".
Copying file from "bin\app.publish\MyProject.exe" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.exe.deploy".
Copying file from "app.config" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.exe.config.deploy".
Copying file from "obj\Debug\MyProject.pdb" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.pdb.deploy".
1>Done Building Project
Basically, how do I get my target "CustomPostPublishActions" to run AFTER "_CopyFilesToPublishFolder"? Is it even possible? Any help is really appreciated!
There are predefined targets that can be overwritten to run before or after publish, update your script like this:
<Target Name="AfterPublish">
<!-- Create directory -->
<MakeDir Directories="$(ProjectDir)..\Deploy\Client\Application Files" />
<!-- Copy published website to deployment location -->
<ItemGroup>
<_CopyItems Include="$(ClickOnceBuildDirectory)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(_CopyItems)" DestinationFolder="$(ProjectDir)..\Deploy\Client" />
<!-- Write publish.htm file for ClickOnce -->
<Copy SourceFiles="$(ProjectDir)\..\..\Build\publish.htm" DestinationFiles="$(ProjectDir)..\Deploy\Client\publish.htm" />
<FileUpdate Files="$(ProjectDir)..\Deploy\Client\publish.htm" Regex="{VERSION}" IgnoreCase="true" Multiline="true" Singleline="false" ReplacementText="$(ApplicationVersion)" />
</Target>
This link will give you an idea of the existing overridable targets and how you can work with them.
My WPF application is deployed with ClickOnce.
In Visual Studio I open "Project properties / Publish".
There I have:
Publish location
Publish URL
Version
Signature
The problem is, that I have to publish every version for test and production.
The difference between them are properties publish location and publish URL. Currently I have to execute the process twice, while changing the values before publishing for production.
So the result of pressing publish is a folder containing folder "ApplicationFiles", the application manifest file and a setup.exe.
Then i decided to automate this process using NANT.
I build/publish the application first for testing (here i set the .csproj file location, publish folder and application varsion)
<target name="BuildTestApplication" depends="Clean" description="Build">
<echo message="Building..." />
<exec program="${msbuildExe}" workingdir="." verbose="true">
<arg value="${projectFile}" />
<arg value="/target:Clean;Publish" />
<arg value="/p:PublishDir=${testPublishFolder}" />
<arg value="/p:ApplicationVersion=${version}" />
<arg value="/p:Publisher="${publisherName}"" />
</exec>
<echo message="Built" />
</target>
With this I found out that build does not set the publisher. Plus I need to change the provider URL, since the application is also installed via internet (different URLs for test and production). So i did:
<target name="UpdateTestApplication" depends="BuildTestApplication" description="Update">
<echo message="Updating..." />
<exec program="${mageExe}" workingdir="." verbose="true">
<arg value="-Update" />
<arg value="${testPublishFolder}/EdpClient.application" />
<arg value="-ProviderUrl" />
<arg value=""${testPublishUrl}"" />
<arg value="-Publisher" />
<arg value=""${publisherName}"" />
</exec>
<echo message="Updated" />
</target>
With this I have updated the application manifest file with correct values (Publisher and ProviderUrl)...
I do the same for production build, meaning i build the application to another folder and update it with different ProviderUrl and add Publisher, since it has to be included in every mage update...
Now the problem is with setup.exe file.
Setup.exe is generated at build and it takes the values from the .csproj file.
Considering all of the above I have three issues:
1.
Is there a way of building the application with the correct parameters, so the setup.exe would contain the correct values?
2.
Also how would I update Assembly information (parameter version) before build? When publishing from VS i need to update it on "Probject properties / Application / Assembly Information"
3.
I noticed that when Publishing from VS the application manifest file is also generated in the "Application Files" folder, while publishing with MSBUILD it is not. Why is that?
Thank you in advance and best regards, no9
EDIT:
I fixed the problem #2 like so:
<!--UPDATE ASSEMBLY INFORMATION BEFORE BUILD-->
<target name="UpdateAssemblyInfo">
<asminfo output="${assemblyInfoFile}" language="CSharp">
<imports>
<import namespace="System" />
<import namespace="System.Reflection" />
<import namespace="System.Resources" />
<import namespace="System.Runtime.CompilerServices" />
<import namespace="System.Runtime.InteropServices" />
<import namespace="System.Windows" />
</imports>
<attributes>
<attribute type="AssemblyTitleAttribute" value="some value" />
<attribute type="AssemblyDescriptionAttribute" value="some value" />
<attribute type="AssemblyConfigurationAttribute" value="some value" />
<attribute type="AssemblyCompanyAttribute" value="some value" />
<attribute type="AssemblyProductAttribute" value="some value" />
<attribute type="AssemblyVersionAttribute" value="some value" />
<attribute type="AssemblyFileVersionAttribute" value="some value" />
<attribute type="AssemblyCopyrightAttribute" value="some value" />
<attribute type="AssemblyTrademarkAttribute" value="some value" />
<attribute type="AssemblyCultureAttribute" value="some value" />
<attribute type="CLSCompliantAttribute" value="boolean value" />
<attribute type="ComVisibleAttribute" value="boolean value" />
</attributes>
</asminfo>
<echo file="${assemblyInfoFile}" append="true">
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
</echo>
<echo message="Updated" />
</target>
Meaning I override Assembly.info file before build and add relevant values.
And the problem #3 like so:
<!--COPY APPLICATION MANIFEST TO APPLICATIONFILES FOLDER-->
<target name="CopyTestApplicationManifestToApplicationFilesFolder" depends="Dependency target name" description="Update">
<echo message="Copying..." />
<copy
file="source file"
tofile="target file" />
<echo message="Copied" />
</target>
I was able to create tasks that properly generated the assets you mentioned in your question (setup.exe,application folder, etc.) without having to explicitly sign manifest.
the "clean_and_publish_application" task does the following
Clean the project
Rebuild the project
Publish the project **Here i provide several parameters specifying my publish url, BootstrapperSDKPath,Application Version, and Application Revision
<target name="clean_and_publish_application" description="Build the application.">
<echo message="Clean the build directory"/>
<msbuild project ="${src.dir}\${target.assembly.name}.csproj">
<arg value="/property:Configuration=Debug;outdir=bin\Debug" />
<arg value="/t:clean" />
</msbuild>
<echo message="Rebuild the application"/>
<msbuild project ="${src.dir}\${target.assembly.name}.csproj">
<arg value="/property:Configuration=Debug;outdir=bin\Debug" />
<arg value="/t:rebuild" />
</msbuild>
<echo message="Publish the application"/>
<msbuild project ="${src.dir}\${target.assembly.name}.csproj">
<arg value="/p:publishurl=${publish.url};
GenerateBootstrapperSdkPath=
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\Bootstrapper\;
ApplicationVersion=${app.version};
ApplicationRevision=${app.revision}" />
<arg value="/t:publish" />
</msbuild>
</target>
The BootstrapperSdkPath property is required for the creation of the setup.exe file. I hard coded the location because it doesn't change. MSBuild is looking for a setup.bin file within that directory.
The ApplicationVersion property is formatted as for example 2.0.0.%2a
The ApplicationRevision property is formatted as a number for example 24 (these values are the Publish Version we see in visual studio. I never actually update the AssemplyInfo.cs file at all.)
Any property you see listed in the .csproj file can be passed as an argument for msbuild. I found this documentation very helpful MSBuild Command-Line Reference
The above task does everything you need EXCEPT actually copy the files to your publish url (Still looking for the answer for this). So I just manually copy all the files from the app.config directory the publish creates
<target name="copy_src">
<echo message="Copying app.config folder"/>
<copy todir="${publish.url}" overwrite="true" failonerror="true">
<fileset basedir="${src.dir}\${app.config.location}">
<include name="**" />
</fileset>
</copy>
</target>
I'm running these scripts in Team City. Because I used the publish target, I didn't have to worry about signing any manifests. Also, I use the msbuild task from the NAnt.Contrib.Tasks.dll which you can download here NAntContrib
is it possible to make nant run a publish on mvc project or a good old web application project
and after the publish make nant FTP the files to the web server
UPDATE: found the solution to the ftp problem
Nant ftp task thanks Paco
what i mean by publich
is there a command line application or nant task that can public like visual studio publish...
The visual studio publish command rebuilds your solution and then copies the files in the solution directory to a new directory. I use the following target to do almost the same:
<target name="copyToPublish">
<delete dir="${dir.publish}" />
<mkdir dir="${dir.publish}" />
<mkdir dir="${dir.publish}\wwwroot"/>
<copy todir="${dir.publish}\wwwroot" includeemptydirs="false">
<fileset basedir="${website.dir}">
<exclude name="**/*.cs"/>
<exclude name="**/*.pdb"/>
<exclude name="**/*.csproj*"/>
<exclude name="**/obj/**"/>
<include name="**/*.*"/>
</fileset>
</copy>
<mkdir dir="${dir.publish}\database"/>
<copy todir="${dir.publish}\database" includeemptydirs="false">
<fileset basedir="${dir.databasescripts}">
<include name="**/*.sql" />
</fileset>
</copy>
<xmlpoke
file="${dir.publish}\wwwroot\Web.config"
xpath="/configuration/system.web/compilation/#debug"
value="false" />
<xmlpoke
file="${dir.publish}\wwwroot\Web.config"
xpath="/configuration/system.web/trace/#enabled"
value="false" />
<move file="${dir.publish}\wwwroot\Web.config" tofile="${dir.publish}\wwwroot\Release.config" overwrite="true" />
<delete file="${dir.publish}\wwwroot\Web.config" />
</target>
Before this target you have to run the normal build procedure of course.
There is a Ftp Task for nant.
Beside that, you have to create a script that copies the files and directories you need and the config files. I don't do it automatically, because I want to have control over database update scripts and changes in web.config.