Compare commits

..

20 Commits

Author SHA1 Message Date
Nikita Bykov
742c5dae81 update 2021-08-20 15:17:09 +03:00
Nikita Bykov
f3f0d2026d update 2021-08-20 11:54:21 +03:00
Nikita Bykov
5e6f2c681c update 2021-08-20 11:48:02 +03:00
Nikita Bykov
bb9fd35708 update 2021-08-19 15:17:18 +03:00
Nikita Bykov
9f535cd83f update 2021-08-19 14:36:29 +03:00
Nikita Bykov
750ff93e50 update 2021-08-19 14:31:13 +03:00
Nikita Bykov
a29d98d3f2 update 2021-08-19 12:47:25 +03:00
Nikita Bykov
538be710eb update 2021-08-19 11:50:50 +03:00
Nikita Bykov
8f1a38e755 update 2021-08-19 11:32:59 +03:00
Nikita Bykov
9fc854ce04 update 2021-08-18 18:30:36 +03:00
Nikita Bykov
03ae7d095d add script for slack notification 2021-08-18 17:43:15 +03:00
Nikita Bykov
97e0e3a660 update get-new-tool-version.ps1 2021-08-17 16:57:27 +03:00
Nikita Bykov
b01e7843b6 Update 2021-07-13 18:06:50 +03:00
Nikita Bykov
856cb1ed00 Update 2021-07-13 17:17:45 +03:00
Nikita Bykov
6b744d4218 Add CancelWorkflow method 2021-07-13 17:14:29 +03:00
Nikita Bykov
4b286369c5 Test 2021-07-12 15:42:01 +03:00
Nikita Bykov
65cd85d7fe Test 2021-07-12 15:37:20 +03:00
Nikita Bykov
7654b2e70d Test 2021-07-12 15:12:52 +03:00
Nikita Bykov
7847e40341 Test 2021-07-12 15:10:09 +03:00
Nikita Bykov
d853f172e3 Update get-new-tool-version.ps1 2021-07-12 14:50:19 +03:00
21 changed files with 584 additions and 250 deletions

View File

@@ -1,39 +0,0 @@
name: 'Send Slack notification'
description: 'SendSlack notification about new versions of a tool'
inputs:
url:
required: true
description: 'Slack channel url'
tool-name:
required: true
description: 'Name of a tool to send notification for. Like Xamarin or Python'
default: 'Xamarin'
tool-version:
required: false
description: 'New versions of a tool'
pipeline-url:
required: false
description: 'Url of a pipeline'
image-url:
required: false
description: 'Image url for message'
default: 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png'
text:
required: false
description: 'Message text'
add-to-toolset-flag:
required: false
description: 'Flag to use notification for adding new versions to toolset'
runs:
using: "composite"
steps:
- id: send-slack-notification
name: Send Slack notification
shell: pwsh
run: ./get-new-tool-versions/send-slack-notification.ps1 -Url "${{ inputs.url }}" `
-ToolName "${{ inputs.tool-name }}" `
-ToolVersion "${{ inputs.tool-version }}" `
-PipelineUrl "${{ inputs.pipeline-url }}" `
-ImageUrl "${{ inputs.image-url }}" `
-Text "${{ inputs.text }}" `
${{ inputs.add-to-toolset-flag }}

View File

@@ -1,89 +0,0 @@
name: Get tools new versions
on:
schedule:
- cron: '0 8 * * THU'
workflow_dispatch:
defaults:
run:
shell: pwsh
jobs:
find-new-tool-versions:
strategy:
fail-fast: false
matrix:
tool:
- name: 'Xamarin'
image: 'https://avatars.githubusercontent.com/u/790012?s=200&v=4'
releases-url: 'null'
filter-parameter: 'null'
filter-arch: 'null'
- name: 'Python'
image: 'https://avatars.githubusercontent.com/u/1525981?s=200&v=4'
releases-url: 'https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json'
filter-parameter: 'version'
filter-arch: 'x64'
- name: 'PyPy'
image: 'https://avatars.githubusercontent.com/u/318667?s=200&v=4'
releases-url: 'https://downloads.python.org/pypy/versions.json'
filter-parameter: 'python_version'
filter-arch: 'x86'
- name: 'Node'
image: 'https://avatars.githubusercontent.com/u/9950313?s=200&v=4'
releases-url: 'https://raw.githubusercontent.com/actions/node-versions/main/versions-manifest.json'
filter-parameter: 'version'
filter-arch: 'x64'
- name: 'Go'
image: 'https://avatars.githubusercontent.com/u/4314092?s=200&v=4'
releases-url: 'https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json'
filter-parameter: 'version'
filter-arch: 'x64'
name: 'Searching for new versions of ${{ matrix.tool.name }}'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- id: get-new-tool-versions
name: Get new tool versions
run: |
$versionsOutput = ./get-new-tool-versions/verify-new-tool-version-added-to-image.ps1 `
-ToolName ${{ matrix.tool.name }} `
-ReleasesUrl ${{ matrix.tool.releases-url }} `
-FilterParameter ${{ matrix.tool.filter-parameter }} `
-FilterArch ${{ matrix.tool.filter-arch }}
echo "::set-output name=versions-output::$versionsOutput"
- name: Check versions
if: steps.get-new-tool-versions.outputs.versions-output == ''
run: Write-Host "No new versions found"
- uses: ./.github/actions/send-slack-notification
name: Send Slack notification
if: steps.get-new-tool-versions.outputs.versions-output != ''
with:
url: ${{ secrets.SLACK_CHANNEL_URL }}
tool-name: '${{ matrix.tool.name }}'
tool-version: ${{ steps.get-new-tool-versions.outputs.versions-output }}
image-url: '${{ matrix.tool.image }}'
add-to-toolset-flag: '-AddToToolsetFlag'
check_build:
name: Check build for failures
runs-on: ubuntu-latest
needs: [find-new-tool-versions]
if: failure()
steps:
- uses: actions/checkout@v2
- id: get-failed-jobs
name: Get failed jobs
run: |
$jobs_url = "$env:GITHUB_API_URL/repos/$env:GITHUB_REPOSITORY/actions/runs/$env:GITHUB_RUN_ID/jobs"
$failedJobs = (Invoke-RestMethod -Uri $jobs_url).jobs |
Where-Object conclusion -eq "failure" |
ForEach-Object {"\n\t" + $_.name.split(" ")[-1] + ": $($_.html_url)"}
echo "::set-output name=failed-jobs::$failedJobs"
- uses: ./.github/actions/send-slack-notification
name: Send Slack notification about failure
with:
url: ${{ secrets.SLACK_CHANNEL_URL }}
tool-name: 'Tool name'
pipeline-url: '$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY/actions/runs/$env:GITHUB_RUN_ID'
text: "Missing toolset tool versions checker pipeline has failed jobs:/n/t${{ steps.get-failed-jobs.outputs.failed-jobs }}"

View File

@@ -0,0 +1,108 @@
class AzureDevOpsApi
{
[string] $BaseUrl
[string] $RepoOwner
[object] $AuthHeader
[UInt32] $RetryCount
[UInt32] $RetryIntervalSec
AzureDevOpsApi(
[string] $TeamFoundationCollectionUri,
[string] $ProjectName,
[string] $AccessToken,
[UInt32] $RetryCount,
[UInt32] $RetryIntervalSec
) {
$this.BaseUrl = $this.BuildBaseUrl($TeamFoundationCollectionUri, $ProjectName)
$this.AuthHeader = $this.BuildAuth($AccessToken)
$this.RetryCount = $RetryCount
$this.RetryIntervalSec = $RetryIntervalSec
}
[object] hidden BuildAuth([string]$AccessToken) {
if ([string]::IsNullOrEmpty($AccessToken)) {
return $null
}
return @{
Authorization = "Bearer $AccessToken"
}
}
[string] hidden BuildBaseUrl([string]$TeamFoundationCollectionUri, [string]$ProjectName) {
return "${TeamFoundationCollectionUri}/${ProjectName}/_apis"
}
[object] QueueBuild([string]$ToolVersion, [string]$SourceBranch, [string]$SourceVersion, [UInt32]$DefinitionId){
$url = "build/builds"
# The content of parameters field should be a json string
$buildParameters = @{ VERSION = $ToolVersion } | ConvertTo-Json
$body = @{
definition = @{
id = $DefinitionId
}
sourceBranch = $SourceBranch
sourceVersion = $SourceVersion
parameters = $buildParameters
} | ConvertTo-Json
return $this.InvokeRestMethod($url, 'POST', $body)
}
[object] GetBuildInfo([UInt32]$BuildId){
$url = "build/builds/$BuildId"
return $this.InvokeRestMethod($url, 'GET', $null)
}
[object] UpdateBuildStatus([UInt32]$BuildId, [string]$BuildStatus){
$url = "build/builds/$BuildId"
$body = @{
status = $BuildStatus
} | ConvertTo-Json
return $this.InvokeRestMethod($url, 'PATCH', $body)
}
[string] hidden BuildUrl([string]$Url) {
return "$($this.BaseUrl)/${Url}/?api-version=5.1"
}
[object] hidden InvokeRestMethod(
[string] $Url,
[string] $Method,
[string] $Body
) {
$requestUrl = $this.BuildUrl($Url)
$params = @{
Method = $Method
ContentType = "application/json"
Uri = $requestUrl
Headers = @{}
}
if ($this.AuthHeader) {
$params.Headers += $this.AuthHeader
}
if (![string]::IsNullOrEmpty($body)) {
$params.Body = $Body
}
$params.RetryIntervalSec = $this.RetryIntervalSec
$params.MaximumRetryCount = $this.RetryCount
return Invoke-RestMethod @params
}
}
function Get-AzureDevOpsApi {
param (
[string] $TeamFoundationCollectionUri,
[string] $ProjectName,
[string] $AccessToken,
[UInt32] $RetryCount = 3,
[UInt32] $RetryIntervalSec = 60
)
return [AzureDevOpsApi]::New($TeamFoundationCollectionUri, $ProjectName, $AccessToken, $RetryCount, $RetryIntervalSec)
}

View File

@@ -0,0 +1,44 @@
Import-Module (Join-Path $PSScriptRoot "azure-devops-api.ps1")
class BuildInfo
{
[AzureDevOpsApi] $AzureDevOpsApi
[String] $Name
[UInt32] $Id
[String] $Status
[String] $Result
[String] $Link
BuildInfo([AzureDevOpsApi] $AzureDevOpsApi, [object] $Build)
{
$this.AzureDevOpsApi = $AzureDevOpsApi
$this.Id = $Build.id
$this.Name = $Build.buildNumber
$this.Link = $Build._links.web.href
$this.Status = $Build.status
$this.Result = $Build.result
}
[boolean] IsFinished() {
return ($this.Status -eq "completed") -or ($this.Status -eq "cancelling")
}
[boolean] IsSuccess() {
return $this.Result -eq "succeeded"
}
[void] UpdateBuildInfo() {
$buildInfo = $this.AzureDevOpsApi.GetBuildInfo($this.Id)
$this.Status = $buildInfo.status
$this.Result = $buildInfo.result
}
}
function Get-BuildInfo {
param (
[AzureDevOpsApi] $AzureDevOpsApi,
[object] $Build
)
return [BuildInfo]::New($AzureDevOpsApi, $Build)
}

View File

@@ -0,0 +1,127 @@
param (
[Parameter(Mandatory)] [string] $TeamFoundationCollectionUri,
[Parameter(Mandatory)] [string] $AzureDevOpsProjectName,
[Parameter(Mandatory)] [string] $AzureDevOpsAccessToken,
[Parameter(Mandatory)] [string] $SourceBranch,
[Parameter(Mandatory)] [UInt32] $DefinitionId,
[Parameter(Mandatory)] [string] $SourceVersion,
[Parameter(Mandatory)] [string] $ManifestLink,
[Parameter(Mandatory)] [bool] $WaitForBuilds,
[string] $ToolVersions,
[UInt32] $RetryIntervalSec = 60,
[UInt32] $RetryCount = 3
)
Import-Module (Join-Path $PSScriptRoot "azure-devops-api.ps1")
Import-Module (Join-Path $PSScriptRoot "build-info.ps1")
function Get-ToolVersions {
param (
[Parameter(Mandatory)] [string] $ManifestLink,
[Parameter(Mandatory)] [UInt32] $RetryIntervalSec,
[Parameter(Mandatory)] [UInt32] $Retries,
[string] $ToolVersions
)
[string[]] $versionsList = @()
if ($ToolVersions) {
$versionsList = $ToolVersions.Split(',')
} else {
Write-Host "Get the list of releases from $ManifestLink"
$releases = Invoke-RestMethod $ManifestLink -MaximumRetryCount $Retries -RetryIntervalSec $RetryIntervalSec
$versionsList = $releases.version
}
Write-Host "Versions to build: $versionsList"
return $versionsList
}
function Queue-Builds {
param (
[Parameter(Mandatory)] [AzureDevOpsApi] $AzureDevOpsApi,
[Parameter(Mandatory)] [string[]] $ToolVersions,
[Parameter(Mandatory)] [string] $SourceBranch,
[Parameter(Mandatory)] [string] $SourceVersion,
[Parameter(Mandatory)] [UInt32] $DefinitionId
)
[BuildInfo[]]$queuedBuilds = @()
$ToolVersions | ForEach-Object {
$version = $_.Trim()
Write-Host "Queue build for $version..."
$queuedBuild = $AzureDevOpsApi.QueueBuild($version, $SourceBranch, $SourceVersion, $DefinitionId)
$buildInfo = Get-BuildInfo -AzureDevOpsApi $AzureDevOpsApi -Build $queuedBuild
Write-Host "Queued build: $($buildInfo.Link)"
$queuedBuilds += $buildInfo
}
return $queuedBuilds
}
function Wait-Builds {
param (
[Parameter(Mandatory)] [BuildInfo[]] $Builds,
[Parameter(Mandatory)] [UInt32] $RetryIntervalSec
)
do {
# If build is still running - refresh its status
foreach($build in $builds) {
if (!$build.IsFinished()) {
$build.UpdateBuildInfo()
if ($build.IsFinished()) {
Write-Host "The $($build.Name) build was completed: $($build.Link)"
}
}
}
$runningBuildsCount = ($builds | Where-Object { !$_.IsFinished() }).Length
Start-Sleep -Seconds $RetryIntervalSec
} while($runningBuildsCount -gt 0)
}
function Make-BuildsOutput {
param (
[Parameter(Mandatory)] [BuildInfo[]] $Builds
)
Write-Host "`nBuilds info:"
$builds | Format-Table -AutoSize -Property Name,Id,Status,Result,Link | Out-String -Width 10000
# Return exit code based on status of builds
$failedBuilds = ($builds | Where-Object { !$_.IsSuccess() })
if ($failedBuilds.Length -ne 0) {
Write-Host "##vso[task.logissue type=error;]Builds failed"
$failedBuilds | ForEach-Object -Process { Write-Host "##vso[task.logissue type=error;]Name: $($_.Name); Link: $($_.Link)" }
Write-Host "##vso[task.complete result=Failed]"
} else {
Write-host "##[section]All builds have been passed successfully"
}
}
$azureDevOpsApi = Get-AzureDevOpsApi -TeamFoundationCollectionUri $TeamFoundationCollectionUri `
-ProjectName $AzureDevOpsProjectName `
-AccessToken $AzureDevOpsAccessToken `
-RetryCount $RetryCount `
-RetryIntervalSec $RetryIntervalSec
$toolVersionsList = Get-ToolVersions -ManifestLink $ManifestLink `
-RetryIntervalSec $RetryIntervalSec `
-Retries $RetryCount `
-ToolVersions $ToolVersions
$queuedBuilds = Queue-Builds -AzureDevOpsApi $azureDevOpsApi `
-ToolVersions $toolVersionsList `
-SourceBranch $SourceBranch `
-SourceVersion $SourceVersion `
-DefinitionId $DefinitionId
if ($WaitForBuilds) {
Write-Host "`nWaiting results of builds ..."
Wait-Builds -Builds $queuedBuilds -RetryIntervalSec $RetryIntervalSec
Make-BuildsOutput -Builds $queuedBuilds
}

View File

@@ -0,0 +1,37 @@
name: $(date:yyyyMMdd)$(rev:.r)
trigger: none
pr: none
schedules:
- cron: "0 8 * * Thu"
displayName: Daily build
branches:
include:
- main
always: true
variables:
PoolName: 'Azure Pipelines'
VmImage: 'ubuntu-18.04'
stages:
- stage: Find_New_Versions
dependsOn: []
jobs:
- job: Find_New_Versions
pool:
name: $(PoolName)
vmImage: $(VmImage)
steps:
- template: /azure-pipelines/templates/get-tool-versions-steps.yml
- stage: Check_New_Versions
dependsOn: Find_New_Versions
jobs:
- job: Check_New_Versions
pool:
name: $(PoolName)
vmImage: $(VmImage)
variables:
ToolVersions: $[ stageDependencies.Find_New_Versions.Find_New_Versions.outputs['Get_versions.TOOL_VERSIONS'] ]
steps:
- template: /azure-pipelines/templates/check-versions.yml

View File

@@ -0,0 +1,61 @@
name: $(date:yyyyMMdd)$(rev:.r)
trigger: none
pr: none
schedules:
- cron: "0 3 * * *"
displayName: First daily build
branches:
include:
- main
always: true
- cron: "0 15 * * *"
displayName: Second daily build
branches:
include:
- main
always: true
variables:
PoolName: 'Azure Pipelines'
VmImage: 'ubuntu-18.04'
stages:
- stage: Find_New_Versions
dependsOn: []
jobs:
- job: Find_New_Versions
pool:
name: $(PoolName)
vmImage: $(VmImage)
steps:
- template: /azure-pipelines/templates/get-tool-versions-steps.yml
- stage: Check_New_Versions
dependsOn: Find_New_Versions
jobs:
- job: Check_New_Versions
pool:
name: $(PoolName)
vmImage: $(VmImage)
variables:
ToolVersions: $[ stageDependencies.Find_New_Versions.Find_New_Versions.outputs['Get_versions.TOOL_VERSIONS'] ]
steps:
- template: /azure-pipelines/templates/check-versions.yml
- stage: Trigger_Builds
dependsOn: [Find_New_Versions, Check_New_Versions]
condition: and(succeeded(), ne(variables['WORKFLOW_FILE_NAME'], ''))
jobs:
- deployment: Run_Builds
pool:
name: $(PoolName)
vmImage: $(VmImage)
variables:
ToolVersions: $[ stageDependencies.Find_New_Versions.Find_New_Versions.outputs['Get_versions.TOOL_VERSIONS'] ]
timeoutInMinutes: 180
environment: 'Get Available Tools Versions - Publishing Approval'
strategy:
runOnce:
deploy:
steps:
- template: /azure-pipelines/templates/run-ci-builds-steps.yml

View File

@@ -0,0 +1,49 @@
steps:
- task: PowerShell@2
displayName: Check Versions
condition: and(succeeded(), eq(variables.ToolVersions, ''))
inputs:
TargetType: inline
script: |
Write-Host "No new versions were found"
Import-Module "./azure-devops/azure-devops-api.ps1"
$azureDevOpsApi = Get-AzureDevOpsApi -TeamFoundationCollectionUri $(System.TeamFoundationCollectionUri) `
-ProjectName $(System.TeamProject) `
-AccessToken $(System.AccessToken)
$AzureDevOpsApi.UpdateBuildStatus($(Build.BuildId), 'Cancelling') | Out-Null
Start-Sleep -Seconds 60
- task: PowerShell@2
displayName: 'Set PIPELINE_URL variable'
inputs:
TargetType: inline
script: |
$ToolName = "$(TOOL_NAME)"
if ($ToolName -in @("Python", "Xamarin")) {
$PipelineUrl = " "
} else {
$PipelineUrl = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)"
}
Write-Host "##vso[task.setvariable variable=PIPELINE_URL]$PipelineUrl"
- task: PowerShell@2
displayName: 'Change build name'
inputs:
TargetType: inline
script: |
$newBuildName = "[FOUND] $(Build.BuildNumber)"
Write-Host "##vso[build.updatebuildnumber]$newBuildName"
- task: PowerShell@2
displayName: 'Send Slack notification'
inputs:
targetType: filePath
filePath: './get-new-tool-versions/send-slack-notification.ps1'
arguments: |
-Url "$(SLACK_CHANNEL_URL)" `
-ToolName "$(TOOL_NAME)" `
-ToolVersion "$(ToolVersions)" `
-PipelineUrl "$(PIPELINE_URL)" `
-ImageUrl "$(IMAGE_URL)"

View File

@@ -0,0 +1,9 @@
steps:
- task: PowerShell@2
displayName: 'Get new versions'
name: 'Get_versions'
inputs:
targetType: filePath
filePath: './get-new-tool-versions/get-new-tool-versions.ps1'
arguments: |
-ToolName "$(TOOL_NAME)"

View File

@@ -0,0 +1,15 @@
steps:
- checkout: self
- task: PowerShell@2
displayName: 'Run builds'
inputs:
targetType: filePath
filePath: './github/run-ci-builds.ps1'
arguments: |
-RepositoryFullName $(REPOSITORY_FULL_NAME) `
-AccessToken $(GITHUB_TOKEN) `
-WorkflowFileName $(WORKFLOW_FILE_NAME) `
-WorkflowDispatchRef $(DISPATCH_REF) `
-ToolVersions "$(ToolVersions)" `
-PublishReleases $(PUPLISH_RELEASES)

View File

@@ -3,7 +3,7 @@
Check and return list of new available tool versions
.PARAMETER ToolName
Required parameter. The name of tool for which parser is available (Node, Go, Python)
Required parameter. The name of tool for which parser is available (Node, Go, Python, Xamarin)
#>
param (
@@ -16,10 +16,18 @@ $ToolVersionParser = Get-ToolVersionsParser -ToolName $ToolName
$VersionsFromDist = $ToolVersionParser.GetAvailableVersions()
$VersionsFromManifest = $ToolVersionParser.GetUploadedVersions()
$VersionsToBuild = $VersionsFromDist | Where-Object { $VersionsFromManifest -notcontains $_ }
$joinChars = ", "
if ($ToolName -eq "Xamarin") {
$VersionsToBuild = $VersionsFromDist | Where-Object { $VersionsFromManifest[$_.name] -notcontains $_.version } | ForEach-Object {[string]::Empty} {
'{0,-15} : {1}' -f $_.name, $_.version
}
$joinChars = "\n\t"
} else {
$VersionsToBuild = $VersionsFromDist | Where-Object { $VersionsFromManifest -notcontains $_ }
}
if ($VersionsToBuild) {
$availableVersions = $VersionsToBuild -join ", "
$availableVersions = $VersionsToBuild -join $joinChars
Write-Host "The following versions are available to build:`n${availableVersions}"
Write-Host "::set-output name=TOOL_VERSIONS::${availableVersions}"
Write-Host "##vso[task.setvariable variable=TOOL_VERSIONS;isOutput=true]${availableVersions}"

View File

@@ -2,7 +2,7 @@ using module "./base-parser.psm1"
class GoVersionsParser: BaseVersionsParser {
[SemVer[]] GetUploadedVersions() {
$url = $this.BuildGitHubFileUrl("actions", "go-versions", "main", "versions-manifest.json")
$url = $this.BuildGitHubFileUrl("nikita-bykov", "go-versions", "move-get-go-version", "versions-manifest.json")
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $releases.version
}

View File

@@ -2,7 +2,7 @@ using module "./base-parser.psm1"
class NodeVersionsParser: BaseVersionsParser {
[SemVer[]] GetUploadedVersions() {
$url = $this.BuildGitHubFileUrl("actions", "node-versions", "main", "versions-manifest.json")
$url = $this.BuildGitHubFileUrl("nikita-bykov", "node-versions", "move-get-node-versions-test", "versions-manifest.json")
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $releases.version
}

View File

@@ -1,6 +1,7 @@
using module "./node-parser.psm1"
using module "./go-parser.psm1"
using module "./python-parser.psm1"
using module "./xamarin-parser.psm1"
function Get-ToolVersionsParser {
param(
@@ -12,6 +13,7 @@ function Get-ToolVersionsParser {
"Node" { return [NodeVersionsParser]::New() }
"Go" { return [GoVersionsParser]::New() }
"Python" { return [PythonVersionsParser]::New() }
"Xamarin" { return [XamarinversionsParser]::New() }
Default {
throw "Unknown tool name"
}

View File

@@ -1,25 +0,0 @@
function Search-ToolsVersionsNotOnImage {
param (
[string]$ToolName,
[string]$ReleasesUrl,
[string]$FilterParameter,
[string]$FilterArch
)
$stableReleases = (Invoke-RestMethod $ReleasesUrl) | Where-Object stable -eq $true
$stableReleaseVersions = $stableReleases | ForEach-Object {
if ($ToolName -eq "Node") {
$_.$FilterParameter.split(".")[0] + ".0"
} else {
$_.$FilterParameter.split(".")[0,1] -join"."
}
} | Select-Object -Unique
$toolsetUrl = "https://raw.githubusercontent.com/actions/virtual-environments/main/images/win/toolsets/toolset-2022.json"
$latestMinorVersion = (Invoke-RestMethod $toolsetUrl).toolcache |
Where-Object {$_.name -eq $ToolName -and $_.arch -eq $FilterArch} |
ForEach-Object {$_.versions.Replace("*","0")} |
Select-Object -Last 1
$versionsToAdd = $stableReleaseVersions | Where-Object {[version]$_ -gt [version]$latestMinorVersion}
return $versionsToAdd
}

View File

@@ -1,19 +0,0 @@
function Search-XamarinVersionsNotOnImage {
param (
[string]$ReleasesUrl,
[array]$FilterProducts
)
$xamarinReleases = (Invoke-RestMethod $ReleasesUrl).items
$filteredReleases = $xamarinReleases | Where-Object {$_.name -in $FilterProducts.name} | Sort-Object name | Select-Object name, version
$toolsetUrl = "https://raw.githubusercontent.com/actions/virtual-environments/main/images/macos/toolsets/toolset-11.json"
$uploadedReleases = (Invoke-RestMethod $toolsetUrl).xamarin
$releasesOnImage = @()
foreach ($FilterProduct in $FilterProducts) {
$releasesOnImage += @{$FilterProduct.name = $uploadedReleases.($FilterProduct.property)}
}
$versionsToAdd = $filteredReleases | Where-Object {$releasesOnImage.($_.name) -notcontains $_.version} | ForEach-Object {[string]::Empty} {
'{0,-15} : {1}' -f $_.name, $_.version
}
return $versionsToAdd
}

View File

@@ -0,0 +1,30 @@
using module "./base-parser.psm1"
class XamarinVersionsParser: BaseVersionsParser {
[PSCustomObject] GetAvailableVersions() {
$allVersions = $this.ParseAllAvailableVersions()
return $allVersions
}
[hashtable] GetUploadedVersions() {
$url = $this.BuildGitHubFileUrl("actions", "virtual-environments", "main", "images/macos/toolsets/toolset-11.json")
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
$xamarin = $releases.xamarin
$xamarinReleases = @{
'Mono Framework' = $xamarin.'mono-versions'
'Xamarin.Android' = $xamarin.'android-versions'
'Xamarin.iOS' = $xamarin.'ios-versions'
'Xamarin.Mac' = $xamarin.'mac-versions'
}
return $xamarinReleases
}
hidden [PSCustomObject] ParseAllAvailableVersions() {
$url = "http://aka.ms/manifest/stable"
$filteredProducts = @('Mono Framework', 'Xamarin.Android', 'Xamarin.iOS', 'Xamarin.Mac')
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
$items = $releases.items
$products = $items | Where-Object {$_.name -in $filteredProducts} | Sort-Object name | Select-Object name, version
return $products
}
}

View File

@@ -0,0 +1,60 @@
<#
.SYNOPSIS
Sending messages using Incoming Webhooks
.PARAMETER Url
Required parameter. Incoming Webhook URL to post a message
.PARAMETER ToolName
Required parameter. The name of tool
.PARAMETER ToolVersion
Required parameter. Specifies the version of tool
.PARAMETER PipelineUrl
Required parameter. The pipeline URL
.PARAMETER ImageUrl
Optional parameter. The image URL
#>
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[System.Uri]$Url,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[System.String]$ToolName,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[System.String]$ToolVersion,
[System.String]$PipelineUrl,
[System.String]$ImageUrl = 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png'
)
# Import helpers module
Import-Module $PSScriptRoot/helpers.psm1 -DisableNameChecking
# Create JSON body
$text = "Some jobs were not successful for the following detection pipelines of '$ToolName'\nLink to the pipeline: '$pipelineUrl'"
$jsonBodyMessage = @"
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "$text"
},
"accessory": {
"type": "image",
"image_url": "$imageUrl",
"alt_text": "$toolName"
}
}
]
}
"@
# Send Slack message
$null = Send-SlackPostMessageIncomingWebHook -Uri $url -Body $jsonBodyMessage

View File

@@ -7,15 +7,11 @@ Required parameter. Incoming Webhook URL to post a message
.PARAMETER ToolName
Required parameter. The name of tool
.PARAMETER ToolVersion
Optional parameter. Specifies the version of tool
Required parameter. Specifies the version of tool
.PARAMETER PipelineUrl
Optional parameter. The pipeline URL
Required parameter. The pipeline URL
.PARAMETER ImageUrl
Optional parameter. The image URL
.PARAMETER Text
Optional parameter. The message to post
.PARAMETER AddToToolsetFlag
Optional parameter. Flag to alternate message text for adding new version of a tool to toolset notification
#>
param(
@@ -30,8 +26,7 @@ param(
[System.String]$ToolVersion,
[System.String]$PipelineUrl,
[System.String]$ImageUrl = 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png',
[System.String]$Text,
[Switch]$AddToToolsetFlag
[System.String]$Text
)
# Import helpers module
@@ -39,16 +34,15 @@ Import-Module $PSScriptRoot/helpers.psm1 -DisableNameChecking
# Create JSON body
if ([string]::IsNullOrWhiteSpace($Text)) {
if ($AddToToolsetFlag) {
if ($toolName -eq "Xamarin") {
$Text = "The following versions of '$toolName' are available, consider adding them to toolset: $toolVersion"
} else {
$Text = "The following versions of '$toolName' are available to upload: $toolVersion"
}
if (-not ([string]::IsNullOrWhiteSpace($PipelineUrl))) {
$Text += "\nLink to the pipeline: $pipelineUrl"
}
}
if (-not ([string]::IsNullOrWhiteSpace($PipelineUrl))) {
$Text += "\nLink to the pipeline: $pipelineUrl"
}
$jsonBodyMessage = @"
{
"blocks": [

View File

@@ -1,38 +0,0 @@
<#
.SYNOPSIS
Check and return list of new available tool versions that not added to toolsets yet
.PARAMETER ToolName
Required parameter. The name of tool for which parser is available (Python, Xamarin, PyPy, Node, Go)
#>
param (
[Parameter(Mandatory)]
[ValidateSet("Python", "Xamarin", "PyPy", "Node", "Go")]
[string] $ToolName,
[string] $ReleasesUrl,
[string] $FilterParameter,
[string] $FilterArch
)
Get-ChildItem "$PSScriptRoot/parsers/verify-added-to-image/" | ForEach-Object {Import-Module $_.FullName}
if ($ToolName -in "Python", "PyPy", "Node", "Go") {
$versionsToAdd = Search-ToolsVersionsNotOnImage -ToolName $ToolName -ReleasesUrl $ReleasesUrl -FilterParameter $FilterParameter -FilterArch $FilterArch
}
if ($ToolName -eq "Xamarin") {
$xamarinReleases = "http://aka.ms/manifest/stable"
$xamarinProducts = @(
[PSCustomObject] @{name = 'Mono Framework'; property = 'mono-versions'}
[PSCustomObject] @{name = 'Xamarin.Android'; property = 'android-versions'}
[PSCustomObject] @{name = 'Xamarin.iOS'; property = 'ios-versions'}
[PSCustomObject] @{name = 'Xamarin.Mac'; property = 'mac-versions'}
)
$versionsToAdd = Search-XamarinVersionsNotOnImage -ReleasesUrl $xamarinReleases -FilterProducts $xamarinProducts
$joinChars = "\n\t"
}
$versionsToAdd = $versionsToAdd -join $joinChars
return $versionsToAdd

View File

@@ -1,29 +1,30 @@
param (
[Parameter(Mandatory)][string] $ManifestPath
[Parameter(Mandatory)][string] $ManifestUrl,
[string] $AccessToken
)
$Global:validationFailed = $false
$authorizationHeaderValue = "Basic $AccessToken"
$webRequestHeaders = @{}
if ($AccessToken) {
$webRequestHeaders.Add("Authorization", $authorizationHeaderValue)
}
function Publish-Error {
param(
[string] $ErrorDescription,
[object] $Exception
)
Write-Output "::error ::$ErrorDescription"
if (-not [string]::IsNullOrEmpty($Exception))
{
Write-Output "Exception: $Exception"
}
$Global:validationFailed = $true
Write-Host "##vso[task.logissue type=error]ERROR: $ErrorDescription."
Write-Host "##vso[task.logissue type=error] $Exception"
Write-Host "##vso[task.complete result=Failed;]"
}
function Test-DownloadUrl {
param(
[string] $DownloadUrl
)
param([string] $DownloadUrl)
$request = [System.Net.WebRequest]::Create($DownloadUrl)
if ($AccessToken) {
$request.Headers.Add("Authorization", $authorizationHeaderValue)
}
try {
$response = $request.GetResponse()
return ([int]$response.StatusCode -eq 200)
@@ -32,16 +33,19 @@ function Test-DownloadUrl {
}
}
if (-not (Test-Path $ManifestPath)) {
Publish-Error "Unable to find manifest json file at '$ManifestPath'"
Write-Host "Downloading manifest json from '$ManifestUrl'..."
try {
$manifestResponse = Invoke-WebRequest -Method Get -Uri $ManifestUrl -Headers $webRequestHeaders
} catch {
Publish-Error "Unable to download manifest json from '$ManifestUrl'" $_
exit 1
}
Write-Host "Parsing manifest json content from '$ManifestPath'..."
Write-Host "Parsing manifest json content from '$ManifestUrl'..."
try {
$manifestJson = Get-Content $ManifestPath | ConvertFrom-Json
$manifestJson = $manifestResponse.Content | ConvertFrom-Json
} catch {
Publish-Error "Unable to parse manifest json content '$ManifestPath'" $_
Publish-Error "Unable to parse manifest json content '$ManifestUrl'" $_
exit 1
}
@@ -57,7 +61,3 @@ $manifestJson | ForEach-Object {
}
}
}
if ($Global:validationFailed) {
exit 1
}