diff --git a/.github/actions/send-slack-notification/action.yml b/.github/actions/send-slack-notification/action.yml new file mode 100644 index 0000000..42062d3 --- /dev/null +++ b/.github/actions/send-slack-notification/action.yml @@ -0,0 +1,39 @@ +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 }} diff --git a/.github/workflows/get-tools-new-versions.yml b/.github/workflows/get-tools-new-versions.yml new file mode 100644 index 0000000..aeaaf74 --- /dev/null +++ b/.github/workflows/get-tools-new-versions.yml @@ -0,0 +1,89 @@ +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 }}" \ No newline at end of file diff --git a/azure-pipelines/get-tool-versions-xamarin.yml b/azure-pipelines/get-tool-versions-xamarin.yml deleted file mode 100644 index 866f810..0000000 --- a/azure-pipelines/get-tool-versions-xamarin.yml +++ /dev/null @@ -1,37 +0,0 @@ -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 diff --git a/azure-pipelines/templates/check-versions.yml b/azure-pipelines/templates/check-versions.yml index 9af96ef..084c913 100644 --- a/azure-pipelines/templates/check-versions.yml +++ b/azure-pipelines/templates/check-versions.yml @@ -21,7 +21,7 @@ steps: TargetType: inline script: | $ToolName = "$(TOOL_NAME)" - if ($ToolName -in @("Python", "Xamarin")) { + if ($ToolName -eq "Python") { $PipelineUrl = " " } else { $PipelineUrl = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)" diff --git a/get-new-tool-versions/get-new-tool-versions.ps1 b/get-new-tool-versions/get-new-tool-versions.ps1 index 75e0353..e8342ed 100644 --- a/get-new-tool-versions/get-new-tool-versions.ps1 +++ b/get-new-tool-versions/get-new-tool-versions.ps1 @@ -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, Xamarin) +Required parameter. The name of tool for which parser is available (Node, Go, Python) #> param ( @@ -16,19 +16,12 @@ $ToolVersionParser = Get-ToolVersionsParser -ToolName $ToolName $VersionsFromDist = $ToolVersionParser.GetAvailableVersions() $VersionsFromManifest = $ToolVersionParser.GetUploadedVersions() -$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 $_ } -} +$VersionsToBuild = $VersionsFromDist | Where-Object { $VersionsFromManifest -notcontains $_ } if ($VersionsToBuild) { - $availableVersions = $VersionsToBuild -join $joinChars + $availableVersions = $VersionsToBuild -join ", " 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}" } else { Write-Host "There aren't versions to build" diff --git a/get-new-tool-versions/parsers/go-parser.psm1 b/get-new-tool-versions/parsers/go-parser.psm1 index 19f3a21..5b9abb0 100644 --- a/get-new-tool-versions/parsers/go-parser.psm1 +++ b/get-new-tool-versions/parsers/go-parser.psm1 @@ -15,7 +15,7 @@ class GoVersionsParser: BaseVersionsParser { hidden [SemVer] FormatVersion([string]$VersionSpec) { $cleanVersion = $VersionSpec -replace "^go", "" - $semanticVersion = $cleanVersion -replace "(\d+\.\d+\.?\d+?)((?:alpha|beta|rc))(\d*)",'$1-$2.$3' + $semanticVersion = $cleanVersion -replace '(\d+\.\d+\.?\d*?)((?:alpha|beta|rc))(\d*)', '$1-$2.$3' return [SemVer]$semanticVersion } diff --git a/get-new-tool-versions/parsers/parsers-factory.psm1 b/get-new-tool-versions/parsers/parsers-factory.psm1 index 199136c..eb9b69c 100644 --- a/get-new-tool-versions/parsers/parsers-factory.psm1 +++ b/get-new-tool-versions/parsers/parsers-factory.psm1 @@ -1,7 +1,6 @@ using module "./node-parser.psm1" using module "./go-parser.psm1" using module "./python-parser.psm1" -using module "./xamarin-parser.psm1" function Get-ToolVersionsParser { param( @@ -13,7 +12,6 @@ function Get-ToolVersionsParser { "Node" { return [NodeVersionsParser]::New() } "Go" { return [GoVersionsParser]::New() } "Python" { return [PythonVersionsParser]::New() } - "Xamarin" { return [XamarinversionsParser]::New() } Default { throw "Unknown tool name" } diff --git a/get-new-tool-versions/parsers/verify-added-to-image/verify-common-tool-parser.psm1 b/get-new-tool-versions/parsers/verify-added-to-image/verify-common-tool-parser.psm1 new file mode 100644 index 0000000..3723390 --- /dev/null +++ b/get-new-tool-versions/parsers/verify-added-to-image/verify-common-tool-parser.psm1 @@ -0,0 +1,25 @@ +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 +} \ No newline at end of file diff --git a/get-new-tool-versions/parsers/verify-added-to-image/verify-xamarin-parser.psm1 b/get-new-tool-versions/parsers/verify-added-to-image/verify-xamarin-parser.psm1 new file mode 100644 index 0000000..4999217 --- /dev/null +++ b/get-new-tool-versions/parsers/verify-added-to-image/verify-xamarin-parser.psm1 @@ -0,0 +1,19 @@ +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 +} \ No newline at end of file diff --git a/get-new-tool-versions/parsers/xamarin-parser.psm1 b/get-new-tool-versions/parsers/xamarin-parser.psm1 deleted file mode 100644 index 7d69416..0000000 --- a/get-new-tool-versions/parsers/xamarin-parser.psm1 +++ /dev/null @@ -1,30 +0,0 @@ -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.0.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 - } -} \ No newline at end of file diff --git a/get-new-tool-versions/send-slack-notification.ps1 b/get-new-tool-versions/send-slack-notification.ps1 index 3f3518a..c609a4b 100644 --- a/get-new-tool-versions/send-slack-notification.ps1 +++ b/get-new-tool-versions/send-slack-notification.ps1 @@ -7,11 +7,15 @@ 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 +Optional parameter. Specifies the version of tool .PARAMETER PipelineUrl -Required parameter. The pipeline URL +Optional 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( @@ -23,26 +27,28 @@ param( [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' + [System.String]$ImageUrl = 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png', + [System.String]$Text, + [Switch]$AddToToolsetFlag ) # Import helpers module Import-Module $PSScriptRoot/helpers.psm1 -DisableNameChecking # Create JSON body -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 ([string]::IsNullOrWhiteSpace($Text)) { + if ($AddToToolsetFlag) { + $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" + $Text += "\nLink to the pipeline: $pipelineUrl" } + $jsonBodyMessage = @" { "blocks": [ @@ -50,7 +56,7 @@ $jsonBodyMessage = @" "type": "section", "text": { "type": "mrkdwn", - "text": "$text" + "text": "$Text" }, "accessory": { "type": "image", diff --git a/get-new-tool-versions/verify-new-tool-version-added-to-image.ps1 b/get-new-tool-versions/verify-new-tool-version-added-to-image.ps1 new file mode 100644 index 0000000..664729d --- /dev/null +++ b/get-new-tool-versions/verify-new-tool-version-added-to-image.ps1 @@ -0,0 +1,38 @@ +<# +.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 diff --git a/github/github-api.psm1 b/github/github-api.psm1 index 3103ed0..6ba32c7 100644 --- a/github/github-api.psm1 +++ b/github/github-api.psm1 @@ -124,6 +124,11 @@ class GitHubApi } } + [void] CancelWorkflow([string]$WorkflowId) { + $url = "actions/runs/$WorkflowId/cancel" + $this.InvokeRestMethod($url, 'POST', $null, $null) + } + [object] hidden InvokeRestMethod( [string] $Url, [string] $Method, diff --git a/packages-generation/manifest-utils.Tests.ps1 b/packages-generation/manifest-utils.Tests.ps1 index 0fcaf05..15765d1 100644 --- a/packages-generation/manifest-utils.Tests.ps1 +++ b/packages-generation/manifest-utils.Tests.ps1 @@ -126,7 +126,7 @@ Describe "Build-VersionsManifest" { [PSCustomObject]@{ version = "3.8.3"; stable = $true; release_url = "fake_html_url"; files = $expectedManifestFiles } ) [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" { @@ -161,4 +161,54 @@ Describe "Build-VersionsManifest" { [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 + } } \ No newline at end of file diff --git a/packages-generation/manifest-utils.psm1 b/packages-generation/manifest-utils.psm1 index df2a8b2..b0da90b 100644 --- a/packages-generation/manifest-utils.psm1 +++ b/packages-generation/manifest-utils.psm1 @@ -50,6 +50,7 @@ function Build-VersionsManifest { ) $Releases = $Releases | Sort-Object -Property "published_at" -Descending + $ltsRules = Get-LtsRules -Configuration $Configuration $versionsHash = @{} foreach ($release in $Releases) { @@ -64,17 +65,49 @@ function Build-VersionsManifest { continue } + $ltsStatus = Get-VersionLtsStatus -Version $versionKey -LtsRules $ltsRules $stable = $version.PreReleaseLabel ? $false : $true [array]$releaseAssets = $release.assets | ForEach-Object { New-AssetItem -ReleaseAsset $_ -Configuration $Configuration } - $versionsHash.Add($versionKey, [PSCustomObject]@{ - version = $versionKey - stable = $stable - release_url = $release.html_url - files = $releaseAssets - }) + $versionHash = [PSCustomObject]@{} + $versionHash | Add-Member -Name "version" -Value $versionKey -MemberType NoteProperty + $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 return $versionsHash.Values | Sort-Object -Property @{ Expression = { [Semver]$_.version }; Descending = $true } -} \ No newline at end of file +} + +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 +} diff --git a/packages-generation/manifest-validator.ps1 b/packages-generation/manifest-validator.ps1 index 7266e11..c50bceb 100644 --- a/packages-generation/manifest-validator.ps1 +++ b/packages-generation/manifest-validator.ps1 @@ -1,30 +1,29 @@ param ( - [Parameter(Mandatory)][string] $ManifestUrl, - [string] $AccessToken + [Parameter(Mandatory)][string] $ManifestPath ) -$authorizationHeaderValue = "Basic $AccessToken" -$webRequestHeaders = @{} -if ($AccessToken) { - $webRequestHeaders.Add("Authorization", $authorizationHeaderValue) -} +$Global:validationFailed = $false function Publish-Error { param( [string] $ErrorDescription, [object] $Exception ) - Write-Host "##vso[task.logissue type=error]ERROR: $ErrorDescription." - Write-Host "##vso[task.logissue type=error] $Exception" - Write-Host "##vso[task.complete result=Failed;]" + + Write-Output "::error ::$ErrorDescription" + if (-not [string]::IsNullOrEmpty($Exception)) + { + Write-Output "Exception: $Exception" + } + $Global:validationFailed = $true } 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) @@ -33,19 +32,16 @@ function Test-DownloadUrl { } } -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'" $_ +if (-not (Test-Path $ManifestPath)) { + Publish-Error "Unable to find manifest json file at '$ManifestPath'" exit 1 } -Write-Host "Parsing manifest json content from '$ManifestUrl'..." +Write-Host "Parsing manifest json content from '$ManifestPath'..." try { - $manifestJson = $manifestResponse.Content | ConvertFrom-Json + $manifestJson = Get-Content $ManifestPath | ConvertFrom-Json } catch { - Publish-Error "Unable to parse manifest json content '$ManifestUrl'" $_ + Publish-Error "Unable to parse manifest json content '$ManifestPath'" $_ exit 1 } @@ -61,3 +57,7 @@ $manifestJson | ForEach-Object { } } } + +if ($Global:validationFailed) { + exit 1 +}