Skip to content
This repository was archived by the owner on Apr 16, 2020. It is now read-only.

integrate with TFS MSBuildLogger #41

Closed
ctaggart opened this issue Jun 8, 2014 · 10 comments
Closed

integrate with TFS MSBuildLogger #41

ctaggart opened this issue Jun 8, 2014 · 10 comments
Milestone

Comments

@ctaggart
Copy link
Owner

ctaggart commented Jun 8, 2014

TFS uses Microsoft.TeamFoundation.Build.Server.Logger.dll to log build information to it's summary. The exact command used can be logged by printing the msbuild command line from the proj file like so:

<Target Name="BeforeBuild">
  <Message Importance="High" Text="CommandLine: $([System.Environment]::CommandLine)" />
 </Target>

An example from VisualStudio Online:

  CommandLine: "C:\Program Files (x86)\MSBuild\12.0\bin\amd64\MSBuild.exe" /nologo /noconsolelogger "C:\a\src\ConsoleApplication1\ConsoleApplication1.sln" /nr:False /fl /flp:"logfile=C:\a\src\ConsoleApplication1\ConsoleApplication1.log;encoding=Unicode;verbosity=normal" /p:SkipInvalidConfigurations=true  /m /p:OutDir="C:\a\bin\\" /p:VCBuildOverride="C:\a\src\ConsoleApplication1\ConsoleApplication1.sln.vsprops"  /dl:WorkflowCentralLogger,"C:\lightrail\Services\Mms\BuildProvisioner\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll";"Verbosity=Normal;BuildUri=vstfs:///Build/Build/364;IgnoreDuplicateProjects=False;InformationNodeId=8;TargetsNotLogged=GetNativeManifest,GetCopyToOutputDirectoryItems,GetTargetPath;TFSUrl=https://ctaggart.visualstudio.com/DefaultCollection;"*WorkflowForwardingLogger,"C:\lightrail\Services\Mms\BuildProvisioner\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll";"Verbosity=Normal;" /p:BuildId="55dc4330-5b8f-42ec-b139-b2ba48ba8fa6,vstfs:///Build/Build/364" /p:BuildLabel="ConsoleApplication1_20140608.3" /p:BuildTimestamp="Sun, 08 Jun 2014 21:18:39 GMT" /p:BuildDefinition="ConsoleApplication1"

PSake did this integration in 2013 and documented it in Using TFS with the WorkflowCentralLogger, PowerShell and PSAKE.

Adding the MSBuildLogger is similar to what is done for both AppVeyor and TeamCity in MSBuildHelper.fs.

@ctaggart ctaggart added this to the 0.4.0 milestone Jun 8, 2014
@ctaggart
Copy link
Owner Author

Will need to add support to FAKE for msbuild /dl in MSBuildHelper.fs, similar to what I did for fsprojects/FAKE#463.

  /distributedlogger:<central logger>*<forwarding logger>
                     Use this logger to log events from MSBuild, attaching a
                     different logger instance to each node. To specify
                     multiple loggers, specify each logger separately.
                     (Short form /dl)
                     The <logger> syntax is:
                       [<logger class>,]<logger assembly>[;<logger parameters>]
                     The <logger class> syntax is:
                       [<partial or full namespace>.]<logger class name>
                     The <logger assembly> syntax is:
                       {<assembly name>[,<strong name>] | <assembly file>}
                     The <logger parameters> are optional, and are passed
                     to the logger exactly as you typed them. (Short form: /l)
                     Examples:
                       /dl:XMLLogger,MyLogger,Version=1.0.2,Culture=neutral
                       /dl:MyLogger,C:\My.dll*ForwardingLogger,C:\Logger.dll

@baronfel
Copy link

baronfel commented Sep 4, 2014

Here I've got an example of what the distributed logger configuration strings look like coming out of some pending changes to FAKE I'm working on. I think this gets up most of the way there, but one potential worry is the syntax mentioned above. I'm not enforcing that as part of the MSBuildDistributedLoggerConfig type, but we may want to.

image

@ctaggart
Copy link
Owner Author

ctaggart commented Sep 4, 2014

The standard TFS 2013 builds have this for the /dl param:

/dl:WorkflowCentralLogger,"C:\Program Files\Microsoft Team Foundation Server 12.0\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll";"Verbosity=Normal;BuildUri=vstfs:///Build/Build/75634;IgnoreDuplicateProjects=False;InformationNodeId=236;TargetsNotLogged=GetNativeManifest,GetCopyToOutputDirectoryItems,GetTargetPath;TFSUrl=http://server:8080/tfs/teamproject;"*WorkflowForwardingLogger,"C:\Program Files\Microsoft Team Foundation Server 12.0\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll";"Verbosity=Normal;"

The params are separated by semicolons.

@ctaggart
Copy link
Owner Author

ctaggart commented Sep 4, 2014

Here is the code I'm using to create the distributed logger based on your FAKE fork.

Target "Build" (fun _ ->
//    !! "SourceLink.sln" |> MSBuildRelease "" "Rebuild" |> ignore

    build (fun defaults ->
        let rebuild = 
            { defaults with
                Targets = ["Rebuild"]
                Properties  = [ "Configuration", "Release" ]
            }
        if isTfsBuild then
            let tb = getTfsBuild()
            let buildUri = tb.Build.Uri.ToString()
            let tfsUrl = tb.Project.Tfs.Uri.ToString()

            // not sure what to use as the InformationNodeId. may be create a new one. not sure.
//            let nodeId = tb.Build.Information.AddActivityTracking
            let nodeId = tb.Build.Information.Nodes.[0].Id

            { rebuild with
                DistributedLoggers =
                    Some [
                        {
                            ClassName = Some "WorkflowCentralLogger"
                            AssemblyPath = "C:\Program Files\Microsoft Team Foundation Server 12.0\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll"
                            Parameters =
                                Some [
                                    "Verbosity", "Normal"
                                    "BuildUri", buildUri
                                    "IgnoreDuplicateProjects", "False"
                                    "InformationNodeId", sprintf "%d" nodeId
                                    "TargetsNotLogged", "GetNativeManifest,GetCopyToOutputDirectoryItems,GetTargetPath"
                                    "TFSUrl", tfsUrl
                                ]
                        }, 
                        Some {
                            ClassName = Some "WorkflowForwardingLogger"
                            AssemblyPath = "C:\Program Files\Microsoft Team Foundation Server 12.0\Tools\Microsoft.TeamFoundation.Build.Server.Logger.dll"
                            Parameters =
                                Some [
                                    "Verbosity", "Normal"
                                ]
                        }
                    ]
            }
        else
            rebuild
    ) "SourceLink.sln"
)

@ctaggart
Copy link
Owner Author

ctaggart commented Sep 5, 2014

The DistributedLogger FAKE pull request is: fsprojects/FAKE#536

@ctaggart
Copy link
Owner Author

ctaggart commented Oct 1, 2014

@baronfel Did you get this working with TFS On-Premise or Visual Studio Online? I'm curious if we should add more to SourceLink to make this easier. Do you have any final setups that can be shared?

@baronfel
Copy link

baronfel commented Oct 1, 2014

I sort of left this hanging. I have BuildTools building on TFS from FAKE now, so let me look into getting that configured using the DistributedLoggers above.

I could see a place for SourceLink.Fake or SourceLink.TFS to make getting the painful parts of that configuration, like the tfsUrl, InformationNodeId, etc. more automatic. Because honestly, no one wants to write all of that. Maybe the default members should be as above...?

@ctaggart
Copy link
Owner Author

ctaggart commented Oct 1, 2014

So I'm marking this as done, but the common code could definitely be moved into this project.

@ctaggart ctaggart closed this as completed Oct 1, 2014
@baronfel
Copy link

baronfel commented Oct 2, 2014

Hey, I think we need to reopen this to answer a couple questions.

  1. Should the Fake build activity check for the user from both the Federated and Windows credential stores? The BuildTools build I'm running right now bombs when creating the TfsBuild object because the tfsUser passed by the Fake build activity is null. This may be because we're using Windows credentials here.

  2. We need an an easier way to get the InformationNodeId passed to Fake. Right now the closest thing we can do is what you're doing above, which is grabbing the first one available. I've done some googling and the whole system seems very...murky. An alternative: If this can be parsed by the Fake build activity and then passed like the other TFS params, that would be easiest. It appears to be on that initial command line that you used to create this issue.

@ctaggart
Copy link
Owner Author

ctaggart commented Oct 2, 2014

  1. See TfsBuild.fs. When the user is null, it creates a TfsUser() which uses TfsClientCredentials() which uses Windows credentials by default. VisualStudio Online gets the TfsClientCredentials from the user passed in using SimpleWebToken. Both are supported. Hope that helps.

  2. Agreed, they tree of information nodes is a bit murky. I recommend using FSI to get a completed build and then inspect the node tree. I'll create a new issue to track figuring out the right informationnodeid.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants