Accessing TeamCity artifacts in Build Step - msbuild

I have been playing around with TeamCity to get a CI environment up and running.
I started by following Troy Hunt's 'You're deploying wrong', which was very useful, however I wanted to split the packaging and deployment into 2 seperate steps, for the following reasons:
I wanted to pass some additional flags to msdeploy, which isnt possible (to m,y knowledge) by using the MSBuild Package and Deploy that Troy describes.
I can easily disable the Second Build Step i.e. deployment, if I ever need to build the package but not deploy it.
I wanted to use the -skip flag on msdeploy to prevent it from deleting certain folders, which again I couldn't find any method of doing without passing as an argument to the command line.
So, in my first MSBuild step I just have the parameters:
/P:Configuration=%env.Configuration%
/P:VisualStudioVersion=11.0
/P:IgnoreDeployManagedRuntimeVersion=True
And then I have a second Build Step that uses a command line build runner to execute the following msdeploy command:
"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:package="C:\ProgramData\JetBrains\TeamCity\system\artifacts\MyProject\%system.teamcity.buildConfName%\%teamcity.build.id%\MyProject.Web.csproj.zip" -dest:auto,ComputerName='https://devserver:8172/msdeploy.axd?site=MyWebsite',UserName='domain\username',Password='password',IncludeAcls='False',AuthType='Basic' -skip:objectName=dirPath,absolutePath=media$ -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -retryAttempts=2 -allowuntrusted
The problem with this is that apparently TeamCity doesnt publish the artifacts until all the build steps are complete, so therefore the Command Line process fails because the package zip file doesnt actually exist at that point.
I have read something about publishing artifacts whilst the Build is still in progress but that does seem like a bit of a hack.
Any advice would be greatly appreciated.

You would be better have two builds vs two build steps.
The first (Build A) would have 1 build step that would do the building then the second (Build B) would just do the deployment in one build step using the artifacts from the first.
So under the first configuration tab of build A, you would specify the artifacts that would need to be made available from the first build. You can then run the build and confirm that under the artifacts section everything you need is available. (These will show when build A has completed running).
Then under the dependencies section (Can't remember the exact name, and I'm away from my TC instance) of Build B you can set it up to use the artifacts of build A which would then be used for the deployment.
Once you have all that working, you could add a build trigger to have Build B run after a successfull execution of Build A, then if you at one point just wanted to run Build A, disable the trigger on build B or pause the Build B configuration which will stop the trigger from firing.

Related

Stop SSDT being published when MSBuild publish run

I have a ClickOnce project that I'm publishing on DevOps. I've set the MSBuild Arguments property for the WinForm solution's build stage in DevOps to /target:Publish in order to trigger the creation of all the ClickOnce files:
However, that solution also contains an SSDT project, and adding the /target:Publish setting appears to then cause the build process to try publish the SSDT too. That then fails with the error:
C:\Program Files (x86)\Microsoft Visual
Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets(1808,5):
error MSB4044: The "SqlPublishTask" task was not given a value for the
required parameter "SqlPublishProfilePath"
Presumably it's failing because there's no publish profile specified in a build parameter for the SSDT to use.
I don't want MSBuild to publish the DacPac to a server, I just want it to create the DacPac. How can I stop the /target:Publish triggering the SSDT publish, is there another build argument I can add to stop that happening?
Notes on what I tried so far to solve this, none of which has worked:
Read about the -target switch in the MS Build official docs in the MSBuild command-line reference and in the MSBuild targets section.
Looked at the code in the .csproj file to try and identify the 'Publish' sections - think Publish must also call Build.
Unticking Deploy for the SSDTs in the solution configuration in VS
Adding entries for False in the Release and Deployment configurations in the SSDT's .csproj file, and also setting that to false for the Debug configuration (as per this question)
Setting MSBuild to only publish one project using the MS Build arguments on DevOps (as per this answer)
Considered pulling the ClickOnce publish out into an entirely separate stage using Mage.exe as per this Walkthrough: Manually deploy a ClickOnce application
Tried to create a publish profile that doesn't actually publish, so that the publish stage can complete (was looking at this question for ideas on that and also the official documentation for SqlPackage.exe)
Eventually I solved the issue above a completely different way. Instead of getting MSBuild to do what I wanted it to, I instead split the solution configuration in two, with one stage for the databases and one for the WinForms project without the databases.
I then used two separate VS Build stages on DevOps with only the WinForms stage still having /target:Publish set.
I've written that up here, but would still like to know the answer to whether it's possible to tell MSBuild not to build the SSDTs when the target is set to Publish?

MSBuild - race condition while trying to build project references

I'm facing a weird issue while trying to build using MSBuild.
I'm using MSBuild to build a solution file with /m (parallel build) and BuildProjectReferences set to true.
Suppose I have A.vcxproj and B.vcxproj in the sln file with B having a project reference to A.
What happens is A project starts to build first and while its in the middle of compiling, B project starts to build in another process (since parallel builds) and it would invoke building A.
Now this causes a race condition because we have two processes trying to build the same project A and I would see access issues.
Ideally MSBuild should not invoke building B if A hasnt finished building or if it does invoke B then detect that A is still building and wait for it to finish.
None of this happens. Also, this happens only with MSBuild - doesnt happen if I try to build the solution file from VS2015 IDE.
Any idea why MSBuild behaves this way?
Finally found the solution to my problem
MSBuild expects that the project dependencies be added in two ways
1. In the vcxproj itself, add all the dependent projectreference
2. In the sln file too, define the projectdependencies.
The following VS blog actually states the opposite- For example - https://blogs.msdn.microsoft.com/vcblog/2010/02/16/project-settings-changes-with-vs2010/ states that projectdependencies and projectreference are analogous and use only one specifically projectreferences.
This may be true when you build using VS IDE but not for MSBuild. It needs the project dependencies to be defined on both ProjectReference and ProjectDependencies.
Hope this helps anyone who hit into the same issue as mine.

How to access artifacts folder after build in TFS online?

PreInfo: I have .net core web api (vs2015) mixed with just ordinary projects.
I have spent almost 2 days now to get this to work and search and tried everything I can think of, but I just cant for the live of me get the build and release in TFS online to play together.
The build (publish artifact step) says "Directory 'D:\a\1\a' is empty. Nothing will be added to build artifact 'drop'."
but the "run dot net" step says
"Published to D:\a\1\s\Operator\MobileService\root\MobileService\src\AMP.Operator.MobileService\bin\release\net452\win7-x64\publish"
...so it must be somewhere the release can pick it up but no matter what I try I can´t get it to be picked up.
Here is my build setup
dotnet run
publishing
And the realse with $(System.DefaultWorkingDirectory)/MobileService-Dev please note that I have tried every combo of $(build.artifactstagingdirectory) in the build to publish without luck but I sure this should point to the publishing folder for the build
I so hope somebody can point me to a solution. I just can´t understand how hard it is to make this work..
Within your build definition, I recommend adding a Copy Files step that will copy your the build artifacts from your msbuild results to the Build's Artifact Staging Directory before you run the Publish Artifact step.
Source Folder: $(Build.SourcesDirectory)
Contents: **\bin\$(BuildConfiguration)\**
Target Folder: $(Build.ArtifactStagingDirectory)
I am assuming that the $(BuildConfiguration) variable is custom to your definition and is probably Debug or Release. I am not sure what exactly the Run dotnet step does, but this build definition I setup published my build artifacts correctly. The Publish Build Artifacts step I'm running has the same steps as yours, except the only control option enabled is Enabled.
I am also running on TFS 2015 update 2.
You can download the files if you just want to take a look at them. Go to the build, click on the Artifacts tab, and then download as shown below:
You need to specify output argument (--output/-o) for dotnet publish command.
Arguments:
Publish -c $(BuildConfiguration) -o $(Build.ArtifactStagingDirectory)
BTW: You said “run dot net” step says “Published to D:\a\1\s....”, the files are in D:\a\1\s, no files in D:\a\1\a (one is s and another is a).

Can we put dependency among build steps in teamcity

In Project Configuration steps, is it possible to add a dependency among build steps. For instance I have 4 build steps added. running web configs of particular project before building the project and also doing a backup before publishing a site. I want to know if one of the build step fails then it should not run the remaining build steps. How can we acheive this.
step 1. Using command line : to copy and compress site before publish (if this step fails it should not run the remaining steps
step 2. using msbuild: Build project before publish
step 3. using command line : Publish project
In TeamCity build steps can only be executed sequentially. If one of build steps returns non zero exit code, TeamCity won't execute subsequent steps. Related issues from our tracker:
http://youtrack.jetbrains.com/issue/TW-17939
http://youtrack.jetbrains.com/issue/TW-13682

Running rsvars.bat before Teamcity build starts

I have a C++ Builder 2010 project that's being built using TeamCity. I noticed some strange errors and after reading up on them I understand that I have to set a few variables located in rsvars.bat. I would like the build script to execute the bat file to set up the environment before performing the actual build. How do I best accomplish this?
Can I just use a <exec /> command at the very beginning of the file or is there a better way?
One way would be to run wrap the build in a script that calls rsvars.bat AND build commands. That would make the variables survive during the execution of the build.
But since I use TeamCity I like it to be a real msbuild step and not msbuild wrapped in something else. I was thinking of having the buildscript setting the variables from rsvars.bat into Machine or User at the start of the build and then remove them at the end, not nice though.
I finally just went with just adding the configurations to the Build Agents environment configuration in TeamCity and keeping installation paths identical between agents.
You can create a new build step and then specify a custom build step order so a new build step will be the first one.
See Configuring Build Steps
Add them as Build Parameters -> Environment Variables (in the build configuration), straight forward and generally works. The build parameter/environment variables will be setup automatically as environment variables on the build agent running the job.
You can then make a template of the build and reuse it.
Assumes that the 'paths' are the same on all build agents, which is generally the case. If not your suggestion of doing it by build agent is the way to go.