* Stress test (#3820)
* mem leak fix
* PR comments fix
* PR comments
* seems to work?
* clang
* curl again
* add first stress test
* also update gitignore
* missing line
* only linux
* clang typo format
* typo 2
* PR comments
* cspell
* remove terminator
* Fixed the metadata for better handling (#3824)
Co-authored-by: sima-zhu <sizhu@microsoft.com>
* Update attestation core vcpkg dependency to latest GA version that is required. (#3830)
* Update attestation core vcpkg dependency to latest GA version that is required.
* Update vcpkg config.cmake to match the dependency version needed.
* Remove winhttp (#3832)
* remove refs to winhttp
* this tsst only curl
* Move perf.yml to eng/common (#3833)
Co-authored-by: Mike Harder <mharder@microsoft.com>
* Sync eng/common directory with azure-sdk-tools for PR 3656 (#3834)
* someone wants to reference the test-proxy startup scripts externally. to make this easy on them we're parameterizing the root of the eng/common for easy use in that scenario
* two leading $ signs on the definition of the certificate path was causing some issues!
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
* Update casing for 'verison' (#3821)
Co-authored-by: Daniel Jurek <djurek@microsoft.com>
* Print additional result summary formats to pipelines UI (#3842)
Co-authored-by: Mike Harder <mharder@microsoft.com>
* Sync eng/common directory with azure-sdk-tools for PR 3702 (#3843)
* Add language-service to list of valid sample slugs
* Update link to taxonomies
Co-authored-by: Heath Stewart <heaths@microsoft.com>
* Fix incorrect failure notification in vcpkg publishing (#3838)
* Set up for testing of template pipeline
* Override branches, set up for template GA release
* More TODOs to prevent merging an unintended change
* More removal of TestPipeline
* Increment template version number
* Use script to set package version
* Check out the correct branch
* branch parameter in the command
* Use $(PublishToVcpkg) to determine if we should check for changes
* dictionary syntax
* Set GA package version to validate GA publish scenario
* Update changelog
* create-pull-request.yml optionally pushes changes
* Output GH PR URI
* Macro syntax with a variable set earlier
* Move up to 1.2.0-beta.2
* beta.1
* Revert changelog
* Revert testing-related changes
* Revert vcpkg-clone.yml
* Revert eng/common changes, ensure global $(HasChanges) is set properly
* Changes to enable testing
* 1.1.0-beta.1
* vcpkg clone should clone at configured branch
* Clone "main" branch of vcpkg betas
* Undo test-specific changes
* More PR cleanup
* PR cleanup
* Helm charts (#3841)
* helm chart
* first pipe setup
* poi
* magiks
* ewewe
* stress
* cleanup
* pr
* QFE and readme
* clang
* stupid clang , waste of time
* ewqwewewrqrewewrqewrqwrqr
* stupid clang
* cspell
* PR
* try try again
* clang again
* Sync eng/common directory with azure-sdk-tools for PR 3661 (#3846)
* Add full clone fallback to sparse checkout
* Improve clone handling and overrides for sparse checkout
* Use SkipSparseCheckout variable name
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Sync eng/common directory with azure-sdk-tools for PR 3735 (#3845)
* Detect API changes using new snadboxinx approach
* Added strictmode
* Remove unset variable
* Changes as per strict mode 3
* Rervert strict mode to allow language level fixes to merge first
Co-authored-by: praveenkuttappan <prmarott@microsoft.com>
* Increment version for keyvault releases (#3809)
* Increment package version after release of azure-security-keyvault-keys
* Increment package version after release of azure-security-keyvault-secrets
* Increment package version after release of azure-security-keyvault-certificates
* Removed hard dependency on opentelemetry version (#3844)
* Revert "Add full clone fallback to sparse checkout (#3661)" (#3851)
This reverts commit 7605ead00308dd20f20f2afe5acc4ec9900a2c47.
Co-authored-by: Ben Broderick Phillips <ben@benbp.net>
* Sync eng/common directory with azure-sdk-tools for PR 3753 (#3857)
* Bump MacOs version to macos-11
* Update eng/common/scripts/job-matrix/tests/job-matrix-functions.tests.ps1
Co-authored-by: Wes Haggard <weshaggard@users.noreply.github.com>
* Update eng/common/scripts/job-matrix/tests/job-matrix-functions.tests.ps1
Co-authored-by: Wes Haggard <weshaggard@users.noreply.github.com>
Co-authored-by: sima-zhu <sizhu@microsoft.com>
Co-authored-by: Sima Zhu <48036328+sima-zhu@users.noreply.github.com>
Co-authored-by: Wes Haggard <weshaggard@users.noreply.github.com>
* Bump macOs version to macos-11 (#3853)
* Update CHANGELOG.md
* Fix misleading step name in az module install (#3859)
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Retry poll calls on EINTR (#3858)
When signals are delievered to the process, calls here to poll may be
interrupted and return with a spurious failure. The call instead should be
restarted.
* Fix bad path to sample matrix json (#3860)
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Sync eng/common directory with azure-sdk-tools for PR 3826 (#3863)
* Add link checking for stress CI
* Remove region segment from stress testing links
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Core August releases (#3862)
* Core August releases
* cspell
Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
* Increment version for core releases (#3865)
* Increment package version after release of azure-core
* Increment package version after release of azure-core-tracing-opentelemetry
* Storage Aug GA release (#3864)
* CG only runs on internal (#3866)
* Condition added and indentation changes
* STG 79 80 81 Features (#3850)
* Sync eng/common directory with azure-sdk-tools for PR 3860 (#3871)
* updating pfx and cert
* update the targeted version of the proxy as well
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
* Storage August Preview Release (#3868)
* Storage August Preview Release
* update versions
* Increment version for storage releases (#3875)
* Increment package version after release of azure-storage-common
* Increment package version after release of azure-storage-blobs
* Fix an issue that reason phrase is missing as expected from HTTP/2 server (#3879)
* Fix an issue that reason phrase is missing as expected from HTTP/2 server
* reverse the condition
* compact comments
* fix clang format
* Update CODEOWNERS (#3881)
* updated targeted proxy version to one that properly allows consumption of TLS certificates (#3888)
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
* Fix `azure-storage-blobs-cpp` beta install (#3889)
Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
* Fixed #3899 - Handle new OSX version correctly; reformatted platform-matrix JSON files (#3900)
* Simpler get-binarysizes check for OSX (#3901)
* Simpler get-binarysizes check for OSX
* Missed wildcard
* Sync eng/common directory with azure-sdk-tools for PR 3874 (#3907)
* Add sparse checkout to perf template
* Rename base template, add parameters
* Add comment
* Add TODO
* Fix copy/pase bug, add language to artifacts path
* Fix language ref
* Fix python language
* perf.yml extends perf-base.yml
* Remove unnecessary base yml
* Fetch pull request refs
* Fix refs path
* Fetch commitish if matches PR syntax
* Print command before running
* Add PR commitish to remote.origin.fetch
* Add pool and vmimage parameters
* Map ref under "refs/remotes/origin"
* Add ref to refs/remotes/origin
Co-authored-by: Mike Harder <mharder@microsoft.com>
* File Share Features until STG82 (#3908)
* Empty file or existing file won't be created/overwritten if the blob to be downloaded doesn't exist. (#3910)
* Remove unnecessary checkout: none that causes conflicts with sparse checkout declarations (#3915)
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Core September Release (#3913)
Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
* Increment package version after release of azure-core (#3919)
* Migrate SkipDefaultCheckout to SkipCheckoutNone (#3916)
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Storage Sept Release (#3914)
* Increment version for storage releases (#3924)
* Increment package version after release of azure-storage-common
* Increment package version after release of azure-storage-blobs
* Increment package version after release of azure-storage-files-shares
* Add github actions based check enforcer (#3922)
* Add `$schema` to `cgmanifest.json` (#3918)
Co-authored-by: Jamie Magee <jamie.magee@microsoft.com>
* Remove SkipDefaultCheckout parameter (#3930)
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Compatibility improvement for striped blob (#3932)
* add a parameter 'condition' to the test-proxy ci invocations. (#3931)
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
* storage ad-hoc release (#3934)
* Increment package version after release of azure-storage-blobs (#3935)
* Update `AttestationClient::AttestTpm` API to match existing `AttestOpenEnclave` and `AttestSgxmEnclave` (#3928)
* Fix broken link and typo in contributing.md
* Use vector<uint8_t> for attest instead of strings
* remove options
* fix comments
* update release version
* remove versionig
* revert changelog
* add the change
* update comment
* Update sdk/attestation/azure-security-attestation/CHANGELOG.md
Co-authored-by: Larry Osterman <LarryOsterman@users.noreply.github.com>
* fix formatting
* address pr comment
* fix formating
* update a comment
* remove the attest tpm comment
Co-authored-by: Peng Li <pengfeli@microsoft.com>
Co-authored-by: Larry Osterman <LarryOsterman@users.noreply.github.com>
* Update check enforcer yaml permissions and name (#3944)
* Set VCPKG_ROOT (#3938)
* Set VCPKG_ROOT
* Update eng/pipelines/templates/steps/vcpkg-clone.yml
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
* Sync the devops helper scripts between azure-sdk repo and tools repo (#3949)
This should fix https://github.com/Azure/azure-sdk-tools/issues/3538
as it will now upgrade the devops extension to the latest version
which has the auth fix needed.
Co-authored-by: Wes Haggard <Wes.Haggard@microsoft.com>
* Add Win32FileTimeConverter (#3941)
* Sync eng/common directory with azure-sdk-tools for PR 4169 (#3950)
* pin newest version of proxy
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
* Enable Query() test in blob SDK (#3960)
* Sync eng/common directory with azure-sdk-tools for PR 4212 (#3962)
* version including lock fixes
* target the correct proxy version
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
* Pipeline core (#3953)
* test1
* glob
* quick cleanup
* ddasda
* ddsa
* envs
* dsds
* Revert "ddsa"
This reverts commit 6d9e385284ba37736fb5bc41e56065943abd7937.
* wq
* comment out issues
* valid test
* maybe
* qwewqewq
* lang steps
* Vcpkg pre-steps in the place Daniel should've recommend they go
* RepoOwner
* Correct repo owner name
* Remove vcpkg.yml (we don't need to write)
* PR trigger
* small change
* Update eng/pipelines/templates/jobs/perf.yml
Co-authored-by: Mike Harder <mharder@microsoft.com>
* Update eng/pipelines/templates/jobs/perf.yml
Co-authored-by: Mike Harder <mharder@microsoft.com>
* Update sdk/core/perf.yml
Co-authored-by: Mike Harder <mharder@microsoft.com>
Co-authored-by: Daniel Jurek <djurek@microsoft.com>
Co-authored-by: Mike Harder <mharder@microsoft.com>
* Win32FileTimeConverter (#3967)
* Sync eng/common directory with azure-sdk-tools for PR 4240 (#3965)
* use version of docker with CLI present
* target repaired executable
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
* Revert "Add Win32FileTimeConverter (#3941)" (#3966)
This reverts commit 14e4f52b91.
* add test case for batch options on snapshots and versions (#3970)
* add test case for batch options on snapshots and versions
* recording
* Merge feature/datalakestg82 (#3973)
* Build subscription configuration from cloud config values (#3976)
* fix LROs in keyvault (#3952)
* fix LROs in keyvault
* qfe
* some cleanup
* fdd
* clangs
* correct fix
* oops
* Pull all Websockets changes to main except for WebSockets itself. (#3954)
* Pulled WebSocket fixes into main except for WebSockets functionality
Co-authored-by: Rick Winter <rick.winter@microsoft.com>
Co-authored-by: Daniel Jurek <djurek@microsoft.com>
Co-authored-by: George Arama <50641385+gearama@users.noreply.github.com>
Co-authored-by: Ahson Khan <ahson_ahmedk@yahoo.com>
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
* Upadte Attestation changelog.md (#3992)
* Remove cspell directive from being visible (#3993)
* Post-merge changes to websockets code
* Update Attestation readme.md (#3991)
* Added back WebSocket_server.py
* Added Start-WebSocketServer.ps1 to list of files to copy
* clang-format
* Fixed memory leak in curl (#3995)
* Fixed memory leak in curl
* fixed documentation in unique_handle.hpp
Co-authored-by: George Arama <50641385+gearama@users.noreply.github.com>
Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com>
Co-authored-by: sima-zhu <sizhu@microsoft.com>
Co-authored-by: Ahson Khan <ahson_ahmedk@yahoo.com>
Co-authored-by: Mike Harder <mharder@microsoft.com>
Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com>
Co-authored-by: Daniel Jurek <djurek@microsoft.com>
Co-authored-by: Heath Stewart <heaths@microsoft.com>
Co-authored-by: Ben Broderick Phillips <bebroder@microsoft.com>
Co-authored-by: praveenkuttappan <prmarott@microsoft.com>
Co-authored-by: Ben Broderick Phillips <ben@benbp.net>
Co-authored-by: Sima Zhu <48036328+sima-zhu@users.noreply.github.com>
Co-authored-by: Wes Haggard <weshaggard@users.noreply.github.com>
Co-authored-by: Rick Winter <rick.winter@microsoft.com>
Co-authored-by: John Heffner <john@topofcenter.net>
Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>
Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
Co-authored-by: JinmingHu <jinmhu@microsoft.com>
Co-authored-by: Jonathan Cárdenas <JonathanCrd@users.noreply.github.com>
Co-authored-by: keshen-msft <53491277+keshen-msft@users.noreply.github.com>
Co-authored-by: microzchang <110015819+microzchang@users.noreply.github.com>
Co-authored-by: Jamie Magee <jamie.magee@gmail.com>
Co-authored-by: Jamie Magee <jamie.magee@microsoft.com>
Co-authored-by: Peng Li <86324823+penglimsft@users.noreply.github.com>
Co-authored-by: Peng Li <pengfeli@microsoft.com>
Co-authored-by: Wes Haggard <Wes.Haggard@microsoft.com>
938 lines
29 KiB
PowerShell
938 lines
29 KiB
PowerShell
|
|
$ReleaseDevOpsOrgParameters = @("--organization", "https://dev.azure.com/azure-sdk")
|
|
$ReleaseDevOpsCommonParameters = $ReleaseDevOpsOrgParameters + @("--output", "json")
|
|
$ReleaseDevOpsCommonParametersWithProject = $ReleaseDevOpsCommonParameters + @("--project", "Release")
|
|
|
|
function Get-DevOpsRestHeaders()
|
|
{
|
|
$headers = $null
|
|
if (Get-Variable -Name "devops_pat" -ValueOnly -ErrorAction "Ignore")
|
|
{
|
|
$encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes([string]::Format("{0}:{1}", "", $devops_pat)))
|
|
$headers = @{ Authorization = "Basic $encodedToken" }
|
|
}
|
|
else
|
|
{
|
|
# Get a temp access token from the logged in az cli user for azure devops resource
|
|
$jwt_accessToken = (az account get-access-token --resource "499b84ac-1321-427f-aa17-267ca6975798" --query "accessToken" --output tsv)
|
|
$headers = @{ Authorization = "Bearer $jwt_accessToken" }
|
|
}
|
|
|
|
return $headers
|
|
}
|
|
|
|
function CheckDevOpsAccess()
|
|
{
|
|
# Dummy test query to validate permissions
|
|
$query = "SELECT [System.ID] FROM WorkItems WHERE [Work Item Type] = 'Package' AND [Package] = 'azure-sdk-template'"
|
|
|
|
$response = Invoke-RestMethod -Method POST `
|
|
-Uri "https://dev.azure.com/azure-sdk/Release/_apis/wit/wiql/?api-version=6.0" `
|
|
-Headers (Get-DevOpsRestHeaders) -Body "{ ""query"": ""$query"" }" -ContentType "application/json" | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashTable
|
|
|
|
if ($response -isnot [HashTable] -or !$response.ContainsKey("workItems")) {
|
|
throw "Failed to run test query against Azure DevOps. Please ensure you are logged into the public azure cloud. Consider running 'az logout' and then 'az login'."
|
|
}
|
|
}
|
|
|
|
function Invoke-AzBoardsCmd($subCmd, $parameters, $output = $true)
|
|
{
|
|
$azCmdStr = "az boards ${subCmd} $($parameters -join ' ')"
|
|
if ($output) {
|
|
Write-Host $azCmdStr
|
|
}
|
|
return Invoke-Expression "$azCmdStr" | ConvertFrom-Json -AsHashTable
|
|
}
|
|
|
|
function Invoke-Query($fields, $wiql, $output = $true)
|
|
{
|
|
#POST https://dev.azure.com/{organization}/{project}/{team}/_apis/wit/wiql?timePrecision={timePrecision}&$top={$top}&api-version=6.1-preview.2
|
|
|
|
$body = @"
|
|
{
|
|
"query": "$wiql"
|
|
}
|
|
"@
|
|
|
|
if ($output) {
|
|
Write-Host "Executing query $wiql"
|
|
}
|
|
|
|
$response = Invoke-RestMethod -Method POST `
|
|
-Uri "https://dev.azure.com/azure-sdk/Release/_apis/wit/wiql/?`$top=10000&api-version=6.0" `
|
|
-Headers (Get-DevOpsRestHeaders) -Body $body -ContentType "application/json" | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashTable
|
|
|
|
if ($response -isnot [HashTable] -or !$response.ContainsKey("workItems") -or $response.workItems.Count -eq 0) {
|
|
Write-Verbose "Query returned no items. $wiql"
|
|
return ,@()
|
|
}
|
|
|
|
$workItems = @()
|
|
$i = 0
|
|
do
|
|
{
|
|
$idBatch = @()
|
|
while ($idBatch.Count -lt 200 -and $i -lt $response.workItems.Count)
|
|
{
|
|
$idBatch += $response.workItems[$i].id
|
|
$i++
|
|
}
|
|
|
|
$uri = "https://dev.azure.com/azure-sdk/Release/_apis/wit/workitems?ids=$($idBatch -join ',')&fields=$($fields -join ',')&api-version=6.0"
|
|
|
|
Write-Verbose "Pulling work items $uri "
|
|
|
|
$batchResponse = Invoke-RestMethod -Method GET -Uri $uri `
|
|
-Headers (Get-DevOpsRestHeaders) -ContentType "application/json" -MaximumRetryCount 3 | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashTable
|
|
|
|
if ($batchResponse.value)
|
|
{
|
|
$batchResponse.value | ForEach-Object { $workItems += $_ }
|
|
}
|
|
else
|
|
{
|
|
Write-Warning "Batch return no items from $uri"
|
|
}
|
|
}
|
|
while ($i -lt $response.workItems.Count)
|
|
|
|
if ($output) {
|
|
Write-Host "Query return $($workItems.Count) items"
|
|
}
|
|
|
|
return $workItems
|
|
}
|
|
|
|
function LoginToAzureDevops([string]$devops_pat)
|
|
{
|
|
if (!$devops_pat) {
|
|
return
|
|
}
|
|
# based on the docs at https://aka.ms/azure-devops-cli-auth the recommendation is to set this env variable to login
|
|
$env:AZURE_DEVOPS_EXT_PAT = $devops_pat
|
|
}
|
|
|
|
function BuildHashKeyNoNull()
|
|
{
|
|
$filterNulls = $args | Where-Object { $_ }
|
|
# if we had any nulls then return null
|
|
if (!$filterNulls -or $args.Count -ne $filterNulls.Count) {
|
|
return $null
|
|
}
|
|
return BuildHashKey $args
|
|
}
|
|
|
|
function BuildHashKey()
|
|
{
|
|
# if no args or the first arg is null return null
|
|
if ($args.Count -lt 1 -or !$args[0]) {
|
|
return $null
|
|
}
|
|
|
|
# exclude null values
|
|
$keys = $args | Where-Object { $_ }
|
|
return $keys -join "|"
|
|
}
|
|
|
|
$parentWorkItems = @{}
|
|
function FindParentWorkItem($serviceName, $packageDisplayName, $outputCommand = $false)
|
|
{
|
|
$key = BuildHashKey $serviceName $packageDisplayName
|
|
if ($key -and $parentWorkItems.ContainsKey($key)) {
|
|
return $parentWorkItems[$key]
|
|
}
|
|
|
|
if ($serviceName) {
|
|
$serviceCondition = "[ServiceName] = '${serviceName}'"
|
|
if ($packageDisplayName) {
|
|
$serviceCondition += " AND [PackageDisplayName] = '${packageDisplayName}'"
|
|
}
|
|
else {
|
|
$serviceCondition += " AND [PackageDisplayName] = ''"
|
|
}
|
|
}
|
|
else {
|
|
$serviceCondition = "[ServiceName] <> ''"
|
|
}
|
|
|
|
$query = "SELECT [ID], [ServiceName], [PackageDisplayName], [Parent] FROM WorkItems WHERE [Work Item Type] = 'Epic' AND ${serviceCondition}"
|
|
|
|
$fields = @("System.Id", "Custom.ServiceName", "Custom.PackageDisplayName", "System.Parent")
|
|
|
|
$workItems = Invoke-Query $fields $query $outputCommand
|
|
|
|
foreach ($wi in $workItems)
|
|
{
|
|
$localKey = BuildHashKey $wi.fields["Custom.ServiceName"] $wi.fields["Custom.PackageDisplayName"]
|
|
if (!$localKey) { continue }
|
|
if ($parentWorkItems.ContainsKey($localKey) -and $parentWorkItems[$localKey].id -ne $wi.id) {
|
|
Write-Warning "Already found parent [$($parentWorkItems[$localKey].id)] with key [$localKey], using that one instead of [$($wi.id)]."
|
|
}
|
|
else {
|
|
Write-Verbose "[$($wi.id)]$localKey - Cached"
|
|
$parentWorkItems[$localKey] = $wi
|
|
}
|
|
}
|
|
|
|
if ($key -and $parentWorkItems.ContainsKey($key)) {
|
|
return $parentWorkItems[$key]
|
|
}
|
|
return $null
|
|
}
|
|
|
|
$packageWorkItems = @{}
|
|
$packageWorkItemWithoutKeyFields = @{}
|
|
|
|
function FindLatestPackageWorkItem($lang, $packageName, $outputCommand = $true)
|
|
{
|
|
# Cache all the versions of this package and language work items
|
|
$null = FindPackageWorkItem $lang $packageName -includeClosed $true -outputCommand $outputCommand
|
|
|
|
$latestWI = $null
|
|
foreach ($wi in $packageWorkItems.Values)
|
|
{
|
|
if ($wi.fields["Custom.Language"] -ne $lang) { continue }
|
|
if ($wi.fields["Custom.Package"] -ne $packageName) { continue }
|
|
|
|
if (!$latestWI) {
|
|
$latestWI = $wi
|
|
continue
|
|
}
|
|
|
|
if (($wi.fields["Custom.PackageVersionMajorMinor"] -as [Version]) -gt ($latestWI.fields["Custom.PackageVersionMajorMinor"] -as [Version])) {
|
|
$latestWI = $wi
|
|
}
|
|
}
|
|
return $latestWI
|
|
}
|
|
|
|
function FindPackageWorkItem($lang, $packageName, $version, $outputCommand = $true, $includeClosed = $false)
|
|
{
|
|
$key = BuildHashKeyNoNull $lang $packageName $version
|
|
if ($key -and $packageWorkItems.ContainsKey($key)) {
|
|
return $packageWorkItems[$key]
|
|
}
|
|
|
|
$fields = @()
|
|
$fields += "System.ID"
|
|
$fields += "System.State"
|
|
$fields += "System.AssignedTo"
|
|
$fields += "System.Parent"
|
|
$fields += "Custom.Language"
|
|
$fields += "Custom.Package"
|
|
$fields += "Custom.PackageDisplayName"
|
|
$fields += "System.Title"
|
|
$fields += "Custom.PackageType"
|
|
$fields += "Custom.PackageTypeNewLibrary"
|
|
$fields += "Custom.PackageVersionMajorMinor"
|
|
$fields += "Custom.PackageRepoPath"
|
|
$fields += "Custom.ServiceName"
|
|
$fields += "Custom.PlannedPackages"
|
|
$fields += "Custom.ShippedPackages"
|
|
$fields += "Custom.PackageBetaVersions"
|
|
$fields += "Custom.PackageGAVersion"
|
|
$fields += "Custom.PackagePatchVersions"
|
|
$fields += "Custom.Generated"
|
|
$fields += "Custom.RoadmapState"
|
|
$fields += "Microsoft.VSTS.Common.StateChangeDate"
|
|
|
|
$fieldList = ($fields | ForEach-Object { "[$_]"}) -join ", "
|
|
$query = "SELECT ${fieldList} FROM WorkItems WHERE [Work Item Type] = 'Package'"
|
|
|
|
if (!$includeClosed -and !$lang) {
|
|
$query += " AND [State] <> 'No Active Development' AND [PackageTypeNewLibrary] = true"
|
|
}
|
|
if ($lang) {
|
|
$query += " AND [Language] = '${lang}'"
|
|
}
|
|
if ($packageName) {
|
|
$query += " AND [Package] = '${packageName}'"
|
|
}
|
|
if ($version) {
|
|
$query += " AND [PackageVersionMajorMinor] = '${version}'"
|
|
}
|
|
|
|
$workItems = Invoke-Query $fields $query $outputCommand
|
|
|
|
foreach ($wi in $workItems)
|
|
{
|
|
$localKey = BuildHashKeyNoNull $wi.fields["Custom.Language"] $wi.fields["Custom.Package"] $wi.fields["Custom.PackageVersionMajorMinor"]
|
|
if (!$localKey) {
|
|
$packageWorkItemWithoutKeyFields[$wi.id] = $wi
|
|
Write-Host "Skipping package [$($wi.id)]$($wi.fields['System.Title']) which is missing required fields language, package, or version."
|
|
continue
|
|
}
|
|
if ($packageWorkItems.ContainsKey($localKey) -and $packageWorkItems[$localKey].id -ne $wi.id) {
|
|
Write-Warning "Already found package [$($packageWorkItems[$localKey].id)] with key [$localKey], using that one instead of [$($wi.id)]."
|
|
}
|
|
else {
|
|
Write-Verbose "Caching package [$($wi.id)] for [$localKey]"
|
|
$packageWorkItems[$localKey] = $wi
|
|
}
|
|
}
|
|
|
|
if ($key -and $packageWorkItems.ContainsKey($key)) {
|
|
return $packageWorkItems[$key]
|
|
}
|
|
return $null
|
|
}
|
|
|
|
function InitializeWorkItemCache($outputCommand = $true, $includeClosed = $false)
|
|
{
|
|
# Pass null to cache all service parents
|
|
$null = FindParentWorkItem -serviceName $null -packageDisplayName $null -outputCommand $outputCommand
|
|
|
|
# Pass null to cache all the package items
|
|
$null = FindPackageWorkItem -lang $null -packageName $null -version $null -outputCommand $outputCommand -includeClosed $includeClosed
|
|
}
|
|
|
|
function GetCachedPackageWorkItems()
|
|
{
|
|
return $packageWorkItems.Values
|
|
}
|
|
|
|
function UpdateWorkItemParent($childWorkItem, $parentWorkItem, $outputCommand = $true)
|
|
{
|
|
$childId = $childWorkItem.id
|
|
$existingParentId = $childWorkItem.fields["System.Parent"]
|
|
$newParentId = $parentWorkItem.id
|
|
|
|
if ($existingParentId -eq $newParentId) {
|
|
return
|
|
}
|
|
|
|
CreateWorkItemParent $childId $newParentId $existingParentId -outputCommand $outputCommand
|
|
$childWorkItem.fields["System.Parent"] = $newParentId
|
|
}
|
|
|
|
function CreateWorkItemParent($id, $parentId, $oldParentId, $outputCommand = $true)
|
|
{
|
|
# Have to remove old parent first if you want to add a new parent.
|
|
if ($oldParentId)
|
|
{
|
|
$parameters = $ReleaseDevOpsCommonParameters
|
|
$parameters += "--yes"
|
|
$parameters += "--id", $id
|
|
$parameters += "--relation-type", "parent"
|
|
$parameters += "--target-id", $oldParentId
|
|
|
|
Invoke-AzBoardsCmd "work-item relation remove" $parameters $outputCommand | Out-Null
|
|
}
|
|
|
|
$parameters = $ReleaseDevOpsCommonParameters
|
|
$parameters += "--id", $id
|
|
$parameters += "--relation-type", "parent"
|
|
$parameters += "--target-id", $parentId
|
|
|
|
Invoke-AzBoardsCmd "work-item relation add" $parameters $outputCommand | Out-Null
|
|
}
|
|
function CreateWorkItem($title, $type, $iteration, $area, $fields, $assignedTo, $parentId, $outputCommand = $true)
|
|
{
|
|
$parameters = $ReleaseDevOpsCommonParametersWithProject
|
|
$parameters += "--title", "`"${title}`""
|
|
$parameters += "--type", "`"${type}`""
|
|
$parameters += "--iteration", "`"${iteration}`""
|
|
$parameters += "--area", "`"${area}`""
|
|
if ($assignedTo) {
|
|
$parameters += "--assigned-to", "`"${assignedTo}`""
|
|
}
|
|
if ($fields) {
|
|
$parameters += "--fields"
|
|
$parameters += $fields
|
|
}
|
|
|
|
$workItem = Invoke-AzBoardsCmd "work-item create" $parameters $outputCommand
|
|
|
|
if ($parentId) {
|
|
$parameters = $ReleaseDevOpsCommonParameters
|
|
$parameters += "--id", $workItem.id
|
|
$parameters += "--relation-type", "parent"
|
|
$parameters += "--target-id", $parentId
|
|
|
|
Invoke-AzBoardsCmd "work-item relation add" $parameters $outputCommand | Out-Null
|
|
}
|
|
|
|
return $workItem
|
|
}
|
|
|
|
function UpdateWorkItem($id, $fields, $title, $state, $assignedTo, $outputCommand = $true)
|
|
{
|
|
$parameters = $ReleaseDevOpsCommonParameters
|
|
$parameters += "--id", $id
|
|
if ($title) {
|
|
$parameters += "--title", "`"${title}`""
|
|
}
|
|
if ($state) {
|
|
$parameters += "--state", "`"${state}`""
|
|
}
|
|
if ($assignedTo) {
|
|
$parameters += "--assigned-to", "`"${assignedTo}`""
|
|
}
|
|
if ($fields) {
|
|
$parameters += "--fields"
|
|
$parameters += $fields
|
|
}
|
|
|
|
return Invoke-AzBoardsCmd "work-item update" $parameters $outputCommand
|
|
}
|
|
|
|
function UpdatePackageWorkItemReleaseState($id, $state, $releaseType, $outputCommand = $true)
|
|
{
|
|
$fields = "`"Custom.ReleaseType=${releaseType}`""
|
|
return UpdateWorkItem -id $id -state $state -fields $fields -outputCommand $outputCommand
|
|
}
|
|
|
|
function FindOrCreateClonePackageWorkItem($lang, $pkg, $verMajorMinor, $allowPrompt = $false, $outputCommand = $false)
|
|
{
|
|
$workItem = FindPackageWorkItem -lang $lang -packageName $pkg.Package -version $verMajorMinor -includeClosed $true -outputCommand $outputCommand
|
|
|
|
if (!$workItem) {
|
|
$latestVersionItem = FindLatestPackageWorkItem -lang $lang -packageName $pkg.Package -outputCommand $outputCommand
|
|
$assignedTo = "me"
|
|
$extraFields = @()
|
|
if ($latestVersionItem) {
|
|
Write-Verbose "Copying data from latest matching [$($latestVersionItem.id)] with version $($latestVersionItem.fields["Custom.PackageVersionMajorMinor"])"
|
|
if ($latestVersionItem.fields["System.AssignedTo"]) {
|
|
$assignedTo = $latestVersionItem.fields["System.AssignedTo"]["uniqueName"]
|
|
}
|
|
$pkg.DisplayName = $latestVersionItem.fields["Custom.PackageDisplayName"]
|
|
$pkg.ServiceName = $latestVersionItem.fields["Custom.ServiceName"]
|
|
if (!$pkg.RepoPath -and $pkg.RepoPath -ne "NA" -and $pkg.fields["Custom.PackageRepoPath"]) {
|
|
$pkg.RepoPath = $pkg.fields["Custom.PackageRepoPath"]
|
|
}
|
|
|
|
if ($latestVersionItem.fields["Custom.Generated"]) {
|
|
$extraFields += "`"Generated=" + $latestVersionItem.fields["Custom.Generated"] + "`""
|
|
}
|
|
|
|
if ($latestVersionItem.fields["Custom.RoadmapState"]) {
|
|
$extraFields += "`"RoadmapState=" + $latestVersionItem.fields["Custom.RoadmapState"] + "`""
|
|
}
|
|
}
|
|
|
|
if ($allowPrompt) {
|
|
if (!$pkg.DisplayName) {
|
|
Write-Host "Display name is used to identify this package across languages and is usually the friendly name (i.e. For 'Azure Anomaly Detector' it would be 'Anomaly Detector'. For 'Azure Cognitive Search' it would be 'Search'.). See https://aka.ms/azsdk/mark-release-status for more info."
|
|
while (($readInput = Read-Host -Prompt "Input the display name") -eq "") { }
|
|
$packageInfo.DisplayName = $readInput
|
|
}
|
|
|
|
if (!$pkg.ServiceName) {
|
|
Write-Host "This is the friendly service name for this package that is used to align it with other packages and languages (i.e., no need to include 'Azure' or 'Microsoft' in the title). The service name is sometimes the same as the `Package Display Name` if there is only one package for a service. (i.e. For 'Azure Anomaly Detector' it would be 'Anomaly Detector'). For services that ship multiple packages be sure to list the service only. (i.e. For 'Schema Registry Avro', the service name is just 'Schema Registry'; For 'Key Vault Certificates', the service name is simply Key Vault.). See https://aka.ms/azsdk/mark-release-status for more info."
|
|
while (($readInput = Read-Host -Prompt "Input the service name") -eq "") { }
|
|
$packageInfo.ServiceName = $readInput
|
|
}
|
|
}
|
|
|
|
|
|
$workItem = CreateOrUpdatePackageWorkItem $lang $pkg $verMajorMinor -existingItem $null -assignedTo $assignedTo -extraFields $extraFields -outputCommand $outputCommand
|
|
}
|
|
|
|
return $workItem
|
|
}
|
|
|
|
function CreateOrUpdatePackageWorkItem($lang, $pkg, $verMajorMinor, $existingItem, $assignedTo = $null, $extraFields = $null, $outputCommand = $true)
|
|
{
|
|
if (!$lang -or !$pkg -or !$verMajorMinor) {
|
|
Write-Host "Cannot create or update because one of lang, pkg or verMajorMinor aren't set. [$lang|$($pkg.Package)|$verMajorMinor]"
|
|
return
|
|
}
|
|
$pkgName = $pkg.Package
|
|
$pkgDisplayName = $pkg.DisplayName
|
|
$pkgType = $pkg.Type
|
|
$pkgNewLibrary = $pkg.New
|
|
$pkgRepoPath = $pkg.RepoPath
|
|
$serviceName = $pkg.ServiceName
|
|
$title = $lang + " - " + $pkg.DisplayName + " - " + $verMajorMinor
|
|
|
|
$fields = @()
|
|
$fields += "`"Language=${lang}`""
|
|
$fields += "`"Package=${pkgName}`""
|
|
$fields += "`"PackageDisplayName=${pkgDisplayName}`""
|
|
$fields += "`"PackageType=${pkgType}`""
|
|
$fields += "`"PackageTypeNewLibrary=${pkgNewLibrary}`""
|
|
$fields += "`"PackageVersionMajorMinor=${verMajorMinor}`""
|
|
$fields += "`"ServiceName=${serviceName}`""
|
|
$fields += "`"PackageRepoPath=${pkgRepoPath}`""
|
|
|
|
if ($extraFields) {
|
|
$fields += $extraFields
|
|
}
|
|
|
|
if ($existingItem)
|
|
{
|
|
$changedField = $null
|
|
|
|
if ($lang -ne $existingItem.fields["Custom.Language"]) { $changedField = "Custom.Language" }
|
|
if ($pkgName -ne $existingItem.fields["Custom.Package"]) { $changedField = "Custom.Package" }
|
|
if ($verMajorMinor -ne $existingItem.fields["Custom.PackageVersionMajorMinor"]) { $changedField = "Custom.PackageVersionMajorMinor" }
|
|
if ($pkgDisplayName -ne $existingItem.fields["Custom.PackageDisplayName"]) { $changedField = "Custom.PackageDisplayName" }
|
|
if ($pkgType -ne [string]$existingItem.fields["Custom.PackageType"]) { $changedField = "Custom.PackageType" }
|
|
if ($pkgNewLibrary -ne $existingItem.fields["Custom.PackageTypeNewLibrary"]) { $changedField = "Custom.PackageTypeNewLibrary" }
|
|
if ($pkgRepoPath -ne $existingItem.fields["Custom.PackageRepoPath"]) { $changedField = "Custom.PackageRepoPath" }
|
|
if ($serviceName -ne $existingItem.fields["Custom.ServiceName"]) { $changedField = "Custom.ServiceName" }
|
|
if ($title -ne $existingItem.fields["System.Title"]) { $changedField = "System.Title" }
|
|
|
|
if ($changedField) {
|
|
Write-Host "At least field $changedField ($($existingItem.fields[$changedField])) changed so updating."
|
|
}
|
|
|
|
if ($changedField) {
|
|
$beforeState = $existingItem.fields["System.State"]
|
|
|
|
# Need to set to New to be able to update
|
|
$existingItem = UpdateWorkItem -id $existingItem.id -fields $fields -title $title -state "New" -assignedTo $assignedTo -outputCommand $outputCommand
|
|
Write-Host "[$($existingItem.id)]$lang - $pkgName($verMajorMinor) - Updated"
|
|
|
|
if ($beforeState -ne $existingItem.fields['System.State']) {
|
|
Write-Verbose "Resetting state for [$($existingItem.id)] from '$($existingItem.fields['System.State'])' to '$beforeState'"
|
|
$existingItem = UpdateWorkItem $existingItem.id -state $beforeState -outputCommand $outputCommand
|
|
}
|
|
}
|
|
|
|
$newparentItem = FindOrCreatePackageGroupParent $serviceName $pkgDisplayName -outputCommand $false
|
|
UpdateWorkItemParent $existingItem $newParentItem -outputCommand $outputCommand
|
|
return $existingItem
|
|
}
|
|
|
|
$parentItem = FindOrCreatePackageGroupParent $serviceName $pkgDisplayName -outputCommand $false
|
|
$workItem = CreateWorkItem $title "Package" "Release" "Release" $fields $assignedTo $parentItem.id -outputCommand $outputCommand
|
|
Write-Host "[$($workItem.id)]$lang - $pkgName($verMajorMinor) - Created"
|
|
return $workItem
|
|
}
|
|
|
|
function FindOrCreatePackageGroupParent($serviceName, $packageDisplayName, $outputCommand = $true)
|
|
{
|
|
$existingItem = FindParentWorkItem $serviceName $packageDisplayName -outputCommand $outputCommand
|
|
if ($existingItem) {
|
|
$newparentItem = FindOrCreateServiceParent $serviceName -outputCommand $outputCommand
|
|
UpdateWorkItemParent $existingItem $newParentItem
|
|
return $existingItem
|
|
}
|
|
|
|
$fields = @()
|
|
$fields += "`"PackageDisplayName=${packageDisplayName}`""
|
|
$fields += "`"ServiceName=${serviceName}`""
|
|
$serviceParentItem = FindOrCreateServiceParent $serviceName -outputCommand $outputCommand
|
|
$workItem = CreateWorkItem $packageDisplayName "Epic" "Release" "Release" $fields $null $serviceParentItem.id
|
|
|
|
$localKey = BuildHashKey $serviceName $packageDisplayName
|
|
Write-Host "[$($workItem.id)]$localKey - Created Parent"
|
|
$parentWorkItems[$localKey] = $workItem
|
|
return $workItem
|
|
}
|
|
|
|
function FindOrCreateServiceParent($serviceName, $outputCommand = $true)
|
|
{
|
|
$serviceParent = FindParentWorkItem $serviceName -outputCommand $outputCommand
|
|
if ($serviceParent) {
|
|
return $serviceParent
|
|
}
|
|
|
|
$fields = @()
|
|
$fields += "`"PackageDisplayName=`""
|
|
$fields += "`"ServiceName=${serviceName}`""
|
|
$parentId = $null
|
|
$workItem = CreateWorkItem $serviceName "Epic" "Release" "Release" $fields $null $parentId -outputCommand $outputCommand
|
|
|
|
$localKey = BuildHashKey $serviceName
|
|
Write-Host "[$($workItem.id)]$localKey - Created"
|
|
$parentWorkItems[$localKey] = $workItem
|
|
return $workItem
|
|
}
|
|
|
|
function ParseVersionSetFromMDField([string]$field)
|
|
{
|
|
$MDTableRegex = "\|\s*(?<t>\S*)\s*\|\s*(?<v>\S*)\s*\|\s*(?<d>\S*)\s*\|"
|
|
$versionSet = @{}
|
|
$tableMatches = [Regex]::Matches($field, $MDTableRegex)
|
|
|
|
foreach ($match in $tableMatches)
|
|
{
|
|
if ($match.Groups["t"].Value -eq "Type" -or $match.Groups["t"].Value -eq "-") {
|
|
continue
|
|
}
|
|
$version = New-Object PSObject -Property @{
|
|
Type = $match.Groups["t"].Value
|
|
Version = $match.Groups["v"].Value
|
|
Date = $match.Groups["d"].Value
|
|
}
|
|
if (!$versionSet.ContainsKey($version.Version)) {
|
|
$versionSet[$version.Version] = $version
|
|
}
|
|
}
|
|
return $versionSet
|
|
}
|
|
|
|
function GetTextVersionFields($versionList, $pkgWorkItem)
|
|
{
|
|
$betaVersions = $gaVersions = $patchVersions = ""
|
|
foreach ($v in $versionList) {
|
|
$vstr = "$($v.Version),$($v.Date)"
|
|
if ($v.Type -eq "Beta") {
|
|
if ($betaVersions.Length + $vstr.Length -lt 255) {
|
|
if ($betaVersions.Length -gt 0) { $betaVersions += "|" }
|
|
$betaVersions += $vstr
|
|
}
|
|
}
|
|
elseif ($v.Type -eq "GA") {
|
|
if ($gaVersions.Length + $vstr.Length -lt 255) {
|
|
if ($gaVersions.Length -gt 0) { $gaVersions += "|" }
|
|
$gaVersions += $vstr
|
|
}
|
|
}
|
|
elseif ($v.Type -eq "Patch") {
|
|
if ($patchVersions.Length + $vstr.Length -lt 255) {
|
|
if ($patchVersions.Length -gt 0) { $patchVersions += "|" }
|
|
$patchVersions += $vstr
|
|
}
|
|
}
|
|
}
|
|
|
|
$fieldUpdates = @()
|
|
if ("$($pkgWorkItem.fields["Custom.PackageBetaVersions"])" -ne $betaVersions)
|
|
{
|
|
$fieldUpdates += @"
|
|
{
|
|
"op": "replace",
|
|
"path": "/fields/PackageBetaVersions",
|
|
"value": "$betaVersions"
|
|
}
|
|
"@
|
|
}
|
|
|
|
if ("$($pkgWorkItem.fields["Custom.PackageGAVersion"])" -ne $gaVersions)
|
|
{
|
|
$fieldUpdates += @"
|
|
{
|
|
"op": "replace",
|
|
"path": "/fields/PackageGAVersion",
|
|
"value": "$gaVersions"
|
|
}
|
|
"@
|
|
}
|
|
|
|
if ("$($pkgWorkItem.fields["Custom.PackagePatchVersions"])" -ne $patchVersions)
|
|
{
|
|
$fieldUpdates += @"
|
|
{
|
|
"op": "replace",
|
|
"path": "/fields/PackagePatchVersions",
|
|
"value": "$patchVersions"
|
|
}
|
|
"@
|
|
}
|
|
return ,$fieldUpdates
|
|
}
|
|
|
|
function GetMDVersionValue($versionlist)
|
|
{
|
|
$mdVersions = ""
|
|
$mdFormat = "| {0} | {1} | {2} |`n"
|
|
|
|
$htmlVersions = ""
|
|
$htmlFormat = @"
|
|
<tr>
|
|
<td>{0}</td>
|
|
<td>{1}</td>
|
|
<td>{2}</td>
|
|
</tr>
|
|
|
|
"@
|
|
|
|
foreach ($version in $versionList) {
|
|
$mdVersions += ($mdFormat -f $version.Type, $version.Version, $version.Date)
|
|
$htmlVersions += ($htmlFormat -f $version.Type, $version.Version, $version.Date)
|
|
}
|
|
|
|
$htmlTemplate = @"
|
|
<div style='display:none;width:0;height:0;overflow:hidden;position:absolute;font-size:0;' id=__md>| Type | Version | Date |
|
|
| - | - | - |
|
|
mdVersions
|
|
</div><style id=__mdStyle>
|
|
.rendered-markdown img {
|
|
cursor:pointer;
|
|
}
|
|
|
|
.rendered-markdown h1, .rendered-markdown h2, .rendered-markdown h3, .rendered-markdown h4, .rendered-markdown h5, .rendered-markdown h6 {
|
|
color:#007acc;
|
|
font-weight:400;
|
|
}
|
|
|
|
.rendered-markdown h1 {
|
|
border-bottom:1px solid #e6e6e6;
|
|
font-size:26px;
|
|
font-weight:600;
|
|
margin-bottom:20px;
|
|
}
|
|
|
|
.rendered-markdown h2 {
|
|
font-size:18px;
|
|
border-bottom:1px solid #e6e6e6;
|
|
font-weight:600;
|
|
color:#303030;
|
|
margin-bottom:10px;
|
|
margin-top:20px;
|
|
}
|
|
|
|
.rendered-markdown h3 {
|
|
font-size:16px;
|
|
font-weight:600;
|
|
margin-bottom:10px;
|
|
}
|
|
|
|
.rendered-markdown h4 {
|
|
font-size:14px;
|
|
margin-bottom:10px;
|
|
}
|
|
|
|
.rendered-markdown h5 {
|
|
font-size:12px;
|
|
margin-bottom:10px;
|
|
}
|
|
|
|
.rendered-markdown h6 {
|
|
font-size:12px;
|
|
font-weight:300;
|
|
margin-bottom:10px;
|
|
}
|
|
|
|
.rendered-markdown.metaitem {
|
|
font-size:12px;
|
|
padding-top:15px;
|
|
}
|
|
|
|
.rendered-markdown.metavalue {
|
|
font-size:12px;
|
|
padding-left:4px;
|
|
}
|
|
|
|
.rendered-markdown.metavalue>img {
|
|
height:32px;
|
|
width:32px;
|
|
margin-bottom:3px;
|
|
padding-left:1px;
|
|
}
|
|
|
|
.rendered-markdown li.metavaluelink {
|
|
list-style-type:disc;
|
|
list-style-position:inside;
|
|
}
|
|
|
|
.rendered-markdown li.metavalue>a {
|
|
border:none;
|
|
padding:0;
|
|
display:inline;
|
|
}
|
|
|
|
.rendered-markdown li.metavalue>a:hover {
|
|
background-color:inherit;
|
|
text-decoration:underline;
|
|
}
|
|
|
|
.rendered-markdown code, .rendered-markdown pre, .rendered-markdown samp {
|
|
font-family:Monaco,Menlo,Consolas,'Droid Sans Mono','Inconsolata','Courier New',monospace;
|
|
}
|
|
|
|
.rendered-markdown code {
|
|
color:#333;
|
|
background-color:#f8f8f8;
|
|
border:1px solid #ccc;
|
|
border-radius:3px;
|
|
padding:2px 4px;
|
|
font-size:90%;
|
|
line-height:2;
|
|
white-space:nowrap;
|
|
}
|
|
|
|
.rendered-markdown pre {
|
|
color:#333;
|
|
background-color:#f8f8f8;
|
|
border:1px solid #ccc;
|
|
display:block;
|
|
padding:6px;
|
|
font-size:13px;
|
|
word-break:break-all;
|
|
word-wrap:break-word;
|
|
}
|
|
|
|
.rendered-markdown pre code {
|
|
padding:0;
|
|
font-size:inherit;
|
|
color:inherit;
|
|
white-space:pre-wrap;
|
|
background-color:transparent;
|
|
line-height:1.428571429;
|
|
border:none;
|
|
}
|
|
|
|
.rendered-markdown.pre-scrollable {
|
|
max-height:340px;
|
|
overflow-y:scroll;
|
|
}
|
|
|
|
.rendered-markdown table {
|
|
border-collapse:collapse;
|
|
}
|
|
|
|
.rendered-markdown table {
|
|
width:auto;
|
|
}
|
|
|
|
.rendered-markdown table, .rendered-markdown th, .rendered-markdown td {
|
|
border:1px solid #ccc;
|
|
padding:4px;
|
|
}
|
|
|
|
.rendered-markdown th {
|
|
font-weight:bold;
|
|
background-color:#f8f8f8;
|
|
}
|
|
</style><div class=rendered-markdown><table>
|
|
<thead>
|
|
<tr>
|
|
<th>Type</th>
|
|
<th>Version</th>
|
|
<th>Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>htmlVersions</tbody>
|
|
</table>
|
|
</div>
|
|
"@ -replace "'", '\"'
|
|
|
|
return $htmlTemplate.Replace("mdVersions", $mdVersions).Replace("htmlVersions", "`n$htmlVersions");
|
|
}
|
|
|
|
function UpdatePackageVersions($pkgWorkItem, $plannedVersions, $shippedVersions)
|
|
{
|
|
# Create the planned and shipped versions, adding the new ones if any
|
|
$updatePlanned = $false
|
|
$plannedVersionSet = ParseVersionSetFromMDField $pkgWorkItem.fields["Custom.PlannedPackages"]
|
|
foreach ($version in $plannedVersions)
|
|
{
|
|
if (!$plannedVersionSet.ContainsKey($version.Version))
|
|
{
|
|
$plannedVersionSet[$version.Version] = $version
|
|
$updatePlanned = $true
|
|
}
|
|
else
|
|
{
|
|
# Lets check to see if someone wanted to update a date
|
|
$existingVersion = $plannedVersionSet[$version.Version]
|
|
if ($existingVersion.Date -ne $version.Date) {
|
|
$existingVersion.Date = $version.Date
|
|
$updatePlanned = $true
|
|
}
|
|
}
|
|
}
|
|
|
|
$updateShipped = $false
|
|
$shippedVersionSet = ParseVersionSetFromMDField $pkgWorkItem.fields["Custom.ShippedPackages"]
|
|
foreach ($version in $shippedVersions)
|
|
{
|
|
if (!$shippedVersionSet.ContainsKey($version.Version))
|
|
{
|
|
$shippedVersionSet[$version.Version] = $version
|
|
$updateShipped = $true
|
|
}
|
|
}
|
|
|
|
$versionSet = @{}
|
|
foreach ($version in $shippedVersionSet.Keys)
|
|
{
|
|
if (!$versionSet.ContainsKey($version))
|
|
{
|
|
$versionSet[$version] = $shippedVersionSet[$version]
|
|
}
|
|
}
|
|
|
|
foreach ($version in @($plannedVersionSet.Keys))
|
|
{
|
|
if (!$versionSet.ContainsKey($version))
|
|
{
|
|
$versionSet[$version] = $plannedVersionSet[$version]
|
|
}
|
|
else
|
|
{
|
|
# Looks like we shipped this version so remove it from the planned set
|
|
$plannedVersionSet.Remove($version)
|
|
$updatePlanned = $true
|
|
}
|
|
}
|
|
|
|
$fieldUpdates = @()
|
|
if ($updatePlanned)
|
|
{
|
|
$plannedPackages = GetMDVersionValue ($plannedVersionSet.Values | Sort-Object {$_.Date -as [DateTime]}, Version -Descending)
|
|
$fieldUpdates += @"
|
|
{
|
|
"op": "replace",
|
|
"path": "/fields/Planned Packages",
|
|
"value": "$plannedPackages"
|
|
}
|
|
"@
|
|
}
|
|
|
|
if ($updateShipped)
|
|
{
|
|
$newShippedVersions = $shippedVersionSet.Values | Sort-Object {$_.Date -as [DateTime]}, Version -Descending
|
|
$shippedPackages = GetMDVersionValue $newShippedVersions
|
|
$fieldUpdates += @"
|
|
{
|
|
"op": "replace",
|
|
"path": "/fields/Shipped Packages",
|
|
"value": "$shippedPackages"
|
|
}
|
|
"@
|
|
|
|
# If we shipped a version after we set "In Release" state then reset the state to "Next Release Unknown"
|
|
if ($pkgWorkItem.fields["System.State"] -eq "In Release")
|
|
{
|
|
$lastShippedDate = [DateTime]$newShippedVersions[0].Date
|
|
$markedInReleaseDate = ([DateTime]$pkgWorkItem.fields["Microsoft.VSTS.Common.StateChangeDate"])
|
|
|
|
# We just shipped so lets set the state to "Next Release Unknown"
|
|
if ($markedInReleaseDate -le $lastShippedDate)
|
|
{
|
|
$fieldUpdates += @'
|
|
{
|
|
"op": "replace",
|
|
"path": "/fields/State",
|
|
"value": "Next Release Unknown"
|
|
}
|
|
'@
|
|
}
|
|
}
|
|
}
|
|
|
|
# Full merged version set
|
|
$versionList = $versionSet.Values | Sort-Object {$_.Date -as [DateTime]}, Version -Descending
|
|
|
|
$versionFieldUpdates = GetTextVersionFields $versionList $pkgWorkItem
|
|
if ($versionFieldUpdates.Count -gt 0)
|
|
{
|
|
$fieldUpdates += $versionFieldUpdates
|
|
}
|
|
|
|
# If no version files to update do nothing
|
|
if ($fieldUpdates.Count -eq 0) {
|
|
return $pkgWorkItem
|
|
}
|
|
|
|
$versionsForDebug = ($versionList | Foreach-Object { $_.Version }) -join ","
|
|
$id = $pkgWorkItem.id
|
|
$loggingString = "[$($pkgWorkItem.id)]"
|
|
$loggingString += "$($pkgWorkItem.fields['Custom.Language'])"
|
|
$loggingString += " - $($pkgWorkItem.fields['Custom.Package'])"
|
|
$loggingString += "($($pkgWorkItem.fields['Custom.PackageVersionMajorMinor']))"
|
|
$loggingString += " - Updating versions $versionsForDebug"
|
|
Write-Host $loggingString
|
|
|
|
$body = "[" + ($fieldUpdates -join ',') + "]"
|
|
|
|
$response = Invoke-RestMethod -Method PATCH `
|
|
-Uri "https://dev.azure.com/azure-sdk/_apis/wit/workitems/${id}?api-version=6.0" `
|
|
-Headers (Get-DevOpsRestHeaders) -Body $body -ContentType "application/json-patch+json" | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashTable
|
|
return $response
|
|
} |