Azure DevOps - Collect several statistics from your az DevOps Organizations using PowerShell

%3CLINGO-SUB%20id%3D%22lingo-sub-2232698%22%20slang%3D%22en-US%22%3EAzure%20DevOps%20-%20Collect%20several%20statistics%20from%20your%20az%20DevOps%20Organizations%20using%20PowerShell%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2232698%22%20slang%3D%22en-US%22%3E%3CP%3EI%20published%20some%20other%20PowerShell%20scripts%20to%20manage%20or%20follow%20Azure%20DevOps%20platform%3A%3C%2FP%3E%3CUL%3E%3CLI%3E%3CSTRONG%3E%3CA%20title%3D%22Azure%20DevOps%20-%20How%20to%20collect%20all%20accounts%20from%20Organization%20using%20PowerShell%22%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fazure-devops%2Fazure-devops-how-to-collect-all-accounts-from-organization-using%2Fm-p%2F2120850%22%20target%3D%22_blank%22%3EAzure%20DevOps%20-%20How%20to%20collect%20all%20accounts%20from%20Organization%20using%20PowerShell%3C%2FA%3E%3C%2FSTRONG%3E%3C%2FLI%3E%3CLI%3E%3CSTRONG%3E%3CA%20title%3D%22Azure%20DevOps%20-%20Send%20an%20email%20to%20each%20Project%20Administrator%20with%20Account%20listed%20into%20using%20PowerShell%22%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fazure-devops%2Fazure-devops-send-an-email-to-each-project-administrator-with%2Fm-p%2F2193427%22%20target%3D%22_blank%22%3EAzure%20DevOps%20-%20Send%20an%20email%20to%20each%20Project%20Administrator%20with%20Account%20listed%20into%20using%20PowerShell%3C%2FA%3E%3C%2FSTRONG%3E%3C%2FLI%3E%3C%2FUL%3E%3CP%3EBut%20some%20other%20questions%20are%20opened%20immediately%3A%3C%2FP%3E%3CUL%3E%3CLI%3EWhat%20is%20the%20usage%20of%20our%20Azure%20DevOps%20platform%3F%3C%2FLI%3E%3CLI%3ECan%20we%20confirm%20the%20success%20or%20fail%20from%20usage%20point%20of%20view%3F%3C%2FLI%3E%3CLI%3EWhat%20is%20the%20maturity%20of%20my%20developer%20population%20related%20to%20DevOps%20(Repos%2C%20branches%2C%20pipelines%2C%20tests%2C%20%E2%80%A6)%20%3F%3C%2FLI%3E%3CLI%3EWhat%20is%20the%20volume%20of%20user%20stories%20per%20type%2C%20with%20specific%20focus%20on%20current%20and%20previous%20years%20%3F%3C%2FLI%3E%3CLI%3E%E2%80%A6%26nbsp%3B%3C%2FLI%3E%3C%2FUL%3E%3CP%3ESo%2C%20this%20script%20will%20help%20you%20to%20have%20information%20responding%20to%20some%20of%20those%20questions%20and%20much%20more.%3C%2FP%3E%3CP%3EIt's%20easy%20to%20read%20and%20adapt%2C%20based%20on%20Azure%20DevOps%20API%20proposed%20by%20Microsoft.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%23Installation%20Azure%20CLI%3A%20https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fcli%2Fazure%2Finstall-azure-cli-windows%3Fview%3Dazure-cli-latest%26amp%3Btabs%3Dazure-powershell%0A%23Invoke-WebRequest%20-Uri%20https%3A%2F%2Faka.ms%2Finstallazurecliwindows%20-OutFile%20.%5CAzureCLI.msi%3B%20Start-Process%20msiexec.exe%20-Wait%20-ArgumentList%20'%2FI%20AzureCLI.msi%20%2Fquiet'%3B%20rm%20.%5CAzureCLI.msi%0A%23Activation%20Az%20DevOps%3A%20az%20devops%20configure%20--defaults%20organization%3D%24Organization%0A%0A%23region%20%20--%20%20Customized%20Script%20Settings%20(need%20to%20be%20reviewed)%20---%0A%23%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20%2F%20Parameters%20to%20Adapt%20%5C%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20%0A%5Bstring%5D%24GlobalPATForAllORganizations%3D%20%22YourPersonalAccessTokenIfGlobalone%22%0A%5Bstring%5D%24JSonStatsFolderPath%20%3D%20%22C%3A%5CDEVOPSSTATISTICS%22%0A%23%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20%5C%20Parameters%20to%20Adapt%20%2F%20%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%20%0A%23endregion%0A%0A%23region%20--%20%20Internal%20Script%20Settings%20%20---%0A%0A%24OrganizationList%20%3D%20%40()%0A%5Bstring%5D%24PAT%20%3D%20%22%22%0A%5Bstring%5D%24OrganizationName%20%3D%20%22%22%0A%5Bstring%5D%24Organization%20%3D%20%22%22%0A%5Bstring%5D%24ProjectStatisticsJSonFilePath%20%3D%20%22%22%20%0A%5Bstring%5D%24ProjectListJSonFilePath%20%3D%20%22%22%0A%24DataRefreshDate%20%3D%20Get-Date%20-Format%20%22yyyy-MM-dd%22%0A%5Bstring%5D%24ProjectProcessModelProperty%20%3D%20%22%22%0A%5Bstring%5D%24ProjectProcessModelIDProperty%20%3D%20%22%22%0A%5Bint%5D%24TotalProjectPerOrganization%20%3D%200%0A%5Bint%5D%24ProjectInProgress%20%3D%200%0A%5Bint%5D%24TotalRepositoriesPerProject%20%3D%200%0A%5Bint%5D%24TotalBranchesPerProject%20%3D%200%0A%5Bint%5D%24TotalWorkItemsPerProject%20%3D%200%0A%5Bint%5D%24TotalOtherItems%20%3D%200%20%0A%5Bint%5D%24TotalWorkItemsPerProjectCurrentYear%20%3D%200%0A%5Bint%5D%24TotalOtherItemsCurrentYear%20%3D%200%0A%5Bint%5D%24TotalWorkItemsPerProjectPreviousYear%20%3D%200%0A%5Bint%5D%24TotalOtherItemsPreviousYear%20%3D%200%0A%5Bint%5D%24CurrentYear%20%3D%200%0A%5Bint%5D%24PreviousYear%20%3D%200%0A%5Bstring%5D%24PreviousyearStart%20%3D%20%22%22%0A%5Bstring%5D%24PreviousyearEnd%20%3D%20%22%22%0A%24StandardWorkItems%3D%20%22Bug%22%2C%20%22Epic%22%2C%20%22Feature%22%2C%20%22Issue%22%2C%20%22Task%22%2C%20%22Test%20Case%22%2C%20%22User%20Story%22%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%5Bstring%5D%24RepoBranchDetails%20%3D%20%22%22%0A%5Bstring%5D%24WorkItemCountPerType%20%3D%20%22%22%0A%5Bstring%5D%24MyWiQlCommand%20%3D%20%22%22%0A%5Bstring%5D%24uriAccount%20%3D%20%22%22%0A%5Bint%5D%24PipelineCount%20%3D%200%0A%5Bint%5D%24TestPlansCount%20%3D%200%0A%24ProjectStatisticsOveralOrganization%20%3D%20%40()%0A%5Bstring%5D%24ProjectStatisticsOveralOragnizationJSonFilePath%20%3D%20%22%24JSonStatsFolderPath%5CDevOps-ProjectStatistics.json%22%0A%23endregion%0A%0A%23region%20--%20%20Each%20Az%20DevOps%20Organization%20%20--%0A%23organization1%0A%24PAT%20%3D%20%24GlobalPATForAllORganizations%20%23https%3A%2F%2Fdev.azure.com%2Forganization1%2F_usersSettings%2Ftokens%0A%24OrganizationName%20%3D%20%22organization1%22%0A%24OrganizationWithPAT%20%3D%20New-Object%20PSObject%20-property%20%40%7BOrganizationName%3D%24OrganizationName%3BOrganizationPAT%3D%24PAT%7D%0A%24OrganizationList%20%2B%3D%20%24OrganizationWithPAT%0A%23organization2%0A%24PAT%20%3D%20%24GlobalPATForAllORganizations%20%23https%3A%2F%2Fdev.azure.com%2Forganization2%2F_usersSettings%2Ftokens%0A%24OrganizationName%20%3D%20%22organization2%22%0A%24OrganizationWithPAT%20%3D%20New-Object%20PSObject%20-property%20%40%7BOrganizationName%3D%24OrganizationName%3BOrganizationPAT%3D%24PAT%7D%0A%24OrganizationList%20%2B%3D%20%24OrganizationWithPAT%0A%23organization3%0A%24PAT%20%3D%20%24GlobalPATForAllORganizations%20%23https%3A%2F%2Fdev.azure.com%2Forganization3%2F_usersSettings%2Ftokens%0A%24OrganizationName%20%3D%20%22organization3%22%0A%24OrganizationWithPAT%20%3D%20New-Object%20PSObject%20-property%20%40%7BOrganizationName%3D%24OrganizationName%3BOrganizationPAT%3D%24PAT%7D%0A%24OrganizationList%20%2B%3D%20%24OrganizationWithPAT%0A%23endregion%0A%0Aforeach(%24MyOrganization%20in%20%24OrganizationList)%0A%7B%0A%20%20%20%20write-host%20%22%20--------------------------------------------------------------------%22%20-ForegroundColor%20White%20-BackgroundColor%20DarkYellow%0A%20%20%20%20write-host%20%22%20-----%20%20%20%20%20%20Organization%20%3A%22%2C%20%24MyOrganization.OrganizationName%20%2C%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20------%22%20-ForegroundColor%20White%20-BackgroundColor%20DarkYellow%0A%20%20%20%20write-host%20%22%20--------------------------------------------------------------------%22%20-ForegroundColor%20White%20-BackgroundColor%20DarkYellow%0A%20%20%20%20%24TotalProjectPerOrganization%20%3D%200%0A%20%20%20%20%24ProjectInProgress%20%3D%200%0A%20%20%20%20%24CurrentYear%20%3D%20%24((Get-Date).year)%0A%20%20%20%20%24PreviousYear%20%3D%20%24((Get-Date).year%20-%201)%0A%20%20%20%20%24AzureDevOpsAuthenicationHeader%20%3D%20%40%7BAuthorization%20%3D%20'Basic%20'%20%2B%20%5BConvert%5D%3A%3AToBase64String(%5BText.Encoding%5D%3A%3AASCII.GetBytes(%22%3A%24(%24MyOrganization.OrganizationPAT)%22))%20%7D%0A%20%24Organization%20%3D%20%22https%3A%2F%2Fdev.azure.com%2F%24(%24MyOrganization.OrganizationName)%2F%22%20%0A%20%24ProjectStatisticsPerOrganization%20%3D%20%40()%0A%20%24ProjectStatisticsJSonFilePath%20%3D%20%22%24JSonStatsFolderPath%5C%24(%24MyOrganization.OrganizationName)-ProjectStatistics.json%22%0A%20%20%20%20%24ProjectListJSonFilePath%20%3D%20%22%24JSonStatsFolderPath%5C%24(%24MyOrganization.OrganizationName)-ProjectList.json%22%0A%20echo%20%24(%24MyOrganization.OrganizationPAT)%20%7C%20az%20devops%20login%20--org%20%24Organization%0A%20az%20devops%20configure%20--defaults%20organization%3D%24Organization%0A%20%23%24allProjects%20%3D%20az%20devops%20project%20list%20--org%20%24Organization%20--top%20100%20%7C%20ConvertFrom-Json%20%7C%20Select-Object%20-ExpandProperty%20value%20%7C%20Sort-Object%20name%20%20%20%20%20%20%20%20%20%20%20%20%20%23Select%201st%20project%20to%20validate%20script%0A%20%23%24allProjects%20%3D%20az%20devops%20project%20list%20--org%20%24Organization%20--top%2010000%20%7C%20ConvertFrom-Json%20%7C%20Select-Object%20-ExpandProperty%20value%20%7C%20Where-Object%20name%20-eq%20%22MyProjectName%22%20%7C%20Sort-Object%20name%20%20%23Select%20filtered%20project%0A%20%24allProjects%20%3D%20az%20devops%20project%20list%20--org%20%24Organization%20--top%2010000%20%7C%20ConvertFrom-Json%20%7C%20Select-Object%20-ExpandProperty%20value%20%7C%20Sort-Object%20name%20%20%20%20%20%20%20%20%20%20%20%20%23Select%20all%20projects%0A%20%20%20%20%23%24allProjects%0A%20%23%24allProjects%20%7C%20ConvertTo-Json%20%7C%20Out-File%20-FilePath%20%24ProjectListJSonFilePath%20-Encoding%20UTF8%20%23If%20you%20want%20to%20save%20a%20copy%0A%20%20%20%20%24TotalProjectPerOrganization%20%3D%20%24allProjects.Count%0A%20%20%20%20foreach(%24myProject%20in%20%24allProjects)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24ProjectInProgress%20%2B%3D%201%0A%20%20%20%20%20%20%20%20%24TotalRepositoriesPerProject%20%3D%200%0A%20%20%24TotalWorkItemsPerProject%20%3D%200%0A%20%20%20%20%20%20%20%20%24TotalOtherItems%20%3D%200%0A%20%20%20%20%20%20%20%20%24TotalWorkItemsPerProjectCurrentYear%20%3D%200%0A%20%20%20%20%20%20%20%20%24TotalOtherItemsCurrentYear%20%3D%200%0A%20%20%20%20%20%20%20%20%24TotalWorkItemsPerProjectPreviousYear%20%3D%200%0A%20%20%20%20%20%20%20%20%24TotalOtherItemsPreviousYear%20%3D%200%0A%20%20%20%20%20%20%20%20%24TotalBranchesPerProject%20%3D%200%0A%20%20%20%20%20%20%20%20%24PipelineCount%20%3D%200%0A%20%20%20%20%20%20%20%20%24TestPlansCount%20%3D%200%0A%20%20%20%20%20%20%20%20%24RepoBranchDetails%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20%24WorkItemCountPerType%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20%24ProjectProcessModelProperty%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20%24ProjectProcessModelIDProperty%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20%24ProcessModelWIWithStates%20%3D%20%40()%0A%20%20%20%20%20%20%20%20write-host%20%22%20----------------------------------------------------------------------------------------------------%20%22%20-ForegroundColor%20Yellow%0A%20%20%20%20%20%20%20%20write-host%20%22%20--%20Project%20Name%3A%22%2C%20%24myProject.Name%2C%20%22%5B%22%2C%20%24ProjectInProgress%2C%20%22%20of%20%22%2C%20%24TotalProjectPerOrganization%2C%20%22%5D%20--%22%20-ForegroundColor%20Yellow%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20%26gt%3B%20Last%20Update%3A%22%2C%20%24myProject.lastUpdateTime%20-ForegroundColor%20DarkYellow%0A%20%20%20%20%20%20%20%20%23write-host%20%22%20%20%20%20%20%26gt%3B%20Project%20Description%3A%22%2C%20%24myProject.Description%20-ForegroundColor%20DarkYellow%0A%20%20%20%20%20%20%20%20write-host%20%22%20----------------------------------------------------------------------------------------------------%20%22%20-ForegroundColor%20Yellow%0A%20%20%20%20%20%20%20%20%23%20-------%20GET%20PROJECT%20PROCESS%20MODEL%20DETAILS%20-------%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20-%20-%20-%20-%20%22%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%20%22_apis%2Fprojects%2F%22%2B%20%24myProject.id%20%2B%22%2Fproperties%3Fapi-version%3D6.0-preview.1%22%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Get%20-ContentType%20%22application%2Fjson%22%0A%20%20%20%20%20%20%20%20%24ProjectProcessModelIDProperty%20%3D%20%24response.value.Where(%7B%24_.name%20-eq%20%22System.ProcessTemplateType%22%7D).value%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%20%22_apis%2Fwork%2Fprocesses%2F%7B%22%2B%20%24ProjectProcessModelIDProperty%20%2B%22%7D%3Fapi-version%3D6.0-preview.2%22%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Get%20-ContentType%20%22application%2Fjson%22%0A%20%20%20%20%20%20%20%20%24ProjectProcessModelProperty%20%3D%20%24response.name%20%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20Project%20Process%20Model%3A%22%2C%20%24ProjectProcessModelProperty%2C%20%22-ID%3A%22%2C%20%24ProjectProcessModelIDProperty%20-ForegroundColor%20Green%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%20%22_apis%2Fwork%2Fprocesses%2F%7B%22%2B%20%24ProjectProcessModelIDProperty%20%2B'%7D%2Fworkitemtypes%3F%24expand%3DStates%26amp%3Bapi-version%3D6.0-preview.2'%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Get%20-ContentType%20%22application%2Fjson%22%0A%20%20%20%20%20%20%20%20%24ProcessModelWIWithStatesTemp%20%3D%20%24response.value%0A%20%20%20%20%20%20%20%20foreach(%24myProcessModelWITypeWithStates%20in%20%24ProcessModelWIWithStatesTemp)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20%20%20%20-%20WI%20Type%3A%22%2C%20%24myProcessModelWITypeWithStates.Name%0A%20%20%20%20%20%20%20%20%20%20%20%20foreach(%24MyWIState%20in%20%24myProcessModelWITypeWithStates.states)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%26gt%3B%20WI%20Type%20States%3A%22%2C%20%24MyWIState.name%2C%20%22-%20Category%3A%22%2C%20%24MyWIState.stateCategory%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24ProcessModelWIWithStates%20%2B%3D%20New-Object%20-TypeName%20PSObject%20-Property%20%40%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Type%3D%24myProcessModelWITypeWithStates.Name%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Type_States%3D%24MyWIState.name%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Type_States_Category%3D%24MyWIState.stateCategory%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%24ProcessModelWIWithStates%20%3D%20%24ProcessModelWIWithStates%20%7C%20ConvertTo-Json%0A%20%20%20%20%20%20%20%20%23%20-------%20GET%20DETAILS%20FOR%20REPOSITORIES%20AND%20BRANCHES%20-------%0A%20%20%20%20%20%20%20%20%24ProjectRepositories%20%3D%20az%20repos%20list%20--org%20%24Organization%20--project%20%24myProject.Name%20%7C%20ConvertFrom-Json%0A%20%20%20%20%20%20%20%20%23%24ProjectRepositories%0A%20%20%20%20%20%20%20%20%24TotalRepositoriesPerProject%20%3D%20%24ProjectRepositories.Count%0A%20%20%20%20%20%20%20%20foreach(%24myRepository%20in%20%24ProjectRepositories)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20Repository%20Name%3A%22%2C%20%24myRepository.name%2C%20%22-%20ID%3A%22%2C%20%24myRepository.id%20-ForegroundColor%20Cyan%0A%20%20%20%20%20%20%20%20%20%20%20%20%24RepositoryBranches%20%3D%20az%20repos%20ref%20list%20--org%20%24Organization%20--project%20%24myProject.Name%20--repository%20%24myRepository.id%20%20%7C%20ConvertFrom-Json%0A%20%20%20%20%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20%20%20%20%26gt%3B%26gt%3B%26gt%3B%20Branch%20Total%3A%22%2C%20%24RepositoryBranches.count%20-ForegroundColor%20Cyan%0A%20%20%20%20%20%20%20%20%20%20%20%20%24TotalBranchesPerProject%20%2B%3D%20%24RepositoryBranches.count%0A%20%20%20%20%20%20%20%20%20%20%20%20%24RepoBranchDetails%20%2B%3D%20%22%5B%24(%24myRepository.name)%5D%3A%24(%24RepositoryBranches.count)%3B%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if(%24RepoBranchDetails.EndsWith(%22%3B%22))%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%24RepoBranchDetails%20%3D%20%24RepoBranchDetails.Substring(0%2C%24RepoBranchDetails.Length-1)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%23%20-------%20GET%20DETAILS%20FOR%20WORK%20ITEMS%20AND%20TYPES%20-------%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20-%20-%20-%20-%20TOTAL%20WORK%20ITEMS%20-%20-%20-%20-%20-%20%22%0A%20%20%20%20%20%20%20%20%24MyWorkItemPerType%20%3D%20%40()%0A%20%20%20%20%20%20%20%20%24MyWiQlCommand%20%3D%20%22Select%20%5BSystem.Id%5D%20FROM%20WorkItems%20WHERE%20%5BSystem.TeamProject%5D%3D'%24(%24myProject.Name)'%22%0A%20%20%20%20%20%20%20%20%24body%20%3D%20%40%7B%20query%20%3D%20%24MyWiQlCommand%20%7D%0A%20%20%20%20%20%20%20%20%24bodyJson%3D%40(%24body)%20%7C%20ConvertTo-Json%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%22_apis%2Fwit%2Fwiql%3Fapi-version%3D6.0%22%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Post%20-ContentType%20%22application%2Fjson%22%20-Body%20%24bodyJson%0A%20%20%20%20%20%20%20%20%24ProjectWorkItemsAPI%3D%20%24response.workItems%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20Work%20Items%20Total%3A%22%2C%20%24ProjectWorkItemsAPI.count%20-ForegroundColor%20Magenta%0A%20%20%20%20%20%20%20%20%24TotalWorkItemsPerProject%20%3D%20%24ProjectWorkItemsAPI.Count%0A%20%20%20%20%20%20%20%20%24TotalOtherItems%20%3D%20%24TotalWorkItemsPerProject%0A%20%20%20%20%20%20%20%20%23check%20for%20each%20Type%20of%20Work%20Item%0A%20%20%20%20%20%20%20%20%24MyWorkItemCount%20%3D%20New-Object%20PSObject%0A%20%20%20%20%20%20%20%20foreach(%24MyWorkItemType%20in%20%24StandardWorkItems)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24MyWiQlCommand%20%3D%20%22Select%20%20%5BSystem.Id%5D%20FROM%20WorkItems%20WHERE%20%5BSystem.TeamProject%5D%3D'%24(%24myProject.Name)'%20AND%20%5BSystem.WorkItemType%5D%20%3D%20'%24(%24MyWorkItemType)'%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%24body%20%3D%20%40%7B%20query%20%3D%20%24MyWiQlCommand%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24bodyJson%3D%40(%24body)%20%7C%20ConvertTo-Json%0A%20%20%20%20%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%22_apis%2Fwit%2Fwiql%3Fapi-version%3D6.0%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Post%20-ContentType%20%22application%2Fjson%22%20-Body%20%24bodyJson%0A%20%20%20%20%20%20%20%20%20%20%20%20%24ProjectWorkItemsAPI%3D%20%24response.workItems%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24ProjectWorkItemsAPI.count%20-gt%200)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20%20%20%20%20%20%20%20%26gt%3B%26gt%3B%26gt%3B%20WorkItems%20Type%20(API)%3A%22%2C%20%24MyWorkItemType%2C%20%22%20-%20Total%3A%22%2C%20%24ProjectWorkItemsAPI.count%20-ForegroundColor%20Magenta%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24MyWorkItemCount%20%7C%20Add-Member%20-type%20NoteProperty%20-Name%20%24(%24MyWorkItemType)%20-Value%20%24(%24ProjectWorkItemsAPI.count)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24TotalOtherItems%20-%3D%20%24ProjectWorkItemsAPI.count%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20else%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24MyWorkItemCount%20%7C%20Add-Member%20-type%20NoteProperty%20-Name%20%24(%24MyWorkItemType)%20-Value%200%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%23%20-------%20GET%20DETAILS%20FOR%20WORK%20ITEMS%20AND%20TYPES%20FOR%20CURRENT%20YEAR%20-------%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20-%20-%20-%20-%20CURRENT%20YEAR%20WORK%20ITEMS%20-%20-%20-%20-%20-%20%22%0A%20%20%20%20%20%20%20%20%24MyWorkItemCountCurrentYear%20%3D%20%40()%0A%20%20%20%20%20%20%20%20%24MyWiQlCommand%20%3D%20%22Select%20%5BSystem.Id%5D%20FROM%20WorkItems%20WHERE%20%5BSystem.TeamProject%5D%3D'%24(%24myProject.Name)'%20AND%20%5BSystem.CreatedDate%5D%20%26gt%3B%3D%20%40StartOfYear%22%0A%20%20%20%20%20%20%20%20%24body%20%3D%20%40%7B%20query%20%3D%20%24MyWiQlCommand%20%7D%0A%20%20%20%20%20%20%20%20%24bodyJson%3D%40(%24body)%20%7C%20ConvertTo-Json%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%22_apis%2Fwit%2Fwiql%3Fapi-version%3D6.0%22%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Post%20-ContentType%20%22application%2Fjson%22%20-Body%20%24bodyJson%0A%20%20%20%20%20%20%20%20%24ProjectWorkItemsAPI%3D%20%24response.workItems%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20Work%20Items%20Total%20Current%20Year%3A%22%2C%20%24ProjectWorkItemsAPI.count%20-ForegroundColor%20Magenta%0A%20%20%20%20%20%20%20%20%24TotalWorkItemsPerProjectCurrentYear%20%3D%20%24ProjectWorkItemsAPI.Count%0A%20%20%20%20%20%20%20%20%24TotalOtherItemsCurrentYear%20%3D%20%24TotalWorkItemsPerProjectCurrentYear%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%23check%20for%20each%20Type%20of%20Work%20Item%0A%20%20%20%20%20%20%20%20%24MyWorkItemCountCurrentYear%20%3D%20New-Object%20PSObject%0A%20%20%20%20%20%20%20%20foreach(%24MyWorkItemType%20in%20%24StandardWorkItems)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24MyWiQlCommand%20%3D%20%22Select%20%20%5BSystem.Id%5D%20FROM%20WorkItems%20WHERE%20%5BSystem.TeamProject%5D%3D'%24(%24myProject.Name)'%20AND%20%5BSystem.WorkItemType%5D%20%3D%20'%24(%24MyWorkItemType)'%20%20AND%20%5BSystem.CreatedDate%5D%20%26gt%3B%3D%20%40StartOfYear%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%24body%20%3D%20%40%7B%20query%20%3D%20%24MyWiQlCommand%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24bodyJson%3D%40(%24body)%20%7C%20ConvertTo-Json%0A%20%20%20%20%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%22_apis%2Fwit%2Fwiql%3Fapi-version%3D6.0%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Post%20-ContentType%20%22application%2Fjson%22%20-Body%20%24bodyJson%0A%20%20%20%20%20%20%20%20%20%20%20%20%24ProjectWorkItemsAPI%3D%20%24response.workItems%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24ProjectWorkItemsAPI.count%20-gt%200)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20%20%20%20%20%20%20%20%26gt%3B%26gt%3B%26gt%3B%20Current%20Year%20WorkItems%20Type%20(API)%3A%22%2C%20%24MyWorkItemType%2C%20%22%20-%20Total%3A%22%2C%20%24ProjectWorkItemsAPI.count%20-ForegroundColor%20Magenta%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24MyWorkItemCountCurrentYear%20%7C%20Add-Member%20-type%20NoteProperty%20-Name%20%24(%24MyWorkItemType)%20-Value%20%24(%24ProjectWorkItemsAPI.count)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24TotalOtherItemsCurrentYear%20-%3D%20%24ProjectWorkItemsAPI.count%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20else%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24MyWorkItemCountCurrentYear%20%7C%20Add-Member%20-type%20NoteProperty%20-Name%20%24(%24MyWorkItemType)%20-Value%200%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%23%20-------%20GET%20DETAILS%20FOR%20WORK%20ITEMS%20AND%20TYPES%20FOR%20PREVIOUS%20YEAR%20-------%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20-%20-%20-%20-%20PREVIOUS%20YEAR%20WORK%20ITEMS%20-%20-%20-%20-%20-%20%22%0A%20%20%20%20%20%20%20%20%24PreviousyearStart%20%3D%20%221%2F1%2F%24(%24PreviousYear)%22%0A%20%20%20%20%20%20%20%20%24PreviousyearEnd%20%3D%20%2212%2F31%2F%24(%24PreviousYear)%22%0A%0A%20%20%20%20%20%20%20%20%24MyWorkItemCountPreviousYear%20%3D%20%40()%0A%20%20%20%20%20%20%20%20%24MyWiQlCommand%20%3D%20%22Select%20%5BSystem.Id%5D%20FROM%20WorkItems%20WHERE%20%5BSystem.TeamProject%5D%3D'%24(%24myProject.Name)'%20AND%20%5BSystem.CreatedDate%5D%20%26gt%3B%3D%20'%24(%24PreviousyearStart)'%20%20AND%20%5BSystem.CreatedDate%5D%20%26lt%3B%3D%20'%24(%24PreviousyearEnd)'%22%0A%20%20%20%20%20%20%20%20%24body%20%3D%20%40%7B%20query%20%3D%20%24MyWiQlCommand%20%7D%0A%20%20%20%20%20%20%20%20%24bodyJson%3D%40(%24body)%20%7C%20ConvertTo-Json%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%22_apis%2Fwit%2Fwiql%3Fapi-version%3D6.0%22%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Post%20-ContentType%20%22application%2Fjson%22%20-Body%20%24bodyJson%0A%20%20%20%20%20%20%20%20%24ProjectWorkItemsAPI%3D%20%24response.workItems%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20Work%20Items%20Total%20Previous%20Year%3A%22%2C%20%24ProjectWorkItemsAPI.count%20-ForegroundColor%20Magenta%0A%20%20%20%20%20%20%20%20%24TotalWorkItemsPerProjectPreviousYear%20%3D%20%24ProjectWorkItemsAPI.Count%0A%20%20%20%20%20%20%20%20%24TotalOtherItemsPreviousYear%20%3D%20%24TotalWorkItemsPerProjectPreviousYear%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%23check%20for%20each%20Type%20of%20Work%20Item%0A%20%20%20%20%20%20%20%20%24MyWorkItemCountPreviousYear%20%3D%20New-Object%20PSObject%0A%20%20%20%20%20%20%20%20foreach(%24MyWorkItemType%20in%20%24StandardWorkItems)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24MyWiQlCommand%20%3D%20%22Select%20%20%5BSystem.Id%5D%20FROM%20WorkItems%20WHERE%20%5BSystem.TeamProject%5D%3D'%24(%24myProject.Name)'%20AND%20%5BSystem.WorkItemType%5D%20%3D%20'%24(%24MyWorkItemType)'%20%20AND%20%5BSystem.CreatedDate%5D%20%26gt%3B%3D%20'%24(%24PreviousyearStart)'%20%20AND%20%5BSystem.CreatedDate%5D%20%26lt%3B%3D%20'%24(%24PreviousyearEnd)'%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%24body%20%3D%20%40%7B%20query%20%3D%20%24MyWiQlCommand%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24bodyJson%3D%40(%24body)%20%7C%20ConvertTo-Json%0A%20%20%20%20%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%22_apis%2Fwit%2Fwiql%3Fapi-version%3D6.0%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Post%20-ContentType%20%22application%2Fjson%22%20-Body%20%24bodyJson%0A%20%20%20%20%20%20%20%20%20%20%20%20%24ProjectWorkItemsAPI%3D%20%24response.workItems%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24ProjectWorkItemsAPI.count%20-gt%200)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20%20%20%20%20%20%20%20%26gt%3B%26gt%3B%26gt%3B%20Previous%20Year%20WorkItems%20Type%20(API)%3A%22%2C%20%24MyWorkItemType%2C%20%22%20-%20Total%3A%22%2C%20%24ProjectWorkItemsAPI.count%20-ForegroundColor%20Magenta%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24MyWorkItemCountPreviousYear%20%7C%20Add-Member%20-type%20NoteProperty%20-Name%20%24(%24MyWorkItemType)%20-Value%20%24(%24ProjectWorkItemsAPI.count)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24TotalOtherItemsPreviousYear%20-%3D%20%24ProjectWorkItemsAPI.count%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20else%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24MyWorkItemCountPreviousYear%20%7C%20Add-Member%20-type%20NoteProperty%20-Name%20%24(%24MyWorkItemType)%20-Value%200%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%23%20-------%20GET%20COUNTER%20FOR%20PIPELINES%20-------%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20-%20-%20-%20-%20%22%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%24myProject.Name%20%2B%20%22%2F_apis%2Fpipelines%3Fapi-version%3D6.0-preview.1%22%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Get%20-ContentType%20%22application%2Fjson%22%0A%20%20%20%20%20%20%20%20if(%24response.count%20-gt%200)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24PipelineCount%3D%20%24response.count%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20azDevOps%20BuildPipeline%20Total%3A%22%2C%20%24PipelineCount%20-ForegroundColor%20Green%0A%20%20%20%20%20%20%20%20%23%20-------%20GET%20COUNTER%20FOR%20TEST%20PLANS%20-------%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20-%20-%20-%20-%20%22%0A%20%20%20%20%20%20%20%20%24uriAccount%20%3D%20%24Organization%20%2B%20%24myProject.Name%20%2B%20%22%2F_apis%2Ftestplan%2Fplans%3Fapi-version%3D6.0-preview.1%22%0A%20%20%20%20%20%20%20%20%24response%20%3D%20Invoke-RestMethod%20-Uri%20%24uriAccount%20-Headers%20%24AzureDevOpsAuthenicationHeader%20-Method%20Get%20-ContentType%20%22application%2Fjson%22%0A%20%20%20%20%20%20%20%20if(%24response.value.count%20-gt%200)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24TestPlansCount%3D%20%24response.value.count%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20write-host%20%22%20%20%20%20%20-%20azDevOps%20Test%20Plans%20Total%3A%22%2C%20%24TestPlansCount%20-ForegroundColor%20White%0A%20%20%20%20%20%20%20%20%23%20-------%20CONSOLIDATE%20ALL%20INFORMATION%20-------%0A%20%20%20%20%20%20%20%20%24ProjectStatisticsPerOrganization%20%2B%3D%20New-Object%20-TypeName%20PSObject%20-Property%20%40%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20DevOpsOrganizationName%3D%24MyOrganization.OrganizationName%0A%20%20%20%20%20%20%20%20%20%20%20%20%20ProjectName%3D%24myProject.Name%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ProjectProcessModel%3D%24ProjectProcessModelProperty%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ProcessModelWIWithStates%3D%24ProcessModelWIWithStates%0A%20%20%20%20%20%20%20%20%20%20%20%20%20ProjectLastModifiedDate%3D%24myProject.lastUpdateTime%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TotalRepositories%3D%24ProjectRepositories.Count%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TotalBranchesOveralRepo%3D%24TotalBranchesPerProject%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20RepositoriesBranchesDetails%3D%24RepoBranchDetails%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TotalWorkItems%3D%24TotalWorkItemsPerProject%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Bug%3D%24MyWorkItemCount.Bug%20%20%20%20%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Epic%3D%24MyWorkItemCount.Epic%20%20%20%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Feature%3D%24MyWorkItemCount.Feature%20%20%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Issue%3D%24MyWorkItemCount.Issue%20%20%20%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Task%3D%24MyWorkItemCount.Task%20%20%20%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_TestCase%3D%24MyWorkItemCount.'Test%20Case'%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_UserStory%3D%24MyWorkItemCount.'User%20Story'%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WI_Other%3D%24TotalOtherItems%20%20%20%20%20%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22TotalWorkItemsCurrentYear%24(%24CurrentYear)%22%3D%24TotalWorkItemsPerProjectCurrentYear%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_BugCurrentYear_%24(%24CurrentYear)%22%3D%24MyWorkItemCountCurrentYear.Bug%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_EpicCurrentYear_%24(%24CurrentYear)%22%3D%24MyWorkItemCountCurrentYear.Epic%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_FeatureCurrentYear_%24(%24CurrentYear)%22%3D%24MyWorkItemCountCurrentYear.Feature%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_IssueCurrentYear_%24(%24CurrentYear)%22%3D%24MyWorkItemCountCurrentYear.Issue%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_TaskCurrentYear_%24(%24CurrentYear)%22%3D%24MyWorkItemCountCurrentYear.Task%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_TestCaseCurrentYear_%24(%24CurrentYear)%22%3D%24MyWorkItemCountCurrentYear.'Test%20Case'%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_UserStoryCurrentYear_%24(%24CurrentYear)%22%3D%24MyWorkItemCountCurrentYear.'User%20Story'%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_OtherCurrentYear_%24(%24CurrentYear)%22%3D%24TotalOtherItemsCurrentYear%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22TotalWorkItemsPreviousYear_%24(%24PreviousYear)%22%3D%24TotalWorkItemsPerProjectPreviousYear%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_BugPreviousYear_%24(%24PreviousYear)%22%3D%24MyWorkItemCountPreviousYear.Bug%20%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_EpicPreviousYear_%24(%24PreviousYear)%22%3D%24MyWorkItemCountPreviousYear.Epic%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_FeaturePreviousYear_%24(%24PreviousYear)%22%3D%24MyWorkItemCountPreviousYear.Feature%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_IssuePreviousYear_%24(%24PreviousYear)%22%3D%24MyWorkItemCountPreviousYear.Issue%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_TaskPreviousYear_%24(%24PreviousYear)%22%3D%24MyWorkItemCountPreviousYear.Task%20%20%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_TestCasePreviousYear_%24(%24PreviousYear)%22%3D%24MyWorkItemCountPreviousYear.'Test%20Case'%20%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_UserStoryPreviousYear_%24(%24PreviousYear)%22%3D%24MyWorkItemCountPreviousYear.'User%20Story'%20%23To%20adapt%20if%20process%20in%20not%20Agile%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22WI_OtherPreviousYear_%24(%24PreviousYear)%22%3D%24TotalOtherItemsPreviousYear%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20BuildPipelineTotal%3D%24PipelineCount%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TestPlansTotal%3D%24TestPlansCount%0A%20%20%20%20%20%20%20%20%20%20%20%20%20DataRefreshDate%20%3D%20%24DataRefreshDate%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20write-host%20%22%20----------------------------------------------------------------------------------------------------%20%22%20-ForegroundColor%20Yellow%0A%20%20%20%20%7D%0A%20%24ProjectStatisticsPerOrganization%20%7C%20ConvertTo-Json%20%7C%20Out-File%20-FilePath%20%24ProjectStatisticsJSonFilePath%20-Encoding%20UTF8%0A%20%24ProjectStatisticsOveralOrganization%20%2B%3D%20%24ProjectStatisticsPerOrganization%0A%20%20%20%20write-host%20%22%20--------------------------------------------------------------------%22%20-ForegroundColor%20White%20-BackgroundColor%20DarkYellow%0A%7D%0A%24ProjectStatisticsOveralOrganization%20%7C%20ConvertTo-Json%20%7C%20Out-File%20-FilePath%20%24ProjectStatisticsOveralOragnizationJSonFilePath%20-Encoding%20UTF8%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EAfter%20this%20execution%2C%20you%20can%20retrieve%20one%20JSON%20file%20per%20organization%20and%20an%20aggregated%20one%20to%20load%20it%20into%20your%20preferred%20reporting%20tool%20(Excel%20or%20Power%20BI).%26nbsp%3B%3C%2FP%3E%3CP%3EYou%20can%20also%20easily%20schedule%20this%20script%20to%20get%20the%20JSON%20file%20in%20Power%20BI%20automatically%20and%20have%20something%20following%20your%20delivery%20team.%3C%2FP%3E%3CP%3EThe%20final%20goal%20of%20that%20module%20is%20to%20see%20and%20show%20the%20platform%20adoption%20and%20communicate%20around%20this.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%3CSTRONG%3E%3CEM%3EReferences%20used%20to%20build%20that%20script%3A%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FP%3E%3CUL%3E%3CLI%3E%3CEM%3E%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Frest%2Fapi%2Fazure%2Fdevops%2F%3Fview%3Dazure-devops-rest-6.1%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3Ehttps%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Frest%2Fapi%2Fazure%2Fdevops%2F%3Fview%3Dazure-devops-rest-6.1%3C%2FA%3E%3C%2FEM%3E%3C%2FLI%3E%3CLI%3E%3CEM%3E%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdevops%2Fboards%2Fwork-items%2Fworkflow-and-state-categories%22%20target%3D%22_self%22%20rel%3D%22noopener%20noreferrer%22%3Ehttps%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdevops%2Fboards%2Fwork-items%2Fworkflow-and-state-categories%3C%2FA%3E%3C%2FEM%3E%3C%2FLI%3E%3CLI%3E%3CEM%3E%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdevops%2Fboards%2Fqueries%2Fwiql-syntax%3Fview%3Dazure-devops%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3Ehttps%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdevops%2Fboards%2Fqueries%2Fwiql-syntax%3Fview%3Dazure-devops%3C%2FA%3E%3C%2FEM%3E%3C%2FLI%3E%3CLI%3E%3CEM%3E%3CA%20href%3D%22https%3A%2F%2Fnewsignature.com%2Farticles%2F59293%2F%22%20target%3D%22_blank%22%20rel%3D%22nofollow%20noopener%20noreferrer%22%3Ehttps%3A%2F%2Fnewsignature.com%2Farticles%2F59293%2F%3C%2FA%3E%3C%2FEM%3E%3C%2FLI%3E%3CLI%3E%3CA%20href%3D%22https%3A%2F%2Fdev.to%2Fomiossec%2Fgetting-started-with-azure-devops-api-with-powershell-59nn%22%20target%3D%22_blank%22%20rel%3D%22nofollow%20noopener%20noreferrer%22%3E%3CEM%3Ehttps%3A%2F%2Fdev.to%2Fomiossec%2Fgetting-started-with-azure-devops-api-with-powershell-59nn%3C%2FEM%3E%3C%2FA%3E%3C%2FLI%3E%3C%2FUL%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2232698%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EDevOps%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EPowerShell%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Eprojects%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Estatistics%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EUsage%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Regular Contributor

I published some other PowerShell scripts to manage or follow Azure DevOps platform:

But some other questions are opened immediately:

  • What is the usage of our Azure DevOps platform?
  • Can we confirm the success or fail from usage point of view?
  • What is the maturity of my developer population related to DevOps (Repos, branches, pipelines, tests, …) ?
  • What is the volume of user stories per type, with specific focus on current and previous years ?
  • … 

So, this script will help you to have information responding to some of those questions and much more.

It's easy to read and adapt, based on Azure DevOps API proposed by Microsoft.

 

#Installation Azure CLI: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?view=azure-cli-latest&tabs=azure-powershell
#Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'; rm .\AzureCLI.msi
#Activation Az DevOps: az devops configure --defaults organization=$Organization

#region  --  Customized Script Settings (need to be reviewed) ---
# ================== / Parameters to Adapt \ ================== 
[string]$GlobalPATForAllORganizations= "YourPersonalAccessTokenIfGlobalone"
[string]$JSonStatsFolderPath = "C:\DEVOPSSTATISTICS"
# ================== \ Parameters to Adapt / ================== 
#endregion

#region --  Internal Script Settings  ---

$OrganizationList = @()
[string]$PAT = ""
[string]$OrganizationName = ""
[string]$Organization = ""
[string]$ProjectStatisticsJSonFilePath = "" 
[string]$ProjectListJSonFilePath = ""
$DataRefreshDate = Get-Date -Format "yyyy-MM-dd"
[string]$ProjectProcessModelProperty = ""
[string]$ProjectProcessModelIDProperty = ""
[int]$TotalProjectPerOrganization = 0
[int]$ProjectInProgress = 0
[int]$TotalRepositoriesPerProject = 0
[int]$TotalBranchesPerProject = 0
[int]$TotalWorkItemsPerProject = 0
[int]$TotalOtherItems = 0 
[int]$TotalWorkItemsPerProjectCurrentYear = 0
[int]$TotalOtherItemsCurrentYear = 0
[int]$TotalWorkItemsPerProjectPreviousYear = 0
[int]$TotalOtherItemsPreviousYear = 0
[int]$CurrentYear = 0
[int]$PreviousYear = 0
[string]$PreviousyearStart = ""
[string]$PreviousyearEnd = ""
$StandardWorkItems= "Bug", "Epic", "Feature", "Issue", "Task", "Test Case", "User Story" #To adapt if process in not Agile model
[string]$RepoBranchDetails = ""
[string]$WorkItemCountPerType = ""
[string]$MyWiQlCommand = ""
[string]$uriAccount = ""
[int]$PipelineCount = 0
[int]$TestPlansCount = 0
$ProjectStatisticsOveralOrganization = @()
[string]$ProjectStatisticsOveralOragnizationJSonFilePath = "$JSonStatsFolderPath\DevOps-ProjectStatistics.json"
#endregion

#region --  Each Az DevOps Organization  --
#organization1
$PAT = $GlobalPATForAllORganizations #https://dev.azure.com/organization1/_usersSettings/tokens
$OrganizationName = "organization1"
$OrganizationWithPAT = New-Object PSObject -property @{OrganizationName=$OrganizationName;OrganizationPAT=$PAT}
$OrganizationList += $OrganizationWithPAT
#organization2
$PAT = $GlobalPATForAllORganizations #https://dev.azure.com/organization2/_usersSettings/tokens
$OrganizationName = "organization2"
$OrganizationWithPAT = New-Object PSObject -property @{OrganizationName=$OrganizationName;OrganizationPAT=$PAT}
$OrganizationList += $OrganizationWithPAT
#organization3
$PAT = $GlobalPATForAllORganizations #https://dev.azure.com/organization3/_usersSettings/tokens
$OrganizationName = "organization3"
$OrganizationWithPAT = New-Object PSObject -property @{OrganizationName=$OrganizationName;OrganizationPAT=$PAT}
$OrganizationList += $OrganizationWithPAT
#endregion

foreach($MyOrganization in $OrganizationList)
{
    write-host " --------------------------------------------------------------------" -ForegroundColor White -BackgroundColor DarkYellow
    write-host " -----      Organization :", $MyOrganization.OrganizationName ,"              ------" -ForegroundColor White -BackgroundColor DarkYellow
    write-host " --------------------------------------------------------------------" -ForegroundColor White -BackgroundColor DarkYellow
    $TotalProjectPerOrganization = 0
    $ProjectInProgress = 0
    $CurrentYear = $((Get-Date).year)
    $PreviousYear = $((Get-Date).year - 1)
    $AzureDevOpsAuthenicationHeader = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($MyOrganization.OrganizationPAT)")) }
	$Organization = "https://dev.azure.com/$($MyOrganization.OrganizationName)/" 
	$ProjectStatisticsPerOrganization = @()
	$ProjectStatisticsJSonFilePath = "$JSonStatsFolderPath\$($MyOrganization.OrganizationName)-ProjectStatistics.json"
    $ProjectListJSonFilePath = "$JSonStatsFolderPath\$($MyOrganization.OrganizationName)-ProjectList.json"
	echo $($MyOrganization.OrganizationPAT) | az devops login --org $Organization
	az devops configure --defaults organization=$Organization
	#$allProjects = az devops project list --org $Organization --top 100 | ConvertFrom-Json | Select-Object -ExpandProperty value | Sort-Object name  											#Select 1st project to validate script
	#$allProjects = az devops project list --org $Organization --top 10000 | ConvertFrom-Json | Select-Object -ExpandProperty value | Where-Object name -eq "MyProjectName" | Sort-Object name 	#Select filtered project
	$allProjects = az devops project list --org $Organization --top 10000 | ConvertFrom-Json | Select-Object -ExpandProperty value | Sort-Object name 											#Select all projects
    #$allProjects
	#$allProjects | ConvertTo-Json | Out-File -FilePath $ProjectListJSonFilePath -Encoding UTF8 #If you want to save a copy
    $TotalProjectPerOrganization = $allProjects.Count
    foreach($myProject in $allProjects)
    {
        $ProjectInProgress += 1
        $TotalRepositoriesPerProject = 0
		$TotalWorkItemsPerProject = 0
        $TotalOtherItems = 0
        $TotalWorkItemsPerProjectCurrentYear = 0
        $TotalOtherItemsCurrentYear = 0
        $TotalWorkItemsPerProjectPreviousYear = 0
        $TotalOtherItemsPreviousYear = 0
        $TotalBranchesPerProject = 0
        $PipelineCount = 0
        $TestPlansCount = 0
        $RepoBranchDetails = ""
        $WorkItemCountPerType = ""
        $ProjectProcessModelProperty = ""
        $ProjectProcessModelIDProperty = ""
        $ProcessModelWIWithStates = @()
        write-host " ---------------------------------------------------------------------------------------------------- " -ForegroundColor Yellow
        write-host " -- Project Name:", $myProject.Name, "[", $ProjectInProgress, " of ", $TotalProjectPerOrganization, "] --" -ForegroundColor Yellow
        write-host "     > Last Update:", $myProject.lastUpdateTime -ForegroundColor DarkYellow
        #write-host "     > Project Description:", $myProject.Description -ForegroundColor DarkYellow
        write-host " ---------------------------------------------------------------------------------------------------- " -ForegroundColor Yellow
        # ------- GET PROJECT PROCESS MODEL DETAILS -------
        write-host "     - - - - - "
        $uriAccount = $Organization +  "_apis/projects/"+ $myProject.id +"/properties?api-version=6.0-preview.1"
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Get -ContentType "application/json"
        $ProjectProcessModelIDProperty = $response.value.Where({$_.name -eq "System.ProcessTemplateType"}).value
        $uriAccount = $Organization +  "_apis/work/processes/{"+ $ProjectProcessModelIDProperty +"}?api-version=6.0-preview.2"
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Get -ContentType "application/json"
        $ProjectProcessModelProperty = $response.name 
        write-host "     - Project Process Model:", $ProjectProcessModelProperty, "-ID:", $ProjectProcessModelIDProperty -ForegroundColor Green
        $uriAccount = $Organization +  "_apis/work/processes/{"+ $ProjectProcessModelIDProperty +'}/workitemtypes?$expand=States&api-version=6.0-preview.2'
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Get -ContentType "application/json"
        $ProcessModelWIWithStatesTemp = $response.value
        foreach($myProcessModelWITypeWithStates in $ProcessModelWIWithStatesTemp)
        {
            write-host "        - WI Type:", $myProcessModelWITypeWithStates.Name
            foreach($MyWIState in $myProcessModelWITypeWithStates.states)
            {
                write-host "              -> WI Type States:", $MyWIState.name, "- Category:", $MyWIState.stateCategory
                $ProcessModelWIWithStates += New-Object -TypeName PSObject -Property @{
                                WI_Type=$myProcessModelWITypeWithStates.Name
                                WI_Type_States=$MyWIState.name
                                WI_Type_States_Category=$MyWIState.stateCategory
                                }
            }
        }
        $ProcessModelWIWithStates = $ProcessModelWIWithStates | ConvertTo-Json
        # ------- GET DETAILS FOR REPOSITORIES AND BRANCHES -------
        $ProjectRepositories = az repos list --org $Organization --project $myProject.Name | ConvertFrom-Json
        #$ProjectRepositories
        $TotalRepositoriesPerProject = $ProjectRepositories.Count
        foreach($myRepository in $ProjectRepositories)
        {
            write-host "     - Repository Name:", $myRepository.name, "- ID:", $myRepository.id -ForegroundColor Cyan
            $RepositoryBranches = az repos ref list --org $Organization --project $myProject.Name --repository $myRepository.id  | ConvertFrom-Json
            write-host "        >>> Branch Total:", $RepositoryBranches.count -ForegroundColor Cyan
            $TotalBranchesPerProject += $RepositoryBranches.count
            $RepoBranchDetails += "[$($myRepository.name)]:$($RepositoryBranches.count);"
        }
        if($RepoBranchDetails.EndsWith(";"))
        {
           $RepoBranchDetails = $RepoBranchDetails.Substring(0,$RepoBranchDetails.Length-1)
        }
        # ------- GET DETAILS FOR WORK ITEMS AND TYPES -------
        write-host "     - - - - - TOTAL WORK ITEMS - - - - - "
        $MyWorkItemPerType = @()
        $MyWiQlCommand = "Select [System.Id] FROM WorkItems WHERE [System.TeamProject]='$($myProject.Name)'"
        $body = @{ query = $MyWiQlCommand }
        $bodyJson=@($body) | ConvertTo-Json
        $uriAccount = $Organization + "_apis/wit/wiql?api-version=6.0"
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Post -ContentType "application/json" -Body $bodyJson
        $ProjectWorkItemsAPI= $response.workItems
        write-host "     - Work Items Total:", $ProjectWorkItemsAPI.count -ForegroundColor Magenta
        $TotalWorkItemsPerProject = $ProjectWorkItemsAPI.Count
        $TotalOtherItems = $TotalWorkItemsPerProject
        #check for each Type of Work Item
        $MyWorkItemCount = New-Object PSObject
        foreach($MyWorkItemType in $StandardWorkItems)
        {
            $MyWiQlCommand = "Select  [System.Id] FROM WorkItems WHERE [System.TeamProject]='$($myProject.Name)' AND [System.WorkItemType] = '$($MyWorkItemType)' "
            $body = @{ query = $MyWiQlCommand }
            $bodyJson=@($body) | ConvertTo-Json
            $uriAccount = $Organization + "_apis/wit/wiql?api-version=6.0"
            $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Post -ContentType "application/json" -Body $bodyJson
            $ProjectWorkItemsAPI= $response.workItems
            if($ProjectWorkItemsAPI.count -gt 0)
            {
                write-host "            >>> WorkItems Type (API):", $MyWorkItemType, " - Total:", $ProjectWorkItemsAPI.count -ForegroundColor Magenta
                $MyWorkItemCount | Add-Member -type NoteProperty -Name $($MyWorkItemType) -Value $($ProjectWorkItemsAPI.count)
                $TotalOtherItems -= $ProjectWorkItemsAPI.count
            }
            else
            {
                $MyWorkItemCount | Add-Member -type NoteProperty -Name $($MyWorkItemType) -Value 0
            }
        }

        # ------- GET DETAILS FOR WORK ITEMS AND TYPES FOR CURRENT YEAR -------
        write-host "     - - - - - CURRENT YEAR WORK ITEMS - - - - - "
        $MyWorkItemCountCurrentYear = @()
        $MyWiQlCommand = "Select [System.Id] FROM WorkItems WHERE [System.TeamProject]='$($myProject.Name)' AND [System.CreatedDate] >= @StartOfYear"
        $body = @{ query = $MyWiQlCommand }
        $bodyJson=@($body) | ConvertTo-Json
        $uriAccount = $Organization + "_apis/wit/wiql?api-version=6.0"
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Post -ContentType "application/json" -Body $bodyJson
        $ProjectWorkItemsAPI= $response.workItems
        write-host "     - Work Items Total Current Year:", $ProjectWorkItemsAPI.count -ForegroundColor Magenta
        $TotalWorkItemsPerProjectCurrentYear = $ProjectWorkItemsAPI.Count
        $TotalOtherItemsCurrentYear = $TotalWorkItemsPerProjectCurrentYear
        
        #check for each Type of Work Item
        $MyWorkItemCountCurrentYear = New-Object PSObject
        foreach($MyWorkItemType in $StandardWorkItems)
        {
            $MyWiQlCommand = "Select  [System.Id] FROM WorkItems WHERE [System.TeamProject]='$($myProject.Name)' AND [System.WorkItemType] = '$($MyWorkItemType)'  AND [System.CreatedDate] >= @StartOfYear"
            $body = @{ query = $MyWiQlCommand }
            $bodyJson=@($body) | ConvertTo-Json
            $uriAccount = $Organization + "_apis/wit/wiql?api-version=6.0"
            $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Post -ContentType "application/json" -Body $bodyJson
            $ProjectWorkItemsAPI= $response.workItems
            if($ProjectWorkItemsAPI.count -gt 0)
            {
                write-host "            >>> Current Year WorkItems Type (API):", $MyWorkItemType, " - Total:", $ProjectWorkItemsAPI.count -ForegroundColor Magenta
                $MyWorkItemCountCurrentYear | Add-Member -type NoteProperty -Name $($MyWorkItemType) -Value $($ProjectWorkItemsAPI.count)
                $TotalOtherItemsCurrentYear -= $ProjectWorkItemsAPI.count
            }
            else
            {
                $MyWorkItemCountCurrentYear | Add-Member -type NoteProperty -Name $($MyWorkItemType) -Value 0
            }
        }

        # ------- GET DETAILS FOR WORK ITEMS AND TYPES FOR PREVIOUS YEAR -------
        write-host "     - - - - - PREVIOUS YEAR WORK ITEMS - - - - - "
        $PreviousyearStart = "1/1/$($PreviousYear)"
        $PreviousyearEnd = "12/31/$($PreviousYear)"

        $MyWorkItemCountPreviousYear = @()
        $MyWiQlCommand = "Select [System.Id] FROM WorkItems WHERE [System.TeamProject]='$($myProject.Name)' AND [System.CreatedDate] >= '$($PreviousyearStart)'  AND [System.CreatedDate] <= '$($PreviousyearEnd)'"
        $body = @{ query = $MyWiQlCommand }
        $bodyJson=@($body) | ConvertTo-Json
        $uriAccount = $Organization + "_apis/wit/wiql?api-version=6.0"
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Post -ContentType "application/json" -Body $bodyJson
        $ProjectWorkItemsAPI= $response.workItems
        write-host "     - Work Items Total Previous Year:", $ProjectWorkItemsAPI.count -ForegroundColor Magenta
        $TotalWorkItemsPerProjectPreviousYear = $ProjectWorkItemsAPI.Count
        $TotalOtherItemsPreviousYear = $TotalWorkItemsPerProjectPreviousYear
        
        #check for each Type of Work Item
        $MyWorkItemCountPreviousYear = New-Object PSObject
        foreach($MyWorkItemType in $StandardWorkItems)
        {
            $MyWiQlCommand = "Select  [System.Id] FROM WorkItems WHERE [System.TeamProject]='$($myProject.Name)' AND [System.WorkItemType] = '$($MyWorkItemType)'  AND [System.CreatedDate] >= '$($PreviousyearStart)'  AND [System.CreatedDate] <= '$($PreviousyearEnd)'"
            $body = @{ query = $MyWiQlCommand }
            $bodyJson=@($body) | ConvertTo-Json
            $uriAccount = $Organization + "_apis/wit/wiql?api-version=6.0"
            $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Post -ContentType "application/json" -Body $bodyJson
            $ProjectWorkItemsAPI= $response.workItems
            if($ProjectWorkItemsAPI.count -gt 0)
            {
                write-host "            >>> Previous Year WorkItems Type (API):", $MyWorkItemType, " - Total:", $ProjectWorkItemsAPI.count -ForegroundColor Magenta
                $MyWorkItemCountPreviousYear | Add-Member -type NoteProperty -Name $($MyWorkItemType) -Value $($ProjectWorkItemsAPI.count)
                $TotalOtherItemsPreviousYear -= $ProjectWorkItemsAPI.count
            }
            else
            {
                $MyWorkItemCountPreviousYear | Add-Member -type NoteProperty -Name $($MyWorkItemType) -Value 0
            }
        }
        # ------- GET COUNTER FOR PIPELINES -------
        write-host "     - - - - - "
        $uriAccount = $Organization + $myProject.Name + "/_apis/pipelines?api-version=6.0-preview.1"
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Get -ContentType "application/json"
        if($response.count -gt 0)
        {
            $PipelineCount= $response.count
        }
        write-host "     - azDevOps BuildPipeline Total:", $PipelineCount -ForegroundColor Green
        # ------- GET COUNTER FOR TEST PLANS -------
        write-host "     - - - - - "
        $uriAccount = $Organization + $myProject.Name + "/_apis/testplan/plans?api-version=6.0-preview.1"
        $response = Invoke-RestMethod -Uri $uriAccount -Headers $AzureDevOpsAuthenicationHeader -Method Get -ContentType "application/json"
        if($response.value.count -gt 0)
        {
            $TestPlansCount= $response.value.count
        }
        write-host "     - azDevOps Test Plans Total:", $TestPlansCount -ForegroundColor White
        # ------- CONSOLIDATE ALL INFORMATION -------
        $ProjectStatisticsPerOrganization += New-Object -TypeName PSObject -Property @{
													DevOpsOrganizationName=$MyOrganization.OrganizationName
													ProjectName=$myProject.Name
                                                    ProjectProcessModel=$ProjectProcessModelProperty
                                                    ProcessModelWIWithStates=$ProcessModelWIWithStates
													ProjectLastModifiedDate=$myProject.lastUpdateTime
                                                    TotalRepositories=$ProjectRepositories.Count
                                                    TotalBranchesOveralRepo=$TotalBranchesPerProject 
                                                    RepositoriesBranchesDetails=$RepoBranchDetails
                                                    TotalWorkItems=$TotalWorkItemsPerProject
                                                    WI_Bug=$MyWorkItemCount.Bug										#To adapt if process in not Agile model
                                                    WI_Epic=$MyWorkItemCount.Epic									#To adapt if process in not Agile model
                                                    WI_Feature=$MyWorkItemCount.Feature								#To adapt if process in not Agile model
                                                    WI_Issue=$MyWorkItemCount.Issue									#To adapt if process in not Agile model
                                                    WI_Task=$MyWorkItemCount.Task									#To adapt if process in not Agile model
                                                    WI_TestCase=$MyWorkItemCount.'Test Case'						#To adapt if process in not Agile model
                                                    WI_UserStory=$MyWorkItemCount.'User Story'						#To adapt if process in not Agile model
                                                    WI_Other=$TotalOtherItems										#To adapt if process in not Agile model
                                                    "TotalWorkItemsCurrentYear$($CurrentYear)"=$TotalWorkItemsPerProjectCurrentYear
                                                    "WI_BugCurrentYear_$($CurrentYear)"=$MyWorkItemCountCurrentYear.Bug					#To adapt if process in not Agile model
                                                    "WI_EpicCurrentYear_$($CurrentYear)"=$MyWorkItemCountCurrentYear.Epic				#To adapt if process in not Agile model
                                                    "WI_FeatureCurrentYear_$($CurrentYear)"=$MyWorkItemCountCurrentYear.Feature			#To adapt if process in not Agile model
                                                    "WI_IssueCurrentYear_$($CurrentYear)"=$MyWorkItemCountCurrentYear.Issue				#To adapt if process in not Agile model
                                                    "WI_TaskCurrentYear_$($CurrentYear)"=$MyWorkItemCountCurrentYear.Task				#To adapt if process in not Agile model
                                                    "WI_TestCaseCurrentYear_$($CurrentYear)"=$MyWorkItemCountCurrentYear.'Test Case'	#To adapt if process in not Agile model
                                                    "WI_UserStoryCurrentYear_$($CurrentYear)"=$MyWorkItemCountCurrentYear.'User Story'	#To adapt if process in not Agile model
                                                    "WI_OtherCurrentYear_$($CurrentYear)"=$TotalOtherItemsCurrentYear					#To adapt if process in not Agile model
                                                    "TotalWorkItemsPreviousYear_$($PreviousYear)"=$TotalWorkItemsPerProjectPreviousYear
                                                    "WI_BugPreviousYear_$($PreviousYear)"=$MyWorkItemCountPreviousYear.Bug					#To adapt if process in not Agile model
                                                    "WI_EpicPreviousYear_$($PreviousYear)"=$MyWorkItemCountPreviousYear.Epic				#To adapt if process in not Agile model
                                                    "WI_FeaturePreviousYear_$($PreviousYear)"=$MyWorkItemCountPreviousYear.Feature			#To adapt if process in not Agile model
                                                    "WI_IssuePreviousYear_$($PreviousYear)"=$MyWorkItemCountPreviousYear.Issue				#To adapt if process in not Agile model
                                                    "WI_TaskPreviousYear_$($PreviousYear)"=$MyWorkItemCountPreviousYear.Task				#To adapt if process in not Agile model
                                                    "WI_TestCasePreviousYear_$($PreviousYear)"=$MyWorkItemCountPreviousYear.'Test Case'		#To adapt if process in not Agile model
                                                    "WI_UserStoryPreviousYear_$($PreviousYear)"=$MyWorkItemCountPreviousYear.'User Story'	#To adapt if process in not Agile model
                                                    "WI_OtherPreviousYear_$($PreviousYear)"=$TotalOtherItemsPreviousYear
                                                    BuildPipelineTotal=$PipelineCount
                                                    TestPlansTotal=$TestPlansCount
													DataRefreshDate = $DataRefreshDate
													}
        write-host " ---------------------------------------------------------------------------------------------------- " -ForegroundColor Yellow
    }
	$ProjectStatisticsPerOrganization | ConvertTo-Json | Out-File -FilePath $ProjectStatisticsJSonFilePath -Encoding UTF8
	$ProjectStatisticsOveralOrganization += $ProjectStatisticsPerOrganization
    write-host " --------------------------------------------------------------------" -ForegroundColor White -BackgroundColor DarkYellow
}
$ProjectStatisticsOveralOrganization | ConvertTo-Json | Out-File -FilePath $ProjectStatisticsOveralOragnizationJSonFilePath -Encoding UTF8

 

After this execution, you can retrieve one JSON file per organization and an aggregated one to load it into your preferred reporting tool (Excel or Power BI). 

You can also easily schedule this script to get the JSON file in Power BI automatically and have something following your delivery team.

The final goal of that module is to see and show the platform adoption and communicate around this.

 

References used to build that script:

0 Replies