Sync eng/common directory with azure-sdk-tools repository (#97)
This commit is contained in:
Родитель
60ac28b0af
Коммит
be7fdcaf33
|
@ -16,8 +16,8 @@ parameters:
|
|||
steps:
|
||||
|
||||
- pwsh: |
|
||||
echo "git add ."
|
||||
git add .
|
||||
echo "git add -A"
|
||||
git add -A
|
||||
|
||||
echo "git diff --name-status --cached --exit-code"
|
||||
git diff --name-status --cached --exit-code
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
# intended to be used as part of a release process
|
||||
parameters:
|
||||
ArtifactLocation: 'not-specified'
|
||||
PackageRepository: 'not-specified'
|
||||
ReleaseSha: 'not-specified'
|
||||
RepoId: 'not-specified'
|
||||
WorkingDirectory: ''
|
||||
ScriptDirectory: eng/common/scripts
|
||||
TargetDocRepoName: ''
|
||||
TargetDocRepoOwner: ''
|
||||
PRBranchName: 'smoke-test-rdme'
|
||||
ArtifactName: ''
|
||||
Language: ''
|
||||
DocRepoDestinationPath: '' #usually docs-ref-services/
|
||||
|
||||
steps:
|
||||
- pwsh: |
|
||||
git clone https://github.com/${{ parameters.TargetDocRepoOwner }}/${{ parameters.TargetDocRepoName }} ${{ parameters.WorkingDirectory }}/repo
|
||||
|
||||
try {
|
||||
Push-Location ${{ parameters.WorkingDirectory }}/repo
|
||||
|
||||
Write-Host "git checkout smoke-test"
|
||||
git checkout smoke-test
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
displayName: Clone Documentation Repository
|
||||
ignoreLASTEXITCODE: false
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Apply Documentation Updates From Artifact'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: ${{ parameters.ScriptDirectory }}/update-docs-metadata.ps1
|
||||
arguments: >
|
||||
-ArtifactLocation ${{parameters.ArtifactLocation}}
|
||||
-Repository ${{parameters.PackageRepository}}
|
||||
-ReleaseSHA ${{parameters.ReleaseSha}}
|
||||
-RepoId ${{parameters.RepoId}}
|
||||
-WorkDirectory '${{parameters.WorkingDirectory}}'
|
||||
-DocRepoLocation "${{parameters.WorkingDirectory}}/repo"
|
||||
-Language "${{parameters.Language}}"
|
||||
-DocRepoContentLocation ${{ parameters.DocRepoDestinationPath }}
|
||||
pwsh: true
|
||||
env:
|
||||
GH_TOKEN: $(azuresdk-github-pat)
|
||||
|
||||
- template: /eng/common/pipelines/templates/steps/create-pull-request.yml
|
||||
parameters:
|
||||
RepoName: ${{ parameters.TargetDocRepoName }}
|
||||
RepoOwner: ${{ parameters.TargetDocRepoOwner }}
|
||||
PRBranchName: ${{ parameters.PRBranchName }}
|
||||
CommitMsg: "Update readme content for ${{ parameters.ArtifactName }}"
|
||||
PRTitle: "Docs.MS Readme Update."
|
||||
BaseBranchName: smoke-test
|
||||
WorkingDirectory: ${{parameters.WorkingDirectory}}/repo
|
||||
ScriptDirectory: ${{parameters.WorkingDirectory}}/${{parameters.ScriptDirectory}}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Template for all Python Scripts in this repository
|
||||
parameters:
|
||||
OSVmImage: $(OSVmImage)
|
||||
|
||||
steps:
|
||||
- task: PythonScript@0
|
||||
displayName: Verify Agent OS
|
||||
inputs:
|
||||
scriptSource: inline
|
||||
script: |
|
||||
# Script verifies the operating system for the platform on which it is being run
|
||||
# Used in build pipelines to verify the build agent os
|
||||
# Variable: The friendly name or image name of the os to verfy against
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import platform
|
||||
|
||||
os_parameter = "${{ parameters.OSVmImage }}".lower()
|
||||
if os_parameter.startswith('mac') or os_parameter.startswith('darwin'):
|
||||
os_parameter = 'macOS'
|
||||
elif os_parameter.startswith('ubuntu') or os_parameter.startswith('linux'):
|
||||
os_parameter = 'Linux'
|
||||
elif os_parameter.startswith('vs') or os_parameter.startswith('win'):
|
||||
os_parameter = 'Windows'
|
||||
else:
|
||||
raise Exception('Variable OSVmImage is empty or has an unexpected value [${{ parameters.OSVmImage }}]')
|
||||
|
||||
|
||||
print("Job requested to run on OS: %s" % (os_parameter))
|
||||
|
||||
agent_os = platform.system()
|
||||
agent_os = 'macOS' if agent_os == 'Darwin' else agent_os
|
||||
|
||||
if (agent_os.lower() == os_parameter.lower()):
|
||||
print('Job ran on OS: %s' % (agent_os))
|
||||
print('##vso[task.setvariable variable=OSName]%s' % (agent_os))
|
||||
else:
|
||||
raise Exception('Job ran on the wrong OS: %s' % (agent_os))
|
|
@ -18,8 +18,9 @@ class AzureEngSemanticVersion {
|
|||
[int] $PrereleaseNumber
|
||||
[bool] $IsPrerelease
|
||||
[string] $RawVersion
|
||||
# Regex inspired but simplified from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
||||
static [string] $SEMVER_REGEX = "(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-?(?<prelabel>[a-zA-Z-]*)(?:\.?(?<prenumber>0|[1-9]\d*)))?"
|
||||
|
||||
|
||||
static [AzureEngSemanticVersion] ParseVersionString([string] $versionString)
|
||||
{
|
||||
try {
|
||||
|
@ -31,10 +32,7 @@ class AzureEngSemanticVersion {
|
|||
}
|
||||
|
||||
AzureEngSemanticVersion([string] $versionString){
|
||||
# Regex inspired but simplifie from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
||||
$SEMVER_REGEX = "^(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-?(?<prelabel>[a-zA-Z-]*)(?:\.?(?<prenumber>0|[1-9]\d*)))?$"
|
||||
|
||||
if ($versionString -match $SEMVER_REGEX) {
|
||||
if ($versionString -match "^$([AzureEngSemanticVersion]::SEMVER_REGEX)$") {
|
||||
if ($null -eq $matches['prelabel']) {
|
||||
# artifically provide these values for non-prereleases to enable easy sorting of them later than prereleases.
|
||||
$prelabel = "zzz"
|
||||
|
|
|
@ -0,0 +1,472 @@
|
|||
. (Join-Path $PSScriptRoot SemVer.ps1)
|
||||
|
||||
$SDIST_PACKAGE_REGEX = "^(?<package>.*)\-(?<versionstring>$([AzureEngSemanticVersion]::SEMVER_REGEX))"
|
||||
|
||||
# Posts a github release for each item of the pkgList variable. SilentlyContinue
|
||||
function CreateReleases($pkgList, $releaseApiUrl, $releaseSha) {
|
||||
foreach ($pkgInfo in $pkgList) {
|
||||
Write-Host "Creating release $($pkgInfo.Tag)"
|
||||
|
||||
$releaseNotes = ""
|
||||
if ($pkgInfo.ReleaseNotes[$pkgInfo.PackageVersion].ReleaseContent -ne $null) {
|
||||
$releaseNotes = $pkgInfo.ReleaseNotes[$pkgInfo.PackageVersion].ReleaseContent
|
||||
}
|
||||
|
||||
$isPrerelease = $False
|
||||
|
||||
$parsedSemver = [AzureEngSemanticVersion]::ParseVersionString($pkgInfo.PackageVersion)
|
||||
|
||||
if ($parsedSemver) {
|
||||
$isPrerelease = $parsedSemver.IsPrerelease
|
||||
}
|
||||
|
||||
$url = $releaseApiUrl
|
||||
$body = ConvertTo-Json @{
|
||||
tag_name = $pkgInfo.Tag
|
||||
target_commitish = $releaseSha
|
||||
name = $pkgInfo.Tag
|
||||
draft = $False
|
||||
prerelease = $isPrerelease
|
||||
body = $releaseNotes
|
||||
}
|
||||
|
||||
$headers = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "token $($env:GH_TOKEN)"
|
||||
}
|
||||
|
||||
Invoke-WebRequest-WithHandling -url $url -body $body -headers $headers -method "Post"
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-WebRequest-WithHandling($url, $method, $body = $null, $headers = $null) {
|
||||
$attempts = 1
|
||||
|
||||
while ($attempts -le 3) {
|
||||
try {
|
||||
return Invoke-RestMethod -Method $method -Uri $url -Body $body -Headers $headers
|
||||
}
|
||||
catch {
|
||||
$response = $_.Exception.Response
|
||||
|
||||
$statusCode = $response.StatusCode.value__
|
||||
$statusDescription = $response.StatusDescription
|
||||
|
||||
if ($statusCode) {
|
||||
Write-Host "API request attempt number $attempts to $url failed with statuscode $statusCode"
|
||||
Write-Host $statusDescription
|
||||
|
||||
Write-Host "Rate Limit Details:"
|
||||
Write-Host "Total: $($response.Headers.GetValues("X-RateLimit-Limit"))"
|
||||
Write-Host "Remaining: $($response.Headers.GetValues("X-RateLimit-Remaining"))"
|
||||
Write-Host "Reset Epoch: $($response.Headers.GetValues("X-RateLimit-Reset"))"
|
||||
}
|
||||
else {
|
||||
Write-Host "API request attempt number $attempts to $url failed with no statuscode present, exception follows:"
|
||||
Write-Host $_.Exception.Response
|
||||
Write-Host $_.Exception
|
||||
}
|
||||
|
||||
if ($attempts -ge 3) {
|
||||
Write-Host "Abandoning Request $url after 3 attempts."
|
||||
exit(1)
|
||||
}
|
||||
|
||||
Start-Sleep -s 10
|
||||
}
|
||||
|
||||
$attempts += 1
|
||||
}
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a maven POM file
|
||||
function ParseMavenPackage($pkg, $workingDirectory) {
|
||||
[xml]$contentXML = Get-Content $pkg
|
||||
|
||||
$pkgId = $contentXML.project.artifactId
|
||||
$pkgVersion = $contentXML.project.version
|
||||
$groupId = if ($contentXML.project.groupId -eq $null) { $contentXML.project.parent.groupId } else { $contentXML.project.groupId }
|
||||
|
||||
# if it's a snapshot. return $null (as we don't want to create tags for this, but we also don't want to fail)
|
||||
if ($pkgVersion.Contains("SNAPSHOT")) {
|
||||
return $null
|
||||
}
|
||||
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $pkg.DirectoryName -Recurse -Include "$($pkg.Basename)-changelog.md")[0]
|
||||
|
||||
$readmeContentLoc = @(Get-ChildItem -Path $pkg.DirectoryName -Recurse -Include "$($pkg.Basename)-readme.md")[0]
|
||||
if (Test-Path -Path $readmeContentLoc) {
|
||||
$readmeContent = Get-Content -Raw $readmeContentLoc
|
||||
}
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsMavenPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion -groupId $groupId.Replace(".", "/"))
|
||||
ReleaseNotes = $releaseNotes
|
||||
ReadmeContent = $readmeContent
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the maven (really sonatype) publish status of a package id and version.
|
||||
function IsMavenPackageVersionPublished($pkgId, $pkgVersion, $groupId) {
|
||||
try {
|
||||
|
||||
$uri = "https://oss.sonatype.org/content/repositories/releases/$groupId/$pkgId/$pkgVersion/$pkgId-$pkgVersion.pom"
|
||||
$pomContent = Invoke-RestMethod -MaximumRetryCount 3 -Method "GET" -uri $uri
|
||||
|
||||
if ($pomContent -ne $null -or $pomContent.Length -eq 0) {
|
||||
return $true
|
||||
}
|
||||
else {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
# if this is 404ing, then this pkg has never been published before
|
||||
if ($statusCode -eq 404) {
|
||||
return $false
|
||||
}
|
||||
|
||||
Write-Host "VersionCheck to maven for packageId $pkgId failed with statuscode $statusCode"
|
||||
Write-Host $statusDescription
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
# make certain to always take the package json closest to the top
|
||||
function ResolvePkgJson($workFolder) {
|
||||
$pathsWithComplexity = @()
|
||||
foreach ($file in (Get-ChildItem -Path $workFolder -Recurse -Include "package.json")) {
|
||||
$complexity = ($file.FullName -Split { $_ -eq "/" -or $_ -eq "\" }).Length
|
||||
$pathsWithComplexity += New-Object PSObject -Property @{
|
||||
Path = $file
|
||||
Complexity = $complexity
|
||||
}
|
||||
}
|
||||
|
||||
return ($pathsWithComplexity | Sort-Object -Property Complexity)[0].Path
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a .tgz npm artifact
|
||||
function ParseNPMPackage($pkg, $workingDirectory) {
|
||||
$workFolder = "$workingDirectory$($pkg.Basename)"
|
||||
$origFolder = Get-Location
|
||||
New-Item -ItemType Directory -Force -Path $workFolder
|
||||
cd $workFolder
|
||||
|
||||
tar -xzf $pkg
|
||||
|
||||
$packageJSON = ResolvePkgJson -workFolder $workFolder | Get-Content | ConvertFrom-Json
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $workFolder -Recurse -Include "CHANGELOG.md")[0]
|
||||
$readmeContentLoc = @(Get-ChildItem -Path $workFolder -Recurse -Include "README.md")[0]
|
||||
if (Test-Path -Path $readmeContentLoc) {
|
||||
$readmeContent = Get-Content -Raw $readmeContentLoc
|
||||
}
|
||||
|
||||
cd $origFolder
|
||||
Remove-Item $workFolder -Force -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
$pkgId = $packageJSON.name
|
||||
$pkgVersion = $packageJSON.version
|
||||
|
||||
$resultObj = New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsNPMPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion)
|
||||
ReleaseNotes = $releaseNotes
|
||||
ReadmeContent = $readmeContent
|
||||
}
|
||||
|
||||
return $resultObj
|
||||
}
|
||||
|
||||
# Returns the npm publish status of a package id and version.
|
||||
function IsNPMPackageVersionPublished($pkgId, $pkgVersion) {
|
||||
$npmVersions = (npm show $pkgId versions)
|
||||
|
||||
if ($LastExitCode -ne 0) {
|
||||
npm ping
|
||||
|
||||
if ($LastExitCode -eq 0) {
|
||||
return $False
|
||||
}
|
||||
|
||||
Write-Host "Could not find a deployed version of $pkgId, and NPM connectivity check failed."
|
||||
exit(1)
|
||||
}
|
||||
|
||||
$npmVersionList = $npmVersions.split(",") | % { return $_.replace("[", "").replace("]", "").Trim() }
|
||||
return $npmVersionList.Contains($pkgVersion)
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a nupkg ZIP format.
|
||||
function ParseNugetPackage($pkg, $workingDirectory) {
|
||||
$workFolder = "$workingDirectory$($pkg.Basename)"
|
||||
$origFolder = Get-Location
|
||||
$zipFileLocation = "$workFolder/$($pkg.Basename).zip"
|
||||
New-Item -ItemType Directory -Force -Path $workFolder
|
||||
|
||||
Copy-Item -Path $pkg -Destination $zipFileLocation
|
||||
Expand-Archive -Path $zipFileLocation -DestinationPath $workFolder
|
||||
[xml] $packageXML = Get-ChildItem -Path "$workFolder/*.nuspec" | Get-Content
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $workFolder -Recurse -Include "CHANGELOG.md")[0]
|
||||
|
||||
$readmeContentLoc = @(Get-ChildItem -Path $workFolder -Recurse -Include "README.md")[0]
|
||||
if (Test-Path -Path $readmeContentLoc) {
|
||||
$readmeContent = Get-Content -Raw $readmeContentLoc
|
||||
}
|
||||
|
||||
Remove-Item $workFolder -Force -Recurse -ErrorAction SilentlyContinue
|
||||
$pkgId = $packageXML.package.metadata.id
|
||||
$pkgVersion = $packageXML.package.metadata.version
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsNugetPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion)
|
||||
ReleaseNotes = $releaseNotes
|
||||
ReadmeContent = $readmeContent
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the nuget publish status of a package id and version.
|
||||
function IsNugetPackageVersionPublished($pkgId, $pkgVersion) {
|
||||
|
||||
$nugetUri = "https://api.nuget.org/v3-flatcontainer/$($pkgId.ToLowerInvariant())/index.json"
|
||||
|
||||
try {
|
||||
$nugetVersions = Invoke-RestMethod -MaximumRetryCount 3 -uri $nugetUri -Method "GET"
|
||||
|
||||
return $nugetVersions.versions.Contains($pkgVersion)
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
# if this is 404ing, then this pkg has never been published before
|
||||
if ($statusCode -eq 404) {
|
||||
return $False
|
||||
}
|
||||
|
||||
Write-Host "Nuget Invocation failed:"
|
||||
Write-Host "StatusCode:" $statusCode
|
||||
Write-Host "StatusDescription:" $statusDescription
|
||||
exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a python sdist of ZIP format.
|
||||
function ParsePyPIPackage($pkg, $workingDirectory) {
|
||||
$pkg.Basename -match $SDIST_PACKAGE_REGEX | Out-Null
|
||||
|
||||
$pkgId = $matches["package"]
|
||||
$pkgVersion = $matches["versionstring"]
|
||||
|
||||
$workFolder = "$workingDirectory$($pkg.Basename)"
|
||||
$origFolder = Get-Location
|
||||
New-Item -ItemType Directory -Force -Path $workFolder
|
||||
|
||||
Expand-Archive -Path $pkg -DestinationPath $workFolder
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $workFolder -Recurse -Include "CHANGELOG.md")[0]
|
||||
$readmeContentLoc = @(Get-ChildItem -Path $workFolder -Recurse -Include "README.md")[0]
|
||||
if (Test-Path -Path $readmeContentLoc) {
|
||||
$readmeContent = Get-Content -Raw $readmeContentLoc
|
||||
}
|
||||
Remove-Item $workFolder -Force -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsPythonPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion)
|
||||
ReleaseNotes = $releaseNotes
|
||||
ReadmeContent = $readmeContent
|
||||
}
|
||||
}
|
||||
|
||||
function ParseCArtifact($pkg, $workingDirectory) {
|
||||
$packageInfo = Get-Content -Raw -Path $pkg | ConvertFrom-JSON
|
||||
$packageArtifactLocation = (Get-ItemProperty $pkg).Directory.FullName
|
||||
|
||||
$releaseNotes = ExtractReleaseNotes -changeLogLocation @(Get-ChildItem -Path $packageArtifactLocation -Recurse -Include "CHANGELOG.md")[0]
|
||||
|
||||
$readmeContentLoc = @(Get-ChildItem -Path $packageArtifactLocation -Recurse -Include "README.md")[0]
|
||||
if (Test-Path -Path $readmeContentLoc) {
|
||||
$readmeContent = Get-Content -Raw $readmeContentLoc
|
||||
}
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $packageInfo.name
|
||||
PackageVersion = $packageInfo.version
|
||||
# Artifact info is always considered deployable for C becasue it is not
|
||||
# deployed anywhere. Dealing with duplicate tags happens downstream in
|
||||
# CheckArtifactShaAgainstTagsList
|
||||
Deployable = $true
|
||||
ReleaseNotes = $releaseNotes
|
||||
ReadmeContent = $readmeContent
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the pypi publish status of a package id and version.
|
||||
function IsPythonPackageVersionPublished($pkgId, $pkgVersion) {
|
||||
try {
|
||||
$existingVersion = (Invoke-RestMethod -MaximumRetryCount 3 -Method "Get" -uri "https://pypi.org/pypi/$pkgId/$pkgVersion/json").info.version
|
||||
|
||||
# if existingVersion exists, then it's already been published
|
||||
return $True
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
# if this is 404ing, then this pkg has never been published before
|
||||
if ($statusCode -eq 404) {
|
||||
return $False
|
||||
}
|
||||
|
||||
Write-Host "PyPI Invocation failed:"
|
||||
Write-Host "StatusCode:" $statusCode
|
||||
Write-Host "StatusDescription:" $statusDescription
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
# Retrieves the list of all tags that exist on the target repository
|
||||
function GetExistingTags($apiUrl) {
|
||||
try {
|
||||
return (Invoke-WebRequest-WithHandling -Method "GET" -url "$apiUrl/git/refs/tags" ) | % { $_.ref.Replace("refs/tags/", "") }
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
Write-Host "Failed to retrieve tags from repository."
|
||||
Write-Host "StatusCode:" $statusCode
|
||||
Write-Host "StatusDescription:" $statusDescription
|
||||
|
||||
# Return an empty list if there are no tags in the repo
|
||||
if ($statusCode -eq 404) {
|
||||
return @()
|
||||
}
|
||||
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
# Walk across all build artifacts, check them against the appropriate repository, return a list of tags/releases
|
||||
function VerifyPackages($pkgRepository, $artifactLocation, $workingDirectory, $apiUrl, $releaseSha, $exitOnError = $True) {
|
||||
$pkgList = [array]@()
|
||||
$ParsePkgInfoFn = ""
|
||||
$packagePattern = ""
|
||||
|
||||
switch ($pkgRepository) {
|
||||
"Maven" {
|
||||
$ParsePkgInfoFn = "ParseMavenPackage"
|
||||
$packagePattern = "*.pom"
|
||||
break
|
||||
}
|
||||
"Nuget" {
|
||||
$ParsePkgInfoFn = "ParseNugetPackage"
|
||||
$packagePattern = "*.nupkg"
|
||||
break
|
||||
}
|
||||
"NPM" {
|
||||
$ParsePkgInfoFn = "ParseNPMPackage"
|
||||
$packagePattern = "*.tgz"
|
||||
break
|
||||
}
|
||||
"PyPI" {
|
||||
$ParsePkgInfoFn = "ParsePyPIPackage"
|
||||
$packagePattern = "*.zip"
|
||||
break
|
||||
}
|
||||
"C" {
|
||||
$ParsePkgInfoFn = "ParseCArtifact"
|
||||
$packagePattern = "*.json"
|
||||
}
|
||||
default {
|
||||
Write-Host "Unrecognized Language: $language"
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
$pkgs = (Get-ChildItem -Path $artifactLocation -Include $packagePattern -Recurse -File)
|
||||
|
||||
foreach ($pkg in $pkgs) {
|
||||
try {
|
||||
$parsedPackage = &$ParsePkgInfoFn -pkg $pkg -workingDirectory $workingDirectory
|
||||
|
||||
if ($parsedPackage -eq $null) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ($parsedPackage.Deployable -ne $True -and $exitOnError) {
|
||||
Write-Host "Package $($parsedPackage.PackageId) is marked with version $($parsedPackage.PackageVersion), the version $($parsedPackage.PackageVersion) has already been deployed to the target repository."
|
||||
Write-Host "Maybe a pkg version wasn't updated properly?"
|
||||
exit(1)
|
||||
}
|
||||
|
||||
$pkgList += New-Object PSObject -Property @{
|
||||
PackageId = $parsedPackage.PackageId
|
||||
PackageVersion = $parsedPackage.PackageVersion
|
||||
Tag = ($parsedPackage.PackageId + "_" + $parsedPackage.PackageVersion)
|
||||
ReleaseNotes = $parsedPackage.ReleaseNotes
|
||||
ReadmeContent = $parsedPackage.ReadmeContent
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host $_.Exception.Message
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
$results = @([array]$pkgList | Sort-Object -Property Tag -uniq)
|
||||
|
||||
$existingTags = GetExistingTags($apiUrl)
|
||||
|
||||
$intersect = $results | % { $_.Tag } | ? { $existingTags -contains $_ }
|
||||
|
||||
if ($intersect.Length -gt 0 -and $exitOnError) {
|
||||
CheckArtifactShaAgainstTagsList -priorExistingTagList $intersect -releaseSha $releaseSha -apiUrl $apiUrl -exitOnError $exitOnError
|
||||
|
||||
# all the tags are clean. remove them from the list of releases we will publish.
|
||||
$results = $results | ? { -not ($intersect -contains $_.Tag ) }
|
||||
}
|
||||
|
||||
return $results
|
||||
}
|
||||
|
||||
# given a set of tags that we want to release, we need to ensure that if they already DO exist.
|
||||
# if they DO exist, quietly exit if the commit sha of the artifact matches that of the tag
|
||||
# if the commit sha does not match, exit with error and report both problem shas
|
||||
function CheckArtifactShaAgainstTagsList($priorExistingTagList, $releaseSha, $apiUrl, $exitOnError) {
|
||||
$headers = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "token $($env:GH_TOKEN)"
|
||||
}
|
||||
|
||||
$unmatchedTags = @()
|
||||
|
||||
foreach ($tag in $priorExistingTagList) {
|
||||
$tagSha = (Invoke-WebRequest-WithHandling -Method "Get" -Url "$apiUrl/git/refs/tags/$tag" -Headers $headers)."object".sha
|
||||
|
||||
if ($tagSha -eq $releaseSha) {
|
||||
Write-Host "This package has already been released. The existing tag commit SHA $releaseSha matches the artifact SHA being processed. Skipping release step for this tag."
|
||||
}
|
||||
else {
|
||||
Write-Host "The artifact SHA $releaseSha does not match that of the currently existing tag."
|
||||
Write-Host "Tag with issues is $tag with commit SHA $tagSha"
|
||||
|
||||
$unmatchedTags += $tag
|
||||
}
|
||||
}
|
||||
|
||||
if ($unmatchedTags.Length -gt 0 -and $exitOnError) {
|
||||
Write-Host "Tags already existing with different SHA versions. Exiting."
|
||||
exit(1)
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
# Example Usage: ./copy-readmes-to-docs.ps1 -CodeRepo C:/repo/sdk-for-python -DocRepo C:/repo/azure-docs-sdk-python
|
||||
# run the link updating script before this to get links fixed to the release
|
||||
# Highly recommended that you use Powershell Core.
|
||||
# git reset --hard origin/smoke-test on the doc repo prior to running this
|
||||
|
||||
param (
|
||||
[String]$CodeRepo,
|
||||
[String]$DocRepo,
|
||||
[String]$TargetServices
|
||||
)
|
||||
|
||||
Write-Host "> $PSCommandPath $args"
|
||||
|
||||
$PACKAGE_README_REGEX = ".*[\/\\]sdk[\\\/][^\/\\]+[\\\/][^\/\\]+[\/\\]README\.md"
|
||||
|
||||
Write-Host "repo is $CodeRepo"
|
||||
|
||||
$date = Get-Date -Format "MM/dd/yyyy"
|
||||
|
||||
if ($CodeRepo -Match "net")
|
||||
{
|
||||
$lang = ".NET"
|
||||
$TARGET_FOLDER = Join-Path -Path $DocRepo -ChildPath "api/overview/azure"
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/dotnet-packages.csv"
|
||||
}
|
||||
if ($CodeRepo -Match "python"){
|
||||
$lang = "Python"
|
||||
$TARGET_FOLDER = Join-Path -Path $DocRepo -ChildPath "docs-ref-services"
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/python-packages.csv"
|
||||
}
|
||||
if ($CodeRepo -Match "java"){
|
||||
$lang = "Java"
|
||||
$TARGET_FOLDER = Join-Path -Path $DocRepo -ChildPath "docs-ref-services"
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/java-packages.csv"
|
||||
}
|
||||
if ($CodeRepo -Match "js"){
|
||||
$lang = "JavaScript"
|
||||
$TARGET_FOLDER = Join-Path -Path $DocRepo -ChildPath "docs-ref-services"
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/js-packages.csv"
|
||||
}
|
||||
|
||||
|
||||
|
||||
$metadataResponse = Invoke-WebRequest -Uri $metadataUri | ConvertFrom-Csv
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($TargetServices))
|
||||
{
|
||||
$selectedServices = $metadataResponse | ForEach-Object -Process {$_.RepoPath} | Get-Unique
|
||||
}
|
||||
else {
|
||||
$selectedServices = $TargetServices -Split "," | % { return $_.Trim() }
|
||||
}
|
||||
|
||||
|
||||
foreach($service in $selectedServices){
|
||||
$readmePath = Join-Path -Path $CodeRepo -ChildPath "sdk/$service"
|
||||
Write-Host "Examining: $readmePath"
|
||||
|
||||
$libraries = $metadataResponse | Where-Object { $_.RepoPath -eq $service }
|
||||
|
||||
foreach($library in $libraries){
|
||||
|
||||
$package = $library.Package
|
||||
$version = If ([string]::IsNullOrWhiteSpace($library.VersionGA)) {$library.VersionPreview} Else {$library.VersionGA}
|
||||
|
||||
$file = Join-Path -Path $readmePath -ChildPath "/$package/README.md" | Get-Item
|
||||
Write-Host "`tOutputting $($file.FullName)"
|
||||
|
||||
$fileContent = Get-Content $file
|
||||
|
||||
$fileContent = $fileContent -Join "`n"
|
||||
|
||||
$fileMatch = (Select-String -InputObject $fileContent -Pattern 'Azure .+? (client|plugin|shared) library for (JavaScript|Java|Python|\.NET)').Matches[0]
|
||||
|
||||
$header = "---`r`ntitle: $fileMatch`r`nkeywords: Azure, $lang, SDK, API, $service, $package`r`nauthor: maggiepint`r`nms.author: magpint`r`nms.date: $date`r`nms.topic: article`r`nms.prod: azure`r`nms.technology: azure`r`nms.devlang: $lang`r`nms.service: $service`r`n---`r`n"
|
||||
|
||||
$fileContent = $fileContent -replace $fileMatch, "$fileMatch - Version $version `r`n"
|
||||
|
||||
$fileContent = "$header $fileContent"
|
||||
|
||||
$readmeName = "$($file.Directory.Name.Replace('azure-','').Replace('Azure.', '').ToLower())-readme.md"
|
||||
|
||||
$readmeOutputLocation = Join-Path $TARGET_FOLDER -ChildPath $readmeName
|
||||
|
||||
Set-Content -Path $readmeOutputLocation -Value $fileContent
|
||||
}
|
||||
}
|
|
@ -20,447 +20,7 @@ param (
|
|||
|
||||
Write-Host "> $PSCommandPath $args"
|
||||
|
||||
$VERSION_REGEX = "(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?((?<pre>[^0-9][^\s]+))?"
|
||||
$SDIST_PACKAGE_REGEX = "^(?<package>.*)\-(?<versionstring>$VERSION_REGEX$)"
|
||||
|
||||
# Posts a github release for each item of the pkgList variable. SilentlyContinue
|
||||
function CreateReleases($pkgList, $releaseApiUrl, $releaseSha) {
|
||||
foreach ($pkgInfo in $pkgList) {
|
||||
Write-Host "Creating release $($pkgInfo.Tag)"
|
||||
|
||||
$releaseNotes = ""
|
||||
if ($pkgInfo.ReleaseNotes[$pkgInfo.PackageVersion].ReleaseContent -ne $null) {
|
||||
$releaseNotes = $pkgInfo.ReleaseNotes[$pkgInfo.PackageVersion].ReleaseContent
|
||||
}
|
||||
|
||||
$isPrerelease = $False
|
||||
if ($pkgInfo.PackageVersion -match $VERSION_REGEX) {
|
||||
$preReleaseLabel = $matches["pre"]
|
||||
$isPrerelease = ![string]::IsNullOrEmpty($preReleaseLabel)
|
||||
}
|
||||
|
||||
$url = $releaseApiUrl
|
||||
$body = ConvertTo-Json @{
|
||||
tag_name = $pkgInfo.Tag
|
||||
target_commitish = $releaseSha
|
||||
name = $pkgInfo.Tag
|
||||
draft = $False
|
||||
prerelease = $isPrerelease
|
||||
body = $releaseNotes
|
||||
}
|
||||
|
||||
$headers = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "token $($env:GH_TOKEN)"
|
||||
}
|
||||
|
||||
FireAPIRequest -url $url -body $body -headers $headers -method "Post"
|
||||
}
|
||||
}
|
||||
|
||||
function FireAPIRequest($url, $method, $body = $null, $headers = $null) {
|
||||
$attempts = 1
|
||||
|
||||
while ($attempts -le 3) {
|
||||
try {
|
||||
return Invoke-RestMethod -Method $method -Uri $url -Body $body -Headers $headers
|
||||
}
|
||||
catch {
|
||||
$response = $_.Exception.Response
|
||||
|
||||
$statusCode = $response.StatusCode.value__
|
||||
$statusDescription = $response.StatusDescription
|
||||
|
||||
if ($statusCode) {
|
||||
Write-Host "API request attempt number $attempts to $url failed with statuscode $statusCode"
|
||||
Write-Host $statusDescription
|
||||
|
||||
Write-Host "Rate Limit Details:"
|
||||
Write-Host "Total: $($response.Headers.GetValues("X-RateLimit-Limit"))"
|
||||
Write-Host "Remaining: $($response.Headers.GetValues("X-RateLimit-Remaining"))"
|
||||
Write-Host "Reset Epoch: $($response.Headers.GetValues("X-RateLimit-Reset"))"
|
||||
}
|
||||
else {
|
||||
Write-Host "API request attempt number $attempts to $url failed with no statuscode present, exception follows:"
|
||||
Write-Host $_.Exception.Response
|
||||
Write-Host $_.Exception
|
||||
}
|
||||
|
||||
if ($attempts -ge 3) {
|
||||
Write-Host "Abandoning Request $url after 3 attempts."
|
||||
exit(1)
|
||||
}
|
||||
|
||||
Start-Sleep -s 10
|
||||
}
|
||||
|
||||
$attempts += 1
|
||||
}
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a maven POM file
|
||||
function ParseMavenPackage($pkg, $workingDirectory) {
|
||||
[xml]$contentXML = Get-Content $pkg
|
||||
|
||||
$pkgId = $contentXML.project.artifactId
|
||||
$pkgVersion = $contentXML.project.version
|
||||
$groupId = if ($contentXML.project.groupId -eq $null) { $contentXML.project.parent.groupId } else { $contentXML.project.groupId }
|
||||
|
||||
# if it's a snapshot. return $null (as we don't want to create tags for this, but we also don't want to fail)
|
||||
if ($pkgVersion.Contains("SNAPSHOT")) {
|
||||
return $null
|
||||
}
|
||||
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $pkg.DirectoryName -Recurse -Include "$($pkg.Basename)-changelog.md")[0]
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsMavenPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion -groupId $groupId.Replace(".", "/"))
|
||||
ReleaseNotes = $releaseNotes
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the maven (really sonatype) publish status of a package id and version.
|
||||
function IsMavenPackageVersionPublished($pkgId, $pkgVersion, $groupId) {
|
||||
try {
|
||||
|
||||
$uri = "https://oss.sonatype.org/content/repositories/releases/$groupId/$pkgId/$pkgVersion/$pkgId-$pkgVersion.pom"
|
||||
$pomContent = Invoke-RestMethod -Method "GET" -Uri $uri
|
||||
|
||||
if ($pomContent -ne $null -or $pomContent.Length -eq 0) {
|
||||
return $true
|
||||
}
|
||||
else {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
# if this is 404ing, then this pkg has never been published before
|
||||
if ($statusCode -eq 404) {
|
||||
return $false
|
||||
}
|
||||
|
||||
Write-Host "VersionCheck to maven for packageId $pkgId failed with statuscode $statusCode"
|
||||
Write-Host $statusDescription
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
# make certain to always take the package json closest to the top
|
||||
function ResolvePkgJson($workFolder) {
|
||||
$pathsWithComplexity = @()
|
||||
foreach ($file in (Get-ChildItem -Path $workFolder -Recurse -Include "package.json")) {
|
||||
$complexity = ($file.FullName -Split { $_ -eq "/" -or $_ -eq "\" }).Length
|
||||
$pathsWithComplexity += New-Object PSObject -Property @{
|
||||
Path = $file
|
||||
Complexity = $complexity
|
||||
}
|
||||
}
|
||||
|
||||
return ($pathsWithComplexity | Sort-Object -Property Complexity)[0].Path
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a .tgz npm artifact
|
||||
function ParseNPMPackage($pkg, $workingDirectory) {
|
||||
$workFolder = "$workingDirectory$($pkg.Basename)"
|
||||
$origFolder = Get-Location
|
||||
mkdir $workFolder
|
||||
cd $workFolder
|
||||
|
||||
tar -xzf $pkg
|
||||
|
||||
$packageJSON = ResolvePkgJson -workFolder $workFolder | Get-Content | ConvertFrom-Json
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $workFolder -Recurse -Include "CHANGELOG.md")[0]
|
||||
|
||||
cd $origFolder
|
||||
Remove-Item $workFolder -Force -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
$pkgId = $packageJSON.name
|
||||
$pkgVersion = $packageJSON.version
|
||||
|
||||
$resultObj = New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsNPMPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion)
|
||||
ReleaseNotes = $releaseNotes
|
||||
}
|
||||
|
||||
return $resultObj
|
||||
}
|
||||
|
||||
# Returns the npm publish status of a package id and version.
|
||||
function IsNPMPackageVersionPublished($pkgId, $pkgVersion) {
|
||||
$npmVersions = (npm show $pkgId versions)
|
||||
|
||||
if ($LastExitCode -ne 0) {
|
||||
npm ping
|
||||
|
||||
if ($LastExitCode -eq 0) {
|
||||
return $False
|
||||
}
|
||||
|
||||
Write-Host "Could not find a deployed version of $pkgId, and NPM connectivity check failed."
|
||||
exit(1)
|
||||
}
|
||||
|
||||
$npmVersionList = $npmVersions.split(",") | % { return $_.replace("[", "").replace("]", "").Trim() }
|
||||
return $npmVersionList.Contains($pkgVersion)
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a nupkg ZIP format.
|
||||
function ParseNugetPackage($pkg, $workingDirectory) {
|
||||
$workFolder = "$workingDirectory$($pkg.Basename)"
|
||||
$origFolder = Get-Location
|
||||
$zipFileLocation = "$workFolder/$($pkg.Basename).zip"
|
||||
mkdir $workFolder
|
||||
|
||||
Copy-Item -Path $pkg -Destination $zipFileLocation
|
||||
Expand-Archive -Path $zipFileLocation -DestinationPath $workFolder
|
||||
[xml] $packageXML = Get-ChildItem -Path "$workFolder/*.nuspec" | Get-Content
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $workFolder -Recurse -Include "CHANGELOG.md")[0]
|
||||
|
||||
Remove-Item $workFolder -Force -Recurse -ErrorAction SilentlyContinue
|
||||
$pkgId = $packageXML.package.metadata.id
|
||||
$pkgVersion = $packageXML.package.metadata.version
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsNugetPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion)
|
||||
ReleaseNotes = $releaseNotes
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the nuget publish status of a package id and version.
|
||||
function IsNugetPackageVersionPublished($pkgId, $pkgVersion) {
|
||||
|
||||
$nugetUri = "https://api.nuget.org/v3-flatcontainer/$($pkgId.ToLowerInvariant())/index.json"
|
||||
|
||||
try {
|
||||
$nugetVersions = Invoke-RestMethod -Method "GET" -Uri $nugetUri
|
||||
|
||||
return $nugetVersions.versions.Contains($pkgVersion)
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
# if this is 404ing, then this pkg has never been published before
|
||||
if ($statusCode -eq 404) {
|
||||
return $False
|
||||
}
|
||||
|
||||
Write-Host "Nuget Invocation failed:"
|
||||
Write-Host "StatusCode:" $statusCode
|
||||
Write-Host "StatusDescription:" $statusDescription
|
||||
exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Parse out package publishing information given a python sdist of ZIP format.
|
||||
function ParsePyPIPackage($pkg, $workingDirectory) {
|
||||
$pkg.Basename -match $SDIST_PACKAGE_REGEX | Out-Null
|
||||
|
||||
$pkgId = $matches["package"]
|
||||
$pkgVersion = $matches["versionstring"]
|
||||
|
||||
$workFolder = "$workingDirectory$($pkg.Basename)"
|
||||
$origFolder = Get-Location
|
||||
mkdir $workFolder
|
||||
|
||||
Expand-Archive -Path $pkg -DestinationPath $workFolder
|
||||
$releaseNotes = &"${PSScriptRoot}/../Extract-ReleaseNotes.ps1" -ChangeLogLocation @(Get-ChildItem -Path $workFolder -Recurse -Include "CHANGELOG.md")[0]
|
||||
Remove-Item $workFolder -Force -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $pkgId
|
||||
PackageVersion = $pkgVersion
|
||||
Deployable = $forceCreate -or !(IsPythonPackageVersionPublished -pkgId $pkgId -pkgVersion $pkgVersion)
|
||||
ReleaseNotes = $releaseNotes
|
||||
}
|
||||
}
|
||||
|
||||
function ParseCArtifact($pkg, $workingDirectory) {
|
||||
$packageInfo = Get-Content -Raw -Path $pkg | ConvertFrom-JSON
|
||||
$packageArtifactLocation = (Get-ItemProperty $pkg).Directory.FullName
|
||||
|
||||
$releaseNotes = ExtractReleaseNotes -changeLogLocation @(Get-ChildItem -Path $packageArtifactLocation -Recurse -Include "CHANGELOG.md")[0]
|
||||
|
||||
return New-Object PSObject -Property @{
|
||||
PackageId = $packageInfo.name
|
||||
PackageVersion = $packageInfo.version
|
||||
# Artifact info is always considered deployable for C becasue it is not
|
||||
# deployed anywhere. Dealing with duplicate tags happens downstream in
|
||||
# CheckArtifactShaAgainstTagsList
|
||||
Deployable = $true
|
||||
ReleaseNotes = $releaseNotes
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the pypi publish status of a package id and version.
|
||||
function IsPythonPackageVersionPublished($pkgId, $pkgVersion) {
|
||||
try {
|
||||
$existingVersion = (Invoke-RestMethod -Method "Get" -Uri "https://pypi.org/pypi/$pkgId/$pkgVersion/json").info.version
|
||||
|
||||
# if existingVersion exists, then it's already been published
|
||||
return $True
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
# if this is 404ing, then this pkg has never been published before
|
||||
if ($statusCode -eq 404) {
|
||||
return $False
|
||||
}
|
||||
|
||||
Write-Host "PyPI Invocation failed:"
|
||||
Write-Host "StatusCode:" $statusCode
|
||||
Write-Host "StatusDescription:" $statusDescription
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
# Retrieves the list of all tags that exist on the target repository
|
||||
function GetExistingTags($apiUrl) {
|
||||
try {
|
||||
return (Invoke-RestMethod -Method "GET" -Uri "$apiUrl/git/refs/tags" ) | % { $_.ref.Replace("refs/tags/", "") }
|
||||
}
|
||||
catch {
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$statusDescription = $_.Exception.Response.StatusDescription
|
||||
|
||||
Write-Host "Failed to retrieve tags from repository."
|
||||
Write-Host "StatusCode:" $statusCode
|
||||
Write-Host "StatusDescription:" $statusDescription
|
||||
|
||||
# Return an empty list if there are no tags in the repo
|
||||
if ($statusCode -eq 404) {
|
||||
return @()
|
||||
}
|
||||
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
# Walk across all build artifacts, check them against the appropriate repository, return a list of tags/releases
|
||||
function VerifyPackages($pkgRepository, $artifactLocation, $workingDirectory, $apiUrl, $releaseSha) {
|
||||
$pkgList = [array]@()
|
||||
$ParsePkgInfoFn = ""
|
||||
$packagePattern = ""
|
||||
|
||||
switch ($pkgRepository) {
|
||||
"Maven" {
|
||||
$ParsePkgInfoFn = "ParseMavenPackage"
|
||||
$packagePattern = "*.pom"
|
||||
break
|
||||
}
|
||||
"Nuget" {
|
||||
$ParsePkgInfoFn = "ParseNugetPackage"
|
||||
$packagePattern = "*.nupkg"
|
||||
break
|
||||
}
|
||||
"NPM" {
|
||||
$ParsePkgInfoFn = "ParseNPMPackage"
|
||||
$packagePattern = "*.tgz"
|
||||
break
|
||||
}
|
||||
"PyPI" {
|
||||
$ParsePkgInfoFn = "ParsePyPIPackage"
|
||||
$packagePattern = "*.zip"
|
||||
break
|
||||
}
|
||||
"C" {
|
||||
$ParsePkgInfoFn = "ParseCArtifact"
|
||||
$packagePattern = "*.json"
|
||||
}
|
||||
default {
|
||||
Write-Host "Unrecognized Language: $language"
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
$pkgs = (Get-ChildItem -Path $artifactLocation -Include $packagePattern -Recurse -File)
|
||||
|
||||
Write-Host $pkgs
|
||||
|
||||
foreach ($pkg in $pkgs) {
|
||||
try {
|
||||
$parsedPackage = &$ParsePkgInfoFn -pkg $pkg -workingDirectory $workingDirectory
|
||||
|
||||
if ($parsedPackage -eq $null) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ($parsedPackage.Deployable -ne $True) {
|
||||
Write-Host "Package $($parsedPackage.PackageId) is marked with version $($parsedPackage.PackageVersion), the version $($parsedPackage.PackageVersion) has already been deployed to the target repository."
|
||||
Write-Host "Maybe a pkg version wasn't updated properly?"
|
||||
exit(1)
|
||||
}
|
||||
|
||||
$pkgList += New-Object PSObject -Property @{
|
||||
PackageId = $parsedPackage.PackageId
|
||||
PackageVersion = $parsedPackage.PackageVersion
|
||||
Tag = ($parsedPackage.PackageId + "_" + $parsedPackage.PackageVersion)
|
||||
ReleaseNotes = $parsedPackage.ReleaseNotes
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host $_.Exception.Message
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
$results = ([array]$pkgList | Sort-Object -Property Tag -uniq)
|
||||
|
||||
$existingTags = GetExistingTags($apiUrl)
|
||||
$intersect = $results | % { $_.Tag } | ? { $existingTags -contains $_ }
|
||||
|
||||
if ($intersect.Length -gt 0) {
|
||||
CheckArtifactShaAgainstTagsList -priorExistingTagList $intersect -releaseSha $releaseSha -apiUrl $apiUrl
|
||||
|
||||
# all the tags are clean. remove them from the list of releases we will publish.
|
||||
$results = $results | ? { -not ($intersect -contains $_.Tag ) }
|
||||
}
|
||||
|
||||
return $results
|
||||
}
|
||||
|
||||
# given a set of tags that we want to release, we need to ensure that if they already DO exist.
|
||||
# if they DO exist, quietly exit if the commit sha of the artifact matches that of the tag
|
||||
# if the commit sha does not match, exit with error and report both problem shas
|
||||
function CheckArtifactShaAgainstTagsList($priorExistingTagList, $releaseSha, $apiUrl) {
|
||||
$headers = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "token $($env:GH_TOKEN)"
|
||||
}
|
||||
|
||||
$unmatchedTags = @()
|
||||
|
||||
foreach ($tag in $priorExistingTagList) {
|
||||
$tagSha = (FireAPIRequest -Method "Get" -Url "$apiUrl/git/refs/tags/$tag" -Headers $headers)."object".sha
|
||||
|
||||
if ($tagSha -eq $releaseSha) {
|
||||
Write-Host "This package has already been released. The existing tag commit SHA $releaseSha matches the artifact SHA being processed. Skipping release step for this tag."
|
||||
}
|
||||
else {
|
||||
Write-Host "The artifact SHA $releaseSha does not match that of the currently existing tag."
|
||||
Write-Host "Tag with issues is $tag with commit SHA $tagSha"
|
||||
|
||||
$unmatchedTags += $tag
|
||||
}
|
||||
}
|
||||
|
||||
if ($unmatchedTags.Length -gt 0) {
|
||||
Write-Host "Tags already existing with different SHA versions. Exiting."
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
. (Join-Path $PSScriptRoot artifact-metadata-parsing.ps1)
|
||||
|
||||
$apiUrl = "https://api.github.com/repos/$repoId"
|
||||
Write-Host "Using API URL $apiUrl"
|
||||
|
|
|
@ -137,7 +137,6 @@ do
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while($needsRetry -and $tryNumber -le $numberOfRetries)
|
||||
|
||||
if ($LASTEXITCODE -ne 0)
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
# Note, due to how `Expand-Archive` is leveraged in this script,
|
||||
# powershell core is a requirement for successful execution.
|
||||
param (
|
||||
# arguments leveraged to parse and identify artifacts
|
||||
$ArtifactLocation, # the root of the artifact folder. DevOps $(System.ArtifactsDirectory)
|
||||
$WorkDirectory, # a clean folder that we can work in
|
||||
$ReleaseSHA, # the SHA for the artifacts. DevOps: $(Release.Artifacts.<artifactAlias>.SourceVersion) or $(Build.SourceVersion)
|
||||
$RepoId, # full repo id. EG azure/azure-sdk-for-net DevOps: $(Build.Repository.Id). Used as a part of VerifyPackages
|
||||
$Repository, # EG: "Maven", "PyPI", "NPM"
|
||||
|
||||
# arguments necessary to power the docs release
|
||||
$DocRepoLocation, # the location on disk where we have cloned the documentation repository
|
||||
$Language, # EG: js, java, dotnet. Used in language for the embedded readme.
|
||||
$DocRepoContentLocation = "docs-ref-services/" # within the doc repo, where does our readme go?
|
||||
)
|
||||
|
||||
Write-Host "> $PSCommandPath $args"
|
||||
|
||||
|
||||
# import artifact parsing and semver handling
|
||||
. (Join-Path $PSScriptRoot artifact-metadata-parsing.ps1)
|
||||
. (Join-Path $PSScriptRoot SemVer.ps1)
|
||||
|
||||
function GetMetaData($lang){
|
||||
switch ($lang) {
|
||||
"java" {
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/java-packages.csv"
|
||||
break
|
||||
}
|
||||
".net" {
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/dotnet-packages.csv"
|
||||
break
|
||||
}
|
||||
"python" {
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/python-packages.csv"
|
||||
break
|
||||
}
|
||||
"javascript" {
|
||||
$metadataUri = "https://raw.githubusercontent.com/Azure/azure-sdk/master/_data/releases/latest/js-packages.csv"
|
||||
break
|
||||
}
|
||||
default {
|
||||
Write-Host "Unrecognized Language: $language"
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
$metadataResponse = Invoke-WebRequest-WithHandling -url $metadataUri -method "GET" | ConvertFrom-Csv
|
||||
}
|
||||
|
||||
function GetAdjustedReadmeContent($pkgInfo, $lang){
|
||||
$date = Get-Date -Format "MM/dd/yyyy"
|
||||
$service = ""
|
||||
|
||||
# the namespace is not expected to be present for js.
|
||||
$pkgId = $pkgInfo.PackageId.Replace("@azure/", "")
|
||||
|
||||
try {
|
||||
$metadata = GetMetaData -lang $lang
|
||||
$service = $metadata | ? { $_.Package -eq $pkgId }
|
||||
|
||||
if ($service) {
|
||||
$service = "$service,"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host $_
|
||||
Write-Host "Unable to retrieve service metadata for packageId $($pkgInfo.PackageId)"
|
||||
}
|
||||
|
||||
$headerContentMatch = (Select-String -InputObject $pkgInfo.ReadmeContent -Pattern 'Azure .+? (client|plugin|shared) library for (JavaScript|Java|Python|\.NET|C)').Matches[0]
|
||||
|
||||
if ($headerContentMatch){
|
||||
$header = "---`r`ntitle: $headerContentMatch`r`nkeywords: Azure, $lang, SDK, API, $service $($pkgInfo.PackageId)`r`nauthor: maggiepint`r`nms.author: magpint`r`nms.date: $date`r`nms.topic: article`r`nms.prod: azure`r`nms.technology: azure`r`nms.devlang: $lang`r`nms.service: $service`r`n---`r`n"
|
||||
$fileContent = $pkgInfo.ReadmeContent -replace $headerContentMatch, "$headerContentMatch - Version $($pkgInfo.PackageVersion) `r`n"
|
||||
return "$header $fileContent"
|
||||
}
|
||||
else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
$apiUrl = "https://api.github.com/repos/$repoId"
|
||||
$pkgs = VerifyPackages -pkgRepository $Repository `
|
||||
-artifactLocation $ArtifactLocation `
|
||||
-workingDirectory $WorkDirectory `
|
||||
-apiUrl $apiUrl `
|
||||
-releaseSha $ReleaseSHA `
|
||||
-exitOnError $False
|
||||
|
||||
if ($pkgs) {
|
||||
Write-Host "Given the visible artifacts, readmes will be copied for the following packages"
|
||||
Write-Host ($pkgs | % { $_.PackageId })
|
||||
|
||||
foreach ($packageInfo in $pkgs) {
|
||||
# sync the doc repo
|
||||
$semVer = [AzureEngSemanticVersion]::ParseVersionString($packageInfo.PackageVersion)
|
||||
$rdSuffix = ""
|
||||
if ($semVer.IsPreRelease) {
|
||||
$rdSuffix = "-pre"
|
||||
}
|
||||
|
||||
$readmeName = "$($packageInfo.PackageId.Replace('azure-','').Replace('Azure.', '').Replace('@azure/', '').ToLower())-readme$rdSuffix.md"
|
||||
$readmeLocation = Join-Path $DocRepoLocation $DocRepoContentLocation $readmeName
|
||||
$adjustedContent = GetAdjustedReadmeContent -pkgInfo $packageInfo -lang $Language
|
||||
|
||||
if ($adjustedContent) {
|
||||
try {
|
||||
Push-Location $DocRepoLocation
|
||||
Set-Content -Path $readmeLocation -Value $adjustedContent -Force
|
||||
|
||||
Write-Host "Updated readme for $readmeName."
|
||||
} catch {
|
||||
Write-Host $_
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
} else {
|
||||
Write-Host "Unable to parse a header out of the readmecontent for PackageId $($packageInfo.PackageId)"
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Host "No readmes discovered for doc release under folder $ArtifactLocation."
|
||||
}
|
Загрузка…
Ссылка в новой задаче