tfscsprojbuild-servernightly-buildgated-checkin

TFS: How to validate if every file is checked-in?


We are working on several ASP.NET MVC C# projects within Visual Studio 2015 and Team Foundation Server 2013. Sometimes the NuGet upgrade process is a mess and some of the replaced files (mostly *.png, *.gif, *.ttf) have not been checked-in properly. What we have figured out so far: the check-in process gets into trouble, if directories should be removed and created in one step. You have to check-in twice. The problem is, if you don’t know about this and one of our developers retrieves the latest source, there are missing files. Visual Studio indicates that with a warning icon in Solution Explorer.

My question is: Is it possible to validate, if every file is present during gated-checkin or nightly-build on TFS which is linked in the csproj file? At least there should be a warning during build.

Hint: This is only a problem with files, which are not compiled (*.cs files) or do not have the setting “copy during build into output directory”. This happens e.g. with JS-files, which are bundled.

Final solution:

Write-Host "Check availability for all referenced files in all projects ..."

function Check-Files($directory, $files){
    if (!$directory.EndsWith("/")) { $directory = "$($directory)/" }
    ForEach($file in $files){
        if($file){
            Write-Host " Referenced file $($directory)$file"
            if(-not (Test-Path "$($directory)$($file)")){
                throw [System.IO.FileNotFoundException] "$($directory)$($file) not found."
            }
        }
    }
}

function CheckProjectFile($csprojFile){
    [xml]$projectContent = Get-Content $csprojFile
    Write-Host "Checking project: $($csprojFile) ..."
    $directory = Split-Path $csprojFile
    ForEach($itemGroup in $projectContent.Project.ItemGroup){
      Check-Files -files $itemGroup.Reference.HintPath -dir $directory
      Check-Files -files $itemGroup.Compile.Include -dir $directory
      Check-Files -files $itemGroup.None.Include -dir $directory
      Check-Files -files $itemGroup.Content.Include -dir $directory
      Check-Files -files $itemGroup.TypeScriptCompile.Include -dir $directory
      Check-Files -files $itemGroup.ProjectReference.Include -dir $directory
    }
}

$csprojFiles = Get-ChildItem -Path ./ -Recurse *.csproj | Select-Object -Property FullName
ForEach($file in $csprojFiles){
    CheckProjectFile($file.FullName)
}

I added the script file to my Team Project on TFS, changed my build definition, added the script directory to my "Source Settings" and included the script into "Pre-build script path". Done!


Solution

  • I created a small piece of powershell that you can execute as a step before building the solution.

    function Check-Files($files){
      ForEach($file in  $files){
        if($file){
          Write-Host "looking for $file"
          if(-not (Test-Path $file)){
            throw [System.IO.FileNotFoundException] "$file not found."
          }
        }
      }
    }
    
    [xml]$projectContent = Get-Content ./your.csproj
    ForEach($itemGroup in $projectContent.Project.ItemGroup){
      Check-Files -files $itemGroup.Reference.HintPath
      Check-Files -files $itemGroup.Compile.Include
      Check-Files -files $itemGroup.None.Include
      Check-Files -files $itemGroup.Content.Include
      Check-Files -files $itemGroup.TypeScriptCompile.Include
      Check-Files -files $itemGroup.ProjectReference.Include
    }
    

    Hope this helps you. Kind regards Jan