Compare commits

..

81 Commits

Author SHA1 Message Date
Maxim Lobanov
f19d5f4b3c fix comments 2021-06-16 09:17:33 +00:00
Maxim Lobanov
00039881ba remove comments 2021-06-16 05:48:00 +00:00
Maxim Lobanov
878c283d3b implement pester tests 2021-06-16 05:46:31 +00:00
Maxim Lobanov
41a1acf1a4 first attempt to support lts 2021-06-15 19:24:00 +00:00
Maxim Lobanov
2bd3b2a3c2 Merge pull request #31 from actions/al-cheb/fix-xamarin-tool
Rename toolset for macOS Big Sur
2021-05-20 11:11:02 +03:00
Aleksandr Chebotov
e81db48281 Rename toolset for macOS Big Sur 2021-05-20 11:07:36 +03:00
MaksimZhukov
ab218c2436 Merge pull request #25 from actions/al-cheb/add-xamarin-tool
Add xamarin tool version check
2021-05-05 17:13:29 +03:00
Aleksandr Chebotov
504e746b96 add missing bracket 2021-05-05 16:47:49 +03:00
Maxim Lobanov
4d97edc41a Merge pull request #26 from actions/al-cheb/fix-go-parser
[Go] update regex pattern
2021-04-06 17:46:52 +03:00
Aleksandr Chebotov
80bbe2ac05 update regex pattern 2021-04-06 16:03:15 +03:00
Aleksandr Chebotov
77b53792b3 update message for Xamarin 2021-03-22 21:35:24 +03:00
Aleksandr Chebotov
725c68b777 fix message 2021-03-22 13:44:19 +03:00
Aleksandr Chebotov
81507e485b fix format 2021-03-19 15:45:09 +03:00
Aleksandr Chebotov
7ec75e0761 add xamarin tool version 2021-03-19 15:23:57 +03:00
Maxim Lobanov
590ebcd1ab Merge pull request #24 from actions/add-codeowners
Create CODEOWNERS
2021-01-20 21:38:59 +03:00
Maxim Lobanov
cc2ef5ff7d Update CODEOWNERS 2021-01-11 19:49:58 +03:00
Maxim Lobanov
e37209e8d6 Create CODEOWNERS 2021-01-08 12:36:57 +03:00
Maxim Lobanov
3d7121daba Merge pull request #21 from actions/v-malob/support-go-beta
Support parsing of Go Beta
2020-12-21 23:36:55 +03:00
Maxim Lobanov
f5bdb61b33 Update go-parser.psm1 2020-12-21 20:38:36 +03:00
Maxim Lobanov
96a98e9fb3 Update go-parser.psm1 2020-12-21 20:35:56 +03:00
Maxim Lobanov
5f0e0eebc8 Merge pull request #20 from actions/v-malob/fix-failed-notifications
Cancel builds if new versions are not found instead of failures
2020-12-21 11:06:21 +03:00
Maxim Lobanov
32fbb87915 Update check-versions.yml 2020-12-21 09:23:39 +03:00
Maxim Lobanov
b22990961a Merge pull request #19 from actions/v-malob/fix-yaml-2
Fix YAML dependency
2020-12-16 14:36:39 +03:00
Maxim Lobanov
fc90da9ef1 Update get-tool-versions.yml 2020-12-16 14:33:30 +03:00
Maxim Lobanov
e9cccdf5ed Merge pull request #18 from actions/v-malob/fix-yaml-publish
Fix notifications about new versions
2020-12-16 12:44:16 +03:00
Maxim Lobanov
c2935ecf46 Update get-tool-versions.yml 2020-12-16 12:06:57 +03:00
Maxim Lobanov
0624df7ce9 Update get-tool-versions.yml 2020-12-16 12:05:05 +03:00
Maxim Lobanov
11360e1ff9 polish changes 2020-12-16 12:00:18 +03:00
Maxim Lobanov
ecc77a65f7 Update get-tool-versions-steps.yml 2020-12-16 11:48:43 +03:00
Maxim Lobanov
c304390e31 test 2020-12-16 11:46:22 +03:00
Maxim Lobanov
7e43a35182 Update get-tool-versions-steps.yml 2020-12-16 11:41:58 +03:00
Maxim Lobanov
0d478268bb fix comments 2020-12-16 11:40:43 +03:00
Maxim Lobanov
14f9ca7540 Update get-tool-versions.yml 2020-12-16 11:36:03 +03:00
Maxim Lobanov
1575bb86d1 Update get-tool-versions.yml 2020-12-16 11:35:33 +03:00
Maxim Lobanov
1b966031cc Update get-tool-versions.yml 2020-12-16 11:31:23 +03:00
Maxim Lobanov
4a932e134c Update get-tool-versions.yml 2020-12-16 11:28:26 +03:00
Maxim Lobanov
3e3417e894 Update get-tool-versions.yml 2020-12-16 11:24:39 +03:00
Maxim Lobanov
a5e1431377 Update get-tool-versions.yml 2020-12-16 10:58:06 +03:00
Maxim Lobanov
fb5b7794f0 Update get-tool-versions.yml 2020-12-16 10:57:27 +03:00
Maxim Lobanov
ea9029b06d Update get-tool-versions.yml 2020-12-16 10:54:30 +03:00
Maxim Lobanov
6bc823feae Update get-tool-versions.yml 2020-12-16 10:49:38 +03:00
Maxim Lobanov
84daa05fbc Update get-tool-versions.yml 2020-12-16 10:43:43 +03:00
Maxim Lobanov
e1cbdde483 test 2020-12-16 10:40:09 +03:00
Maxim Lobanov
d61f870ac7 Update get-new-tool-versions.ps1 2020-12-16 10:35:57 +03:00
Maxim Lobanov
e9a19e1251 Update get-tool-versions-steps.yml 2020-12-16 10:31:40 +03:00
Maxim Lobanov
3bfd520dd0 Update get-tool-versions.yml 2020-12-16 10:30:06 +03:00
Maxim Lobanov
840e3a64d3 Update get-tool-versions-steps.yml 2020-12-16 10:26:58 +03:00
Maxim Lobanov
ab240b2f15 Merge pull request #17 from actions/v-malob/python-parser
Rework version grabber and add Python support
2020-12-09 22:25:52 +03:00
Maxim Lobanov
2e6d8df345 fix comments 2020-12-09 15:17:11 +03:00
Maxim Lobanov
5b7cb28e2e fix nitpicks 2020-12-09 14:30:30 +03:00
Maxim Lobanov
4ce7f7efbc Delete get-new-tool-versions.Tests.ps1 2020-12-09 13:32:54 +03:00
Maxim Lobanov
5e5de280d6 fix minor nitpicks 2020-12-09 12:28:15 +03:00
Maxim Lobanov
236d44a167 Update get-tool-versions-steps.yml 2020-12-09 12:07:11 +03:00
Maxim Lobanov
02afcca5c6 Update get-tool-versions-steps.yml 2020-12-09 11:50:51 +03:00
Maxim Lobanov
f4ff9fb93d test 2020-12-09 11:48:13 +03:00
Maxim Lobanov
21cbc1e8ca Update get-tool-versions.yml 2020-12-09 11:15:51 +03:00
Maxim Lobanov
109e6bd009 check condition 2020-12-09 11:15:10 +03:00
Maxim Lobanov
be051a1f12 add parsers 2020-12-09 11:06:04 +03:00
MaksimZhukov
4b0fa42d99 Merge pull request #16 from actions/v-nibyko/boost
Add GetToolDirectory function and fix Get-CommandResult to work properly on Windows
2020-09-09 15:07:13 +03:00
Nikita Bykov
5bcb80c333 refactored function 2020-09-09 12:28:21 +03:00
Nikita Bykov
3f2b844267 added the function GetToolDirectory 2020-09-09 12:18:45 +03:00
Nikita Bykov
7f90ceb82c fixed naming 2020-09-08 14:00:33 +03:00
Nikita Bykov
34c6f7f0ec Resolved comments 2020-09-08 13:59:03 +03:00
Nikita Bykov
94d8a3af83 removed changes 2020-09-08 13:27:15 +03:00
Nikita Bykov
89ebce9383 Fix win-vs-env.psm1 and pester-extensions.psm1 (#15) 2020-09-08 11:39:22 +03:00
MaksimZhukov
f8f76caff1 Merge pull request #14 from actions/v-mazhuk/move-python-versions-ci
Move python-versions CI
2020-08-28 14:01:39 +03:00
MaksimZhukov
8463c1f4c0 Remove redundant string 2020-08-28 12:51:16 +03:00
MaksimZhukov
8e8ae73c1d Fix SYNOPSIS 2020-08-28 11:43:35 +03:00
MaksimZhukov
7aa3827a98 Fix inputs type 2020-08-28 10:16:06 +03:00
MaksimZhukov
2ea972432a Update CreateWorkflowDispatch method 2020-08-27 18:53:42 +03:00
MaksimZhukov
7e2bc9a237 Add create-release.ps1 script 2020-08-27 15:26:35 +03:00
Maxim Lobanov
3b38e3de4c Merge pull request #13 from actions/v-mazhuk/migrate-tools-ci-to-github-actions
Migrate tools CI to GitHub Actions
2020-08-25 11:56:23 +03:00
MaksimZhukov
606411ff6f Update GetPullRequest function 2020-08-24 19:59:55 +03:00
MaksimZhukov
5e417400d9 Add Get-CommandResult function 2020-08-24 18:51:49 +03:00
MaksimZhukov
15842ce7fe Update ShouldReturnZeroExitCode function 2020-08-24 18:40:08 +03:00
MaksimZhukov
45424846c7 Fix typo 2020-08-24 15:36:31 +03:00
MaksimZhukov
ebc70e779a Update github API 2020-08-24 14:53:44 +03:00
MaksimZhukov
347402ff31 Update github API 2020-08-24 14:07:45 +03:00
MaksimZhukov
7a56615638 Migrate tools CI to GA 2020-08-21 19:35:25 +03:00
Maxim Lobanov
68072bedef Merge pull request #12 from actions/v-mazhuk/fix-bug-with-versions-manifest
Build correct manifest json if release includes one asset
2020-07-30 12:07:01 +03:00
MaksimZhukov
377623de6c Fix bug related to versions-manifest-generator 2020-07-29 17:26:07 +03:00
26 changed files with 747 additions and 285 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @actions/virtual-environments-owners

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

@@ -20,25 +20,38 @@ variables:
VmImage: 'ubuntu-18.04' VmImage: 'ubuntu-18.04'
stages: stages:
- stage: Get_New_Versions - stage: Find_New_Versions
dependsOn: [] dependsOn: []
jobs: jobs:
- job: Get_Tool_Versions - job: Find_New_Versions
pool: pool:
name: $(PoolName) name: $(PoolName)
vmImage: $(VmImage) vmImage: $(VmImage)
steps: steps:
- template: /azure-pipelines/templates/get-tool-versions-steps.yml - 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 - stage: Trigger_Builds
dependsOn: Get_New_Versions dependsOn: [Find_New_Versions, Check_New_Versions]
condition: and(succeeded(), ne(variables['WORKFLOW_FILE_NAME'], ''))
jobs: jobs:
- deployment: Run_Builds - deployment: Run_Builds
pool: pool:
name: $(PoolName) name: $(PoolName)
vmImage: $(VmImage) vmImage: $(VmImage)
variables: variables:
ToolVersions: $[ stageDependencies.Get_New_Versions.Get_Tool_Versions.outputs['Get_versions.TOOL_VERSIONS'] ] ToolVersions: $[ stageDependencies.Find_New_Versions.Find_New_Versions.outputs['Get_versions.TOOL_VERSIONS'] ]
timeoutInMinutes: 180 timeoutInMinutes: 180
environment: 'Get Available Tools Versions - Publishing Approval' environment: 'Get Available Tools Versions - Publishing Approval'
strategy: strategy:

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

@@ -6,42 +6,4 @@ steps:
targetType: filePath targetType: filePath
filePath: './get-new-tool-versions/get-new-tool-versions.ps1' filePath: './get-new-tool-versions/get-new-tool-versions.ps1'
arguments: | arguments: |
-DistURL "$(DIST_URL)" ` -ToolName "$(TOOL_NAME)"
-ManifestLink "$(MANIFEST_URL)" `
-VersionFilterToInclude $(INCLUDE_FILTER) `
-VersionFilterToExclude $(EXCLUDE_FILTER)
- task: PowerShell@2
displayName: 'Cancel build'
condition: and(succeeded(), eq(variables['Get_versions.TOOL_VERSIONS'], ''))
inputs:
TargetType: inline
script: |
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
- task: PowerShell@2
displayName: 'Set env variable'
condition: and(succeeded(), ne(variables['Get_versions.TOOL_VERSIONS'], ''))
inputs:
TargetType: inline
script: |
$PipelineUrl = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)"
Write-Output "##vso[task.setvariable variable=PIPELINE_URL]$PipelineUrl"
- task: PowerShell@2
displayName: 'Send Slack notification'
condition: and(succeeded(), ne(variables['Get_versions.TOOL_VERSIONS'], ''))
inputs:
targetType: filePath
filePath: './get-new-tool-versions/send-slack-notification.ps1'
arguments: |
-Url "$(SLACK_CHANNEL_URL)" `
-ToolName "$(TOOL_NAME)" `
-ToolVersion "$(Get_versions.TOOL_VERSIONS)" `
-PipelineUrl "$(PIPELINE_URL)" `
-ImageUrl "$(IMAGE_URL)"

View File

@@ -1,29 +1,15 @@
steps: steps:
- checkout: self - checkout: self
- task: PowerShell@2
displayName: 'Get source version'
inputs:
TargetType: inline
script: |
$url = "https://api.github.com/repos/$(REPOSITORY)/commits/$(BRANCH)"
$commit = Invoke-RestMethod -Uri $url -Method "GET"
Write-Output "##vso[task.setvariable variable=COMMIT_SHA]$($commit.sha)"
- task: PowerShell@2 - task: PowerShell@2
displayName: 'Run builds' displayName: 'Run builds'
inputs: inputs:
targetType: filePath targetType: filePath
filePath: './azure-devops/run-ci-builds.ps1' filePath: './github/run-ci-builds.ps1'
arguments: | arguments: |
-TeamFoundationCollectionUri $(System.TeamFoundationCollectionUri) ` -RepositoryFullName $(REPOSITORY_FULL_NAME) `
-AzureDevOpsProjectName $(System.TeamProject) ` -AccessToken $(GITHUB_TOKEN) `
-AzureDevOpsAccessToken $(System.AccessToken) ` -WorkflowFileName $(WORKFLOW_FILE_NAME) `
-SourceBranch $(BRANCH) ` -WorkflowDispatchRef $(DISPATCH_REF) `
-DefinitionId $(DEFINITION_ID) `
-SourceVersion $(COMMIT_SHA) `
-ManifestLink $(MANIFEST_URL) `
-WaitForBuilds $(WAIT_FOR_BUILDS) `
-ToolVersions "$(ToolVersions)" ` -ToolVersions "$(ToolVersions)" `
-RetryIntervalSec $(INTERVAL_SEC) ` -PublishReleases $(PUPLISH_RELEASES)
-RetryCount $(RETRY_COUNT)

View File

@@ -3,6 +3,11 @@ param (
) )
$targetPath = $env:AGENT_TOOLSDIRECTORY $targetPath = $env:AGENT_TOOLSDIRECTORY
if ([string]::IsNullOrEmpty($targetPath)) {
# GitHub Windows images don't have `AGENT_TOOLSDIRECTORY` variable
$targetPath = $env:RUNNER_TOOL_CACHE
}
if ($ToolName) { if ($ToolName) {
$targetPath = Join-Path $targetPath $ToolName $targetPath = Join-Path $targetPath $ToolName
} }

View File

@@ -83,3 +83,26 @@ function IsNixPlatform {
return ($Platform -match "macos") -or ($Platform -match "darwin") -or ($Platform -match "ubuntu") -or ($Platform -match "linux") return ($Platform -match "macos") -or ($Platform -match "darwin") -or ($Platform -match "ubuntu") -or ($Platform -match "linux")
} }
<#
.SYNOPSIS
Get root directory of selected tool
#>
function GetToolDirectory {
param(
[Parameter(Mandatory=$true)]
[String]$ToolName,
[Parameter(Mandatory=$true)]
[String]$Version,
[Parameter(Mandatory=$true)]
[String]$Architecture
)
$targetPath = $env:AGENT_TOOLSDIRECTORY
if ([string]::IsNullOrEmpty($targetPath)) {
# GitHub Windows images don't have `AGENT_TOOLSDIRECTORY` variable
$targetPath = $env:RUNNER_TOOL_CACHE
}
$ToolcachePath = Join-Path -Path $targetPath -ChildPath $ToolName
$ToolcacheVersionPath = Join-Path -Path $ToolcachePath -ChildPath $Version
return Join-Path $ToolcacheVersionPath $Architecture
}

View File

@@ -1,93 +0,0 @@
#Requires -Modules Pester
Import-Module (Join-Path $PSScriptRoot "helpers.psm1") -Force
Describe "Validate-FiltersFormat" {
It "Filter with word" {
{ Validate-FiltersFormat -Filters @("1two.2") } | Should -Throw "Invalid filter format"
}
It "Filter with non-word character" {
{ Validate-FiltersFormat -Filters @("1,.2") } | Should -Throw "Invalid filter format"
}
It "Valid filters" {
{ Validate-FiltersFormat -Filters @("*", "1", "1.*", "1.2", "1.2.*") } | Should -Not -Throw "Invalid filter format"
}
}
Describe "Format-Versions" {
It "Clean versions" {
$actualOutput = Format-Versions -Versions @("14.2.0", "1.14.0")
$expectedOutput = @("14.2.0", "1.14.0")
$actualOutput | Should -Be $expectedOutput
}
It "Versions with prefixes" {
$actualOutput = Format-Versions -Versions @("v14.2.0", "go1.14.0")
$expectedOutput = @("14.2.0", "1.14.0")
$actualOutput | Should -Be $expectedOutput
}
It "Skip beta and rc versions" {
$actualOutput = Format-Versions -Versions @("14.2.0-beta", "v1.14.0-rc-1")
$expectedOutput = @()
$actualOutput | Should -Be $expectedOutput
}
It "Short version" {
$actualOutput = Format-Versions -Versions @("14.2", "v2.0")
$expectedOutput = @("14.2.0", "2.0.0")
$actualOutput | Should -Be $expectedOutput
}
It "Skip versions with 1 digit" {
$actualOutput = Format-Versions -Versions @("14", "v2")
$expectedOutput = @()
$actualOutput | Should -Be $expectedOutput
}
}
Describe "Select-VersionsByFilter" {
$inputVersions = @("8.2.1", "9.3.3", "10.0.2", "10.0.3", "10.5.6", "12.4.3", "12.5.1", "14.2.0")
It "Include filter only" {
$includeFilters = @("8.*", "14.*")
$excludeFilters = @()
$actualOutput = Select-VersionsByFilter -Versions $inputVersions -IncludeFilters $includeFilters -ExcludeFilters $excludeFilters
$expectedOutput = @("8.2.1", "14.2.0")
$actualOutput | Should -Be $expectedOutput
}
It "Include and exclude filters" {
$includeFilters = @("10.*", "12.*")
$excludeFilters = @("10.0.*", "12.4.3")
$actualOutput = Select-VersionsByFilter -Versions $inputVersions -IncludeFilters $includeFilters -ExcludeFilters $excludeFilters
$expectedOutput = @("10.5.6", "12.5.1")
$actualOutput | Should -Be $expectedOutput
}
It "Exclude filter only" {
$includeFilters = @()
$excludeFilters = @("10.*", "12.*")
$actualOutput = Select-VersionsByFilter -Versions $inputVersions -IncludeFilters $includeFilters -ExcludeFilters $excludeFilters
$expectedOutput = @("8.2.1", "9.3.3", "14.2.0")
$actualOutput | Should -Be $expectedOutput
}
It "Include and exclude filters are empty" {
$actualOutput = Select-VersionsByFilter -Versions $inputVersions
$expectedOutput = @("8.2.1", "9.3.3", "10.0.2", "10.0.3", "10.5.6", "12.4.3", "12.5.1", "14.2.0")
$actualOutput | Should -Be $expectedOutput
}
}
Describe "Skip-ExistingVersions" {
It "Substract versions correctly" {
$distInput = @("14.2.0", "14.3.0", "14.4.0", "14.4.1")
$manifestInput = @("12.0.0", "14.2.0", "14.4.0")
$actualOutput = Skip-ExistingVersions -VersionsFromDist $distInput -VersionsFromManifest $manifestInput
$expectedOutput = @("14.3.0", "14.4.1")
$actualOutput | Should -Be $expectedOutput
}
}

View File

@@ -2,79 +2,34 @@
.SYNOPSIS .SYNOPSIS
Check and return list of new available tool versions Check and return list of new available tool versions
.PARAMETER DistURL .PARAMETER ToolName
Required parameter. Link to the json file included all available tool versions Required parameter. The name of tool for which parser is available (Node, Go, Python, Xamarin)
.PARAMETER ManifestLink
Required parameter. Link to the the version-manifest.json file
.PARAMETER VersionFilterToInclude
Optional parameter. List of filters to include particular versions
.PARAMETER VersionFilterToExclude
Optional parameter. List of filters to exclude particular versions
.PARAMETER RetryIntervalSec
Optional parameter. Retry interval in seconds
.PARAMETER RetryCount
Optional parameter. Retry count
#> #>
param ( param (
[Parameter(Mandatory)] [string] $DistURL, [Parameter(Mandatory)] [string] $ToolName
[Parameter(Mandatory)] [string] $ManifestLink,
[string[]] $VersionFilterToInclude,
[string[]] $VersionFilterToExclude,
[UInt32] $RetryIntervalSec = 60,
[UInt32] $RetryCount = 3
) )
Import-Module (Join-Path $PSScriptRoot "helpers.psm1") Import-Module "$PSScriptRoot/parsers/parsers-factory.psm1"
function Get-VersionsByUrl { $ToolVersionParser = Get-ToolVersionsParser -ToolName $ToolName
param ( $VersionsFromDist = $ToolVersionParser.GetAvailableVersions()
[Parameter(Mandatory)] [string] $ToolPackagesUrl, $VersionsFromManifest = $ToolVersionParser.GetUploadedVersions()
[Parameter(Mandatory)] [UInt32] $RetryIntervalSec,
[Parameter(Mandatory)] [UInt32] $RetryCount
)
$packages = Invoke-RestMethod $ToolPackagesUrl -MaximumRetryCount $RetryCount -RetryIntervalSec $RetryIntervalSec $joinChars = ", "
return $packages.version 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 ($VersionFilterToInclude) { if ($VersionsToBuild) {
Validate-FiltersFormat -Filters $VersionFilterToInclude $availableVersions = $VersionsToBuild -join $joinChars
} Write-Host "The following versions are available to build:`n${availableVersions}"
Write-Host "##vso[task.setvariable variable=TOOL_VERSIONS;isOutput=true]${availableVersions}"
if ($VersionFilterToExclude) {
Validate-FiltersFormat -Filters $VersionFilterToExclude
}
Write-Host "Get the packages list from $DistURL"
$versionsFromDist = Get-VersionsByUrl -ToolPackagesUrl $DistURL `
-RetryIntervalSec $RetryIntervalSec `
-RetryCount $RetryCount
Write-Host "Get the packages list from $ManifestLink"
[Version[]] $versionsFromManifest = Get-VersionsByUrl -ToolPackagesUrl $ManifestLink `
-RetryIntervalSec $RetryIntervalSec `
-RetryCount $RetryCount
[Version[]] $formattedVersions = Format-Versions -Versions $versionsFromDist
$formattedVersions = Select-VersionsByFilter -Versions $formattedVersions `
-IncludeFilters $VersionFilterToInclude `
-ExcludeFilters $VersionFilterToExclude
if (-not $formattedVersions) {
Write-Host "Couldn't find available versions with current filters"
exit 1
}
$versionsToBuild = Skip-ExistingVersions -VersionsFromManifest $versionsFromManifest `
-VersionsFromDist $formattedVersions
if ($versionsToBuild) {
$availableVersions = $versionsToBuild -join ","
$toolVersions = $availableVersions.Replace(",",", ")
Write-Host "The following versions are available to build:`n$toolVersions"
Write-Output "##vso[task.setvariable variable=TOOL_VERSIONS;isOutput=true]$toolVersions"
} else { } else {
Write-Host "There aren't versions to build" Write-Host "There aren't versions to build"
} }

View File

@@ -1,17 +1,3 @@
function Validate-FiltersFormat {
param (
[Parameter(Mandatory)] [string[]] $Filters
)
foreach($filter in $Filters) {
$filter.Split('.') | ForEach-Object {
if (($_ -notmatch '^\d+$') -and ($_ -ne '*')) {
throw "Invalid filter format - $filter"
}
}
}
}
function Format-Versions { function Format-Versions {
param ( param (
[Parameter(Mandatory)] [string[]] $Versions [Parameter(Mandatory)] [string[]] $Versions

View File

@@ -0,0 +1,31 @@
class BaseVersionsParser {
[Int32]$ApiRetryCount = 3
[Int32]$ApiRetryIntervalSeconds = 60
[SemVer[]] GetAvailableVersions() {
$allVersionsRaw = $this.ParseAllAvailableVersions()
$allVersions = $allVersionsRaw | ForEach-Object { $this.FormatVersion($_) }
$filteredVersions = $allVersions | Where-Object { $this.ShouldIncludeVersion($_) }
return $filteredVersions
}
[SemVer[]] GetUploadedVersions() {
throw "Method is not implemented in base class"
}
hidden [SemVer[]] ParseAllAvailableVersions() {
throw "Method is not implemented in base class"
}
hidden [SemVer] FormatVersion([string]$VersionSpec) {
throw "Method is not implemented in base class"
}
hidden [bool] ShouldIncludeVersion([SemVer]$Version) {
throw "Method is not implemented in base class"
}
hidden [string] BuildGitHubFileUrl($OrganizationName, $RepositoryName, $BranchName, $FilePath) {
return "https://raw.githubusercontent.com/${OrganizationName}/${RepositoryName}/${BranchName}/${FilePath}"
}
}

View File

@@ -0,0 +1,30 @@
using module "./base-parser.psm1"
class GoVersionsParser: BaseVersionsParser {
[SemVer[]] GetUploadedVersions() {
$url = $this.BuildGitHubFileUrl("actions", "go-versions", "main", "versions-manifest.json")
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $releases.version
}
hidden [string[]] ParseAllAvailableVersions() {
$url = "https://golang.org/dl/?mode=json&include=all"
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $releases.version
}
hidden [SemVer] FormatVersion([string]$VersionSpec) {
$cleanVersion = $VersionSpec -replace "^go", ""
$semanticVersion = $cleanVersion -replace '(\d+\.\d+\.?\d*?)((?:alpha|beta|rc))(\d*)', '$1-$2.$3'
return [SemVer]$semanticVersion
}
hidden [bool] ShouldIncludeVersion([SemVer]$Version) {
if ($Version.PreReleaseLabel) {
return $false
}
# For Go, we include all versions greater than 1.12
return $Version -gt [SemVer]"1.12.0"
}
}

View File

@@ -0,0 +1,30 @@
using module "./base-parser.psm1"
class NodeVersionsParser: BaseVersionsParser {
[SemVer[]] GetUploadedVersions() {
$url = $this.BuildGitHubFileUrl("actions", "node-versions", "main", "versions-manifest.json")
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $releases.version
}
hidden [string[]] ParseAllAvailableVersions() {
$url = "https://nodejs.org/dist/index.json"
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $releases.version
}
hidden [SemVer] FormatVersion([string]$VersionSpec) {
$cleanVersion = $VersionSpec -replace "^v", ""
return [SemVer]$cleanVersion
}
hidden [bool] ShouldIncludeVersion([SemVer]$Version) {
if ($Version.Major -lt 8) {
return $false
}
# For Node.JS, we should include all LTS versions (all even-numbered releases)
# https://nodejs.org/en/about/releases/
return $Version.Major % 2 -eq 0
}
}

View File

@@ -0,0 +1,21 @@
using module "./node-parser.psm1"
using module "./go-parser.psm1"
using module "./python-parser.psm1"
using module "./xamarin-parser.psm1"
function Get-ToolVersionsParser {
param(
[Parameter(Mandatory)]
[string]$ToolName
)
switch ($ToolName) {
"Node" { return [NodeVersionsParser]::New() }
"Go" { return [GoVersionsParser]::New() }
"Python" { return [PythonVersionsParser]::New() }
"Xamarin" { return [XamarinversionsParser]::New() }
Default {
throw "Unknown tool name"
}
}
}

View File

@@ -0,0 +1,53 @@
using module "./base-parser.psm1"
class PythonVersionsParser: BaseVersionsParser {
[SemVer[]] GetUploadedVersions() {
$url = $this.BuildGitHubFileUrl("actions", "python-versions", "main", "versions-manifest.json")
$releases = Invoke-RestMethod $url -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $releases.version
}
hidden [string[]] ParseAllAvailableVersions() {
$stableVersionsUrl = "https://www.python.org/ftp/python"
$stableVersionsHtmlRaw = Invoke-WebRequest $stableVersionsUrl -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
$stableVersionsList = $stableVersionsHtmlRaw.Links.href | Where-Object {
$parsed = $null
return $_.EndsWith("/") -and [SemVer]::TryParse($_.Replace("/", ""), [ref]$parsed)
}
return $stableVersionsList | ForEach-Object {
$subVersionsUrl = "${stableVersionsUrl}/${_}"
$subVersionsHtmlRaw = Invoke-WebRequest $subVersionsUrl -MaximumRetryCount $this.ApiRetryCount -RetryIntervalSec $this.ApiRetryIntervalSeconds
return $subVersionsHtmlRaw.Links.href | ForEach-Object {
if ($_ -match "^Python-(\d+\.\d+\.\d+[a-z]{0,2}\d*)\.tgz$") {
return $Matches[1]
}
}
}
}
hidden [SemVer] FormatVersion([string]$VersionSpec) {
$VersionSpec -match "^(\d+)\.(\d+)\.(\d+)([a-z]{1,2})?(\d+)?$"
if ($Matches.Count -gt 4) {
$VersionLabel = "{0}.{1}" -f $this.ConvertPythonLabel($Matches[4]), $Matches[5]
return [SemVer]::new($Matches[1], $Matches[2], $Matches[3], $VersionLabel)
}
return [SemVer]::new($Matches[1], $Matches[2], $Matches[3])
}
hidden [string] ConvertPythonLabel([string]$Label) {
switch ($Label) {
"a" { return "alpha" }
"b" { return "beta" }
}
return $Label
}
[bool] ShouldIncludeVersion([SemVer]$Version) {
# For Python, we include all versions greater than 3.9.0
return $Version -gt [SemVer]"3.9.0"
}
}

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

@@ -27,10 +27,7 @@ param(
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[System.String]$ToolVersion, [System.String]$ToolVersion,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[System.String]$PipelineUrl, [System.String]$PipelineUrl,
[System.String]$ImageUrl = 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png' [System.String]$ImageUrl = 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png'
) )
@@ -38,7 +35,14 @@ param(
Import-Module $PSScriptRoot/helpers.psm1 -DisableNameChecking Import-Module $PSScriptRoot/helpers.psm1 -DisableNameChecking
# Create JSON body # Create JSON body
$text = "The following versions of '$toolName' are available to upload: $toolVersion\nLink to the pipeline: $pipelineUrl" 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"
}
$jsonBodyMessage = @" $jsonBodyMessage = @"
{ {
"blocks": [ "blocks": [

View File

@@ -2,10 +2,8 @@
.SYNOPSIS .SYNOPSIS
Create commit with all unstaged changes in repository and create pull-request Create commit with all unstaged changes in repository and create pull-request
.PARAMETER RepositoryOwner .PARAMETER RepositoryFullName
Required parameter. The organization which tool repository belongs Required parameter. The owner and repository name. For example, 'actions/versions-package-tools'
.PARAMETER RepositoryName
Optional parameter. The name of tool repository
.PARAMETER AccessToken .PARAMETER AccessToken
Required parameter. PAT Token to authorize Required parameter. PAT Token to authorize
.PARAMETER BranchName .PARAMETER BranchName
@@ -18,8 +16,7 @@ Required parameter. The title of pull-request
Required parameter. The description of pull-request Required parameter. The description of pull-request
#> #>
param ( param (
[Parameter(Mandatory)] [string] $RepositoryOwner, [Parameter(Mandatory)] [string] $RepositoryFullName,
[Parameter(Mandatory)] [string] $RepositoryName,
[Parameter(Mandatory)] [string] $AccessToken, [Parameter(Mandatory)] [string] $AccessToken,
[Parameter(Mandatory)] [string] $BranchName, [Parameter(Mandatory)] [string] $BranchName,
[Parameter(Mandatory)] [string] $CommitMessage, [Parameter(Mandatory)] [string] $CommitMessage,
@@ -46,11 +43,11 @@ function Update-PullRequest {
$updatedPullRequest = $GitHubApi.UpdatePullRequest($Title, $Body, $BranchName, $PullRequest.number) $updatedPullRequest = $GitHubApi.UpdatePullRequest($Title, $Body, $BranchName, $PullRequest.number)
if (($updatedPullRequest -eq $null) -or ($updatedPullRequest.html_url -eq $null)) { if (($null -eq $updatedPullRequest) -or ($null -eq $updatedPullRequest.html_url)) {
Write-Host "##vso[task.logissue type=error;] Unexpected error occurs while updating pull request." Write-Host "Unexpected error occurs while updating pull request."
exit 1 exit 1
} }
Write-host "##[section] Pull request updated: $($updatedPullRequest.html_url)" Write-host "Pull request updated: $($updatedPullRequest.html_url)"
} }
function Create-PullRequest { function Create-PullRequest {
@@ -67,12 +64,12 @@ function Create-PullRequest {
$createdPullRequest = $GitHubApi.CreateNewPullRequest($Title, $Body, $BranchName) $createdPullRequest = $GitHubApi.CreateNewPullRequest($Title, $Body, $BranchName)
if (($createdPullRequest -eq $null) -or ($createdPullRequest.html_url -eq $null)) { if (($null -eq $createdPullRequest) -or ($null -eq $createdPullRequest.html_url)) {
Write-Host "##vso[task.logissue type=error;] Unexpected error occurs while creating pull request." Write-Host "Unexpected error occurs while creating pull request."
exit 1 exit 1
} }
Write-host "##[section] Pull request created: $($createdPullRequest.html_url)" Write-host "Pull request created: $($createdPullRequest.html_url)"
} }
Write-Host "Configure local git preferences" Write-Host "Configure local git preferences"
@@ -87,8 +84,8 @@ Git-CommitAllChanges -Message $CommitMessage
Write-Host "Push branch: $BranchName" Write-Host "Push branch: $BranchName"
Git-PushBranch -Name $BranchName -Force $true Git-PushBranch -Name $BranchName -Force $true
$gitHubApi = Get-GitHubApi -AccountName $RepositoryOwner -ProjectName $RepositoryName -AccessToken $AccessToken $gitHubApi = Get-GitHubApi -RepositoryFullName $RepositoryFullName -AccessToken $AccessToken
$pullRequest = $gitHubApi.GetPullRequest($BranchName, $RepositoryOwner) $pullRequest = $gitHubApi.GetPullRequest($BranchName)
if ($pullRequest.Count -gt 0) { if ($pullRequest.Count -gt 0) {
Write-Host "Update pull request" Write-Host "Update pull request"

86
github/create-release.ps1 Normal file
View File

@@ -0,0 +1,86 @@
<#
.SYNOPSIS
Trigger runs on the workflow_dispatch event to create tool release
.PARAMETER RepositoryFullName
Required parameter. The owner and repository name. For example, 'actions/versions-package-tools'
.PARAMETER AccessToken
Required parameter. PAT Token to authorize
.PARAMETER ToolVersion
Required parameter. Version of tool
.PARAMETER TagName
Required parameter. The name of the release tag
.PARAMETER ReleaseBody
Required parameter. Text describing the contents of the release
.PARAMETER EventType
Required parameter. The name of the repository dispatch event
#>
param (
[Parameter(Mandatory)] [string] $RepositoryFullName,
[Parameter(Mandatory)] [string] $AccessToken,
[Parameter(Mandatory)] [string] $ToolVersion,
[Parameter(Mandatory)] [string] $TagName,
[Parameter(Mandatory)] [string] $ReleaseBody,
[Parameter(Mandatory)] [string] $EventType,
[UInt32] $RetryIntervalSec = 10,
[UInt32] $RetryCount = 5
)
Import-Module (Join-Path $PSScriptRoot "github-api.psm1")
function Create-Release {
param (
[Parameter(Mandatory)] [object] $GitHubApi,
[Parameter(Mandatory)] [string] $ToolVersion,
[Parameter(Mandatory)] [string] $TagName,
[Parameter(Mandatory)] [string] $ReleaseBody,
[Parameter(Mandatory)] [string] $EventType
)
$eventPayload = @{
ToolVersion = $ToolVersion
TagName = $TagName
ReleaseBody = $ReleaseBody
}
Write-Host "Create '$EventType' repository dispatch event"
$GitHubApi.CreateRepositoryDispatch($EventType, $eventPayload)
}
function Validate-ReleaseAvailability {
param (
[Parameter(Mandatory)] [object] $GitHubApi,
[Parameter(Mandatory)] [string] $TagName,
[Parameter(Mandatory)] [UInt32] $RetryIntervalSec,
[Parameter(Mandatory)] [UInt32] $RetryCount
)
do {
$createdRelease = $GitHubApi.GetReleases() | Where-Object { $_.tag_name -eq $TagName }
if ($createdRelease) {
Write-Host "Release was successfully created: $($createdRelease.html_url)"
return
}
$RetryCount--
Start-Sleep -Seconds $RetryIntervalSec
} while($RetryCount -gt 0)
Write-Host "Release was not created"
exit 1
}
$gitHubApi = Get-GitHubApi -RepositoryFullName $RepositoryFullName -AccessToken $AccessToken
Create-Release -GitHubApi $gitHubApi `
-ToolVersion $ToolVersion `
-TagName $TagName `
-ReleaseBody $ReleaseBody `
-EventType $EventType
Start-Sleep -s $RetryIntervalSec
Validate-ReleaseAvailability -GitHubApi $gitHubApi `
-TagName $TagName `
-RetryIntervalSec $RetryIntervalSec `
-RetryCount $RetryCount

View File

@@ -5,8 +5,8 @@ The module that contains a bunch of methods to interact with GitHub API V3
class GitHubApi class GitHubApi
{ {
[string] $BaseUrl [string] $BaseUrl
[string] $RepoOwner
[object] $AuthHeader [object] $AuthHeader
[string] $RepositoryOwner
GitHubApi( GitHubApi(
[string] $AccountName, [string] $AccountName,
@@ -15,6 +15,7 @@ class GitHubApi
) { ) {
$this.BaseUrl = $this.BuildBaseUrl($AccountName, $ProjectName) $this.BaseUrl = $this.BuildBaseUrl($AccountName, $ProjectName)
$this.AuthHeader = $this.BuildAuth($AccessToken) $this.AuthHeader = $this.BuildAuth($AccessToken)
$this.RepositoryOwner = $AccountName
} }
[object] hidden BuildAuth([string]$AccessToken) { [object] hidden BuildAuth([string]$AccessToken) {
@@ -43,9 +44,9 @@ class GitHubApi
return $this.InvokeRestMethod($url, 'Post', $null, $requestBody) return $this.InvokeRestMethod($url, 'Post', $null, $requestBody)
} }
[object] GetPullRequest([string]$BranchName, [string]$RepositoryOwner){ [object] GetPullRequest([string]$BranchName){
$url = "pulls" $url = "pulls"
return $this.InvokeRestMethod($url, 'GET', "head=${RepositoryOwner}:$BranchName&base=main", $null) return $this.InvokeRestMethod($url, 'GET', "head=$($this.RepositoryOwner):${BranchName}&base=main", $null)
} }
[object] UpdatePullRequest([string]$Title, [string]$Body, [string]$BranchName, [string]$PullRequestNumber){ [object] UpdatePullRequest([string]$Title, [string]$Body, [string]$BranchName, [string]$PullRequestNumber){
@@ -82,6 +83,39 @@ class GitHubApi
return $releases return $releases
} }
[void] CreateRepositoryDispatch([string]$EventType, [object]$EventPayload) {
$url = "dispatches"
$body = @{
event_type = $EventType
client_payload = $EventPayload
} | ConvertTo-Json
$this.InvokeRestMethod($url, 'POST', $null, $body)
}
[object] GetWorkflowRuns([string]$WorkflowFileName) {
$url = "actions/workflows/$WorkflowFileName/runs"
return $this.InvokeRestMethod($url, 'GET', $null, $null)
}
[object] GetWorkflowRunJobs([string]$WorkflowRunId) {
$url = "actions/runs/$WorkflowRunId/jobs"
return $this.InvokeRestMethod($url, 'GET', $null, $null)
}
[void] CreateWorkflowDispatch([string]$WorkflowFileName, [string]$Ref, [object]$Inputs) {
$url = "actions/workflows/${WorkflowFileName}/dispatches"
$body = @{ ref = $Ref }
if ($Inputs) {
$body.inputs = $Inputs
}
$jsonBody = $body | ConvertTo-Json
$this.InvokeRestMethod($url, 'POST', $null, $jsonBody)
}
[string] hidden BuildUrl([string]$Url, [string]$RequestParams) { [string] hidden BuildUrl([string]$Url, [string]$RequestParams) {
if ([string]::IsNullOrEmpty($RequestParams)) { if ([string]::IsNullOrEmpty($RequestParams)) {
return "$($this.BaseUrl)/$($Url)" return "$($this.BaseUrl)/$($Url)"
@@ -117,10 +151,18 @@ class GitHubApi
function Get-GitHubApi { function Get-GitHubApi {
param ( param (
[string] $AccountName, [Parameter(ParameterSetName = 'RepositorySingle')]
[string] $ProjectName, [string] $RepositoryFullName,
[Parameter(ParameterSetName = 'RepositorySplitted')]
[string] $RepositoryOwner,
[Parameter(ParameterSetName = 'RepositorySplitted')]
[string] $RepositoryName,
[string] $AccessToken [string] $AccessToken
) )
return [GitHubApi]::New($AccountName, $ProjectName, $AccessToken) if ($PSCmdlet.ParameterSetName -eq "RepositorySingle") {
$RepositoryOwner, $RepositoryName = $RepositoryFullName.Split('/', 2)
}
return [GitHubApi]::New($RepositoryOwner, $RepositoryName, $AccessToken)
} }

91
github/run-ci-builds.ps1 Normal file
View File

@@ -0,0 +1,91 @@
<#
.SYNOPSIS
Trigger runs on the workflow_dispatch event to build and upload tool packages
.PARAMETER RepositoryFullName
Required parameter. The owner and repository name. For example, 'actions/versions-package-tools'
.PARAMETER AccessToken
Required parameter. PAT to authorize
.PARAMETER WorkflowFileName
Required parameter. The name of workflow file that will be triggered
.PARAMETER WorkflowDispatchRef
Required parameter. The reference of the workflow run. The reference can be a branch, tag, or a commit SHA.
.PARAMETER ToolVersions
Required parameter. List of tool versions to build and upload
.PARAMETER PublishReleases
Required parameter. Whether to publish releases, true or false
#>
param (
[Parameter(Mandatory)] [string] $RepositoryFullName,
[Parameter(Mandatory)] [string] $AccessToken,
[Parameter(Mandatory)] [string] $WorkflowFileName,
[Parameter(Mandatory)] [string] $WorkflowDispatchRef,
[Parameter(Mandatory)] [string] $ToolVersions,
[Parameter(Mandatory)] [string] $PublishReleases
)
Import-Module (Join-Path $PSScriptRoot "github-api.psm1")
function Get-WorkflowRunLink {
param(
[Parameter(Mandatory)] [object] $GitHubApi,
[Parameter(Mandatory)] [string] $WorkflowFileName,
[Parameter(Mandatory)] [string] $ToolVersion
)
$listWorkflowRuns = $GitHubApi.GetWorkflowRuns($WorkflowFileName).workflow_runs | Sort-Object -Property 'run_number' -Descending
foreach ($workflowRun in $listWorkflowRuns) {
$workflowRunJob = $gitHubApi.GetWorkflowRunJobs($workflowRun.id).jobs | Select-Object -First 1
if ($workflowRunJob.name -match $ToolVersion) {
return $workflowRun.html_url
}
}
return $null
}
function Queue-Builds {
param (
[Parameter(Mandatory)] [object] $GitHubApi,
[Parameter(Mandatory)] [string] $ToolVersions,
[Parameter(Mandatory)] [string] $WorkflowFileName,
[Parameter(Mandatory)] [string] $WorkflowDispatchRef,
[Parameter(Mandatory)] [string] $PublishReleases
)
$inputs = @{
PUBLISH_RELEASES = $PublishReleases
}
$ToolVersions.Split(',') | ForEach-Object {
$version = $_.Trim()
$inputs.VERSION = $version
Write-Host "Queue build for $version..."
$GitHubApi.CreateWorkflowDispatch($WorkflowFileName, $WorkflowDispatchRef, $inputs)
Start-Sleep -s 10
$workflowRunLink = Get-WorkflowRunLink -GitHubApi $GitHubApi `
-WorkflowFileName $WorkflowFileName `
-ToolVersion $version
if (-not $workflowRunLink) {
Write-Host "Could not find build for $version..."
exit 1
}
Write-Host "Link to the build: $workflowRunLink"
}
}
$gitHubApi = Get-GitHubApi -RepositoryFullName $RepositoryFullName -AccessToken $AccessToken
Write-Host "Versions to build: $ToolVersions"
Queue-Builds -GitHubApi $gitHubApi `
-ToolVersions $ToolVersions `
-WorkflowFileName $WorkflowFileName `
-WorkflowDispatchRef $WorkflowDispatchRef `
-PublishReleases $PublishReleases

View File

@@ -1,13 +1,10 @@
<# <#
.SYNOPSIS .SYNOPSIS
Generate versions manifest based on repository releases Generate versions manifest based on repository releases
.DESCRIPTION .DESCRIPTION
Versions manifest is needed to find the latest assets for particular version of tool Versions manifest is needed to find the latest assets for particular version of tool
.PARAMETER GitHubRepositoryOwner .PARAMETER RepositoryFullName
Required parameter. The organization which tool repository belongs Required parameter. The owner and repository name. For example, 'actions/versions-package-tools'
.PARAMETER GitHubRepositoryName
Required parameter. The name of tool repository
.PARAMETER GitHubAccessToken .PARAMETER GitHubAccessToken
Required parameter. PAT Token to overcome GitHub API Rate limit Required parameter. PAT Token to overcome GitHub API Rate limit
.PARAMETER OutputFile .PARAMETER OutputFile
@@ -17,8 +14,7 @@ Path to the json file with parsing configuration
#> #>
param ( param (
[Parameter(Mandatory)] [string] $GitHubRepositoryOwner, [Parameter(Mandatory)] [string] $RepositoryFullName,
[Parameter(Mandatory)] [string] $GitHubRepositoryName,
[Parameter(Mandatory)] [string] $GitHubAccessToken, [Parameter(Mandatory)] [string] $GitHubAccessToken,
[Parameter(Mandatory)] [string] $OutputFile, [Parameter(Mandatory)] [string] $OutputFile,
[Parameter(Mandatory)] [string] $ConfigurationFile [Parameter(Mandatory)] [string] $ConfigurationFile
@@ -29,7 +25,7 @@ Import-Module (Join-Path $PSScriptRoot "manifest-utils.psm1") -Force
$configuration = Read-ConfigurationFile -Filepath $ConfigurationFile $configuration = Read-ConfigurationFile -Filepath $ConfigurationFile
$gitHubApi = Get-GitHubApi -AccountName $GitHubRepositoryOwner -ProjectName $GitHubRepositoryName -AccessToken $GitHubAccessToken $gitHubApi = Get-GitHubApi -RepositoryFullName $RepositoryFullName -AccessToken $GitHubAccessToken
$releases = $gitHubApi.GetReleases() $releases = $gitHubApi.GetReleases()
$versionIndex = Build-VersionsManifest -Releases $releases -Configuration $configuration $versionIndex = Build-VersionsManifest -Releases $releases -Configuration $configuration
$versionIndex | ConvertTo-Json -Depth 5 | Out-File $OutputFile -Encoding UTF8NoBOM -Force $versionIndex | ConvertTo-Json -Depth 5 | Out-File $OutputFile -Encoding UTF8NoBOM -Force

View File

@@ -126,7 +126,7 @@ Describe "Build-VersionsManifest" {
[PSCustomObject]@{ version = "3.8.3"; stable = $true; release_url = "fake_html_url"; files = $expectedManifestFiles } [PSCustomObject]@{ version = "3.8.3"; stable = $true; release_url = "fake_html_url"; files = $expectedManifestFiles }
) )
[array]$actualManifest = Build-VersionsManifest -Releases $releases -Configuration $configuration [array]$actualManifest = Build-VersionsManifest -Releases $releases -Configuration $configuration
Assert-Equivalent -Actual $actualManifest -Expected $expectedManifest Assert-Equivalent -Actual $actualManifest -Expected $expectedManifest
} }
It "take latest published release for each version" { It "take latest published release for each version" {
@@ -141,4 +141,74 @@ Describe "Build-VersionsManifest" {
[array]$actualManifest = Build-VersionsManifest -Releases $releases -Configuration $configuration [array]$actualManifest = Build-VersionsManifest -Releases $releases -Configuration $configuration
Assert-Equivalent -Actual $actualManifest -Expected $expectedManifest Assert-Equivalent -Actual $actualManifest -Expected $expectedManifest
} }
It "build correct manifest if release includes one asset" {
$asset = @(
@{ name = "python-3.8.3-linux-16.04-x64.tar.gz"; browser_download_url = "fake_url"; }
)
$expectedManifestFile = @(
[PSCustomObject]@{ filename = "python-3.8.3-linux-16.04-x64.tar.gz"; arch = "x64"; platform = "linux"; platform_version = "16.04"; download_url = "fake_url" }
)
$releases = @(
@{ name = "3.8.3"; draft = $false; prerelease = $false; html_url = "fake_html_url"; published_at = "2020-05-06T11:43:38Z"; assets = $asset },
@{ name = "3.8.1"; draft = $false; prerelease = $false; html_url = "fake_html_url"; published_at = "2020-05-14T09:54:06Z"; assets = $assets }
)
$expectedManifest = @(
[PSCustomObject]@{ version = "3.8.3"; stable = $true; release_url = "fake_html_url"; files = $expectedManifestFile },
[PSCustomObject]@{ version = "3.8.1"; stable = $true; release_url = "fake_html_url"; files = $expectedManifestFiles }
)
[array]$actualManifest = Build-VersionsManifest -Releases $releases -Configuration $configuration
Assert-Equivalent -Actual $actualManifest -Expected $expectedManifest
}
It "set correct lts value for versions" {
$releases = @(
@{ name = "14.2.1"; draft = false; prerelease = $false; html_url = "fake_html_url"; published_at = "2020-05-14T09:54:06Z"; assets = $assets },
@{ name = "12.0.1"; draft = $false; prerelease = false; html_url = "fake_html_url"; published_at = "2020-05-06T11:45:36Z"; assets = $assets },
@{ name = "16.2.2"; draft = $false; prerelease = $false; html_url = "fake_html_url"; published_at = "2020-05-06T11:43:38Z"; assets = $assets }
)
$configuration = @{
regex = "python-\d+\.\d+\.\d+-(\w+)-([\w\.]+)?-?(x\d+)";
groups = [PSCustomObject]@{ platform = 1; platform_version = 2; arch = "x64"; }
lts_rule_expression = "@(@{ Name = '14'; Value = 'Fermium' }, @{ Name = '12'; Value = 'Erbium' })"
}
$expectedManifest = @(
[PSCustomObject]@{ version = "16.2.2"; stable = $true; release_url = "fake_html_url"; files = $expectedManifestFiles },
[PSCustomObject]@{ version = "14.2.1"; stable = $true; lts = "Fermium"; release_url = "fake_html_url"; files = $expectedManifestFiles },
[PSCustomObject]@{ version = "12.0.1"; stable = $true; lts = "Erbium"; release_url = "fake_html_url"; files = $expectedManifestFiles }
)
[array]$actualManifest = Build-VersionsManifest -Releases $releases -Configuration $configuration
Assert-Equivalent -Actual $actualManifest -Expected $expectedManifest
}
}
Describe "Get-VersionLtsStatus" {
$ltsRules = @(
@{ Name = "14"; Value = "Fermium" },
@{ Name = "12"; Value = "Erbium" },
@{ Name = "10"; Value = $true },
@{ Name = "8.3"; Value = "LTS 8.3" }
)
It "lts label is matched" {
Get-VersionLtsStatus -Version "14.2.2" -LtsRules $ltsRules | Should -Be "Fermium"
Get-VersionLtsStatus -Version "12.3.1" -LtsRules $ltsRules | Should -Be "Erbium"
Get-VersionLtsStatus -Version "10.8.1" -LtsRules $ltsRules | Should -Be $true
Get-VersionLtsStatus -Version "8.3.2" -LtsRules $ltsRules | Should -Be "LTS 8.3"
Get-VersionLtsStatus -Version "14" -LtsRules $ltsRules | Should -Be "Fermium"
}
It "lts label is not matched" {
Get-VersionLtsStatus -Version "9.1" -LtsRules $ltsRules | Should -Be $null
Get-VersionLtsStatus -Version "13.8" -LtsRules $ltsRules | Should -Be $null
Get-VersionLtsStatus -Version "5" -LtsRules $ltsRules | Should -Be $null
Get-VersionLtsStatus -Version "8.4" -LtsRules $ltsRules | Should -Be $null
Get-VersionLtsStatus -Version "142.5.1" -LtsRules $ltsRules | Should -Be $null
}
It "no rules" {
Get-VersionLtsStatus -Version "14.2.2" | Should -Be $null
Get-VersionLtsStatus -Version "12.3.1" -LtsRules $null | Should -Be $null
}
} }

View File

@@ -50,6 +50,7 @@ function Build-VersionsManifest {
) )
$Releases = $Releases | Sort-Object -Property "published_at" -Descending $Releases = $Releases | Sort-Object -Property "published_at" -Descending
$ltsRules = Get-LtsRules -Configuration $Configuration
$versionsHash = @{} $versionsHash = @{}
foreach ($release in $Releases) { foreach ($release in $Releases) {
@@ -64,15 +65,49 @@ function Build-VersionsManifest {
continue continue
} }
$ltsStatus = Get-VersionLtsStatus -Version $versionKey -LtsRules $ltsRules
$stable = $version.PreReleaseLabel ? $false : $true $stable = $version.PreReleaseLabel ? $false : $true
$versionsHash.Add($versionKey, [PSCustomObject]@{ [array]$releaseAssets = $release.assets | ForEach-Object { New-AssetItem -ReleaseAsset $_ -Configuration $Configuration }
version = $versionKey
stable = $stable $versionHash = [PSCustomObject]@{}
release_url = $release.html_url $versionHash | Add-Member -Name "version" -Value $versionKey -MemberType NoteProperty
files = $release.assets | ForEach-Object { New-AssetItem -ReleaseAsset $_ -Configuration $Configuration } $versionHash | Add-Member -Name "stable" -Value $stable -MemberType NoteProperty
}) if ($ltsStatus) {
$versionHash | Add-Member -Name "lts" -Value $ltsStatus -MemberType NoteProperty
}
$versionHash | Add-Member -Name "release_url" -Value $release.html_url -MemberType NoteProperty
$versionHash | Add-Member -Name "files" -Value $releaseAssets -MemberType NoteProperty
$versionsHash.Add($versionKey, $versionHash)
} }
# Sort versions by descending # Sort versions by descending
return $versionsHash.Values | Sort-Object -Property @{ Expression = { [Semver]$_.version }; Descending = $true } return $versionsHash.Values | Sort-Object -Property @{ Expression = { [Semver]$_.version }; Descending = $true }
} }
function Get-LtsRules {
param (
[Parameter(Mandatory)][object]$Configuration
)
$ruleExpression = $Configuration."lts_rule_expression"
if ($ruleExpression) {
Invoke-Expression $ruleExpression
} else {
@()
}
}
function Get-VersionLtsStatus {
param (
[Parameter(Mandatory)][string]$Version,
[array]$LtsRules
)
foreach ($ltsRule in $LtsRules) {
if (($Version -eq $ltsRule.Name) -or ($Version.StartsWith("$($ltsRule.Name)."))) {
return $ltsRule.Value
}
}
return $null
}

View File

@@ -4,30 +4,52 @@ Pester extension that allows to run command and validate exit code
.EXAMPLE .EXAMPLE
"python file.py" | Should -ReturnZeroExitCode "python file.py" | Should -ReturnZeroExitCode
#> #>
function Get-CommandResult {
Param (
[Parameter(Mandatory=$true)]
[string] $Command,
[switch] $Multiline
)
# CMD and bash trick to suppress and show error output because some commands write to stderr (for example, "python --version")
If ($IsWindows) {
$stdout = & $env:comspec /c "$Command 2>&1"
} else {
$stdout = & bash -c "$Command 2>&1"
}
$exitCode = $LASTEXITCODE
return @{
Output = If ($Multiline -eq $true) { $stdout } else { [string]$stdout }
ExitCode = $exitCode
}
}
function ShouldReturnZeroExitCode { function ShouldReturnZeroExitCode {
Param( Param(
[Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $ActualValue,
[String]$ActualValue, [switch] $Negate,
[switch]$Negate [string] $Because # This parameter is unused by we need it to match Pester asserts signature
) )
Write-Host "Run command '${ActualValue}'" $result = Get-CommandResult $ActualValue
Invoke-Expression -Command $ActualValue | ForEach-Object { Write-Host $_ }
$actualExitCode = $LASTEXITCODE
[bool]$succeeded = $actualExitCode -eq 0 [bool]$succeeded = $result.ExitCode -eq 0
if ($Negate) { $succeeded = -not $succeeded } if ($Negate) { $succeeded = -not $succeeded }
if (-not $succeeded) if (-not $succeeded)
{ {
$failureMessage = "Command '${ActualValue}' has finished with exit code ${actualExitCode}" $commandOutputIndent = " " * 4
$commandOutput = ($result.Output | ForEach-Object { "${commandOutputIndent}${_}" }) -join "`n"
$failureMessage = "Command '${ActualValue}' has finished with exit code ${actualExitCode}`n${commandOutput}"
} }
return New-Object PSObject -Property @{ return [PSCustomObject] @{
Succeeded = $succeeded Succeeded = $succeeded
FailureMessage = $failureMessage FailureMessage = $failureMessage
} }
} }
Add-AssertionOperator -Name ReturnZeroExitCode ` if (Get-Command -Name Add-AssertionOperator -ErrorAction SilentlyContinue) {
-Test $function:ShouldReturnZeroExitCode Add-AssertionOperator -Name ReturnZeroExitCode -InternalName ShouldReturnZeroExitCode -Test ${function:ShouldReturnZeroExitCode}
}