mirror of
https://github.com/actions/versions-package-tools.git
synced 2025-12-24 10:38:08 +08:00
Merge pull request #13 from actions/v-mazhuk/migrate-tools-ci-to-github-actions
Migrate tools CI to GitHub Actions
This commit is contained in:
@@ -1,29 +1,15 @@
|
||||
steps:
|
||||
- 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
|
||||
displayName: 'Run builds'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: './azure-devops/run-ci-builds.ps1'
|
||||
filePath: './github/run-ci-builds.ps1'
|
||||
arguments: |
|
||||
-TeamFoundationCollectionUri $(System.TeamFoundationCollectionUri) `
|
||||
-AzureDevOpsProjectName $(System.TeamProject) `
|
||||
-AzureDevOpsAccessToken $(System.AccessToken) `
|
||||
-SourceBranch $(BRANCH) `
|
||||
-DefinitionId $(DEFINITION_ID) `
|
||||
-SourceVersion $(COMMIT_SHA) `
|
||||
-ManifestLink $(MANIFEST_URL) `
|
||||
-WaitForBuilds $(WAIT_FOR_BUILDS) `
|
||||
-RepositoryFullName $(REPOSITORY_FULL_NAME) `
|
||||
-AccessToken $(GITHUB_TOKEN) `
|
||||
-WorkflowFileName $(WORKFLOW_FILE_NAME) `
|
||||
-WorkflowDispatchRef $(DISPATCH_REF) `
|
||||
-ToolVersions "$(ToolVersions)" `
|
||||
-RetryIntervalSec $(INTERVAL_SEC) `
|
||||
-RetryCount $(RETRY_COUNT)
|
||||
-PublishReleases $(PUPLISH_RELEASES)
|
||||
@@ -3,6 +3,11 @@ param (
|
||||
)
|
||||
|
||||
$targetPath = $env:AGENT_TOOLSDIRECTORY
|
||||
if ([string]::IsNullOrEmpty($targetPath)) {
|
||||
# GitHub Windows images don't have `AGENT_TOOLSDIRECTORY` variable
|
||||
$targetPath = $env:RUNNER_TOOL_CACHE
|
||||
}
|
||||
|
||||
if ($ToolName) {
|
||||
$targetPath = Join-Path $targetPath $ToolName
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
.SYNOPSIS
|
||||
Create commit with all unstaged changes in repository and create pull-request
|
||||
|
||||
.PARAMETER RepositoryOwner
|
||||
Required parameter. The organization which tool repository belongs
|
||||
.PARAMETER RepositoryName
|
||||
Optional parameter. The name of tool repository
|
||||
.PARAMETER RepositoryFullName
|
||||
Required parameter. The owner and repository name. For example, 'actions/versions-package-tools'
|
||||
.PARAMETER AccessToken
|
||||
Required parameter. PAT Token to authorize
|
||||
.PARAMETER BranchName
|
||||
@@ -18,8 +16,7 @@ Required parameter. The title of pull-request
|
||||
Required parameter. The description of pull-request
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory)] [string] $RepositoryOwner,
|
||||
[Parameter(Mandatory)] [string] $RepositoryName,
|
||||
[Parameter(Mandatory)] [string] $RepositoryFullName,
|
||||
[Parameter(Mandatory)] [string] $AccessToken,
|
||||
[Parameter(Mandatory)] [string] $BranchName,
|
||||
[Parameter(Mandatory)] [string] $CommitMessage,
|
||||
@@ -46,11 +43,11 @@ function Update-PullRequest {
|
||||
|
||||
$updatedPullRequest = $GitHubApi.UpdatePullRequest($Title, $Body, $BranchName, $PullRequest.number)
|
||||
|
||||
if (($updatedPullRequest -eq $null) -or ($updatedPullRequest.html_url -eq $null)) {
|
||||
Write-Host "##vso[task.logissue type=error;] Unexpected error occurs while updating pull request."
|
||||
if (($null -eq $updatedPullRequest) -or ($null -eq $updatedPullRequest.html_url)) {
|
||||
Write-Host "Unexpected error occurs while updating pull request."
|
||||
exit 1
|
||||
}
|
||||
Write-host "##[section] Pull request updated: $($updatedPullRequest.html_url)"
|
||||
Write-host "Pull request updated: $($updatedPullRequest.html_url)"
|
||||
}
|
||||
|
||||
function Create-PullRequest {
|
||||
@@ -67,12 +64,12 @@ function Create-PullRequest {
|
||||
|
||||
$createdPullRequest = $GitHubApi.CreateNewPullRequest($Title, $Body, $BranchName)
|
||||
|
||||
if (($createdPullRequest -eq $null) -or ($createdPullRequest.html_url -eq $null)) {
|
||||
Write-Host "##vso[task.logissue type=error;] Unexpected error occurs while creating pull request."
|
||||
if (($null -eq $createdPullRequest) -or ($null -eq $createdPullRequest.html_url)) {
|
||||
Write-Host "Unexpected error occurs while creating pull request."
|
||||
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"
|
||||
@@ -87,8 +84,8 @@ Git-CommitAllChanges -Message $CommitMessage
|
||||
Write-Host "Push branch: $BranchName"
|
||||
Git-PushBranch -Name $BranchName -Force $true
|
||||
|
||||
$gitHubApi = Get-GitHubApi -AccountName $RepositoryOwner -ProjectName $RepositoryName -AccessToken $AccessToken
|
||||
$pullRequest = $gitHubApi.GetPullRequest($BranchName, $RepositoryOwner)
|
||||
$gitHubApi = Get-GitHubApi -RepositoryFullName $RepositoryFullName -AccessToken $AccessToken
|
||||
$pullRequest = $gitHubApi.GetPullRequest($BranchName)
|
||||
|
||||
if ($pullRequest.Count -gt 0) {
|
||||
Write-Host "Update pull request"
|
||||
|
||||
@@ -5,8 +5,8 @@ The module that contains a bunch of methods to interact with GitHub API V3
|
||||
class GitHubApi
|
||||
{
|
||||
[string] $BaseUrl
|
||||
[string] $RepoOwner
|
||||
[object] $AuthHeader
|
||||
[string] $RepositoryOwner
|
||||
|
||||
GitHubApi(
|
||||
[string] $AccountName,
|
||||
@@ -15,6 +15,7 @@ class GitHubApi
|
||||
) {
|
||||
$this.BaseUrl = $this.BuildBaseUrl($AccountName, $ProjectName)
|
||||
$this.AuthHeader = $this.BuildAuth($AccessToken)
|
||||
$this.RepositoryOwner = $AccountName
|
||||
}
|
||||
|
||||
[object] hidden BuildAuth([string]$AccessToken) {
|
||||
@@ -43,9 +44,9 @@ class GitHubApi
|
||||
return $this.InvokeRestMethod($url, 'Post', $null, $requestBody)
|
||||
}
|
||||
|
||||
[object] GetPullRequest([string]$BranchName, [string]$RepositoryOwner){
|
||||
[object] GetPullRequest([string]$BranchName){
|
||||
$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){
|
||||
@@ -82,6 +83,35 @@ class GitHubApi
|
||||
return $releases
|
||||
}
|
||||
|
||||
[void] DispatchWorkflow([string]$EventType) {
|
||||
$url = "dispatches"
|
||||
$body = @{
|
||||
event_type = $EventType
|
||||
} | 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
|
||||
inputs = $Inputs
|
||||
} | ConvertTo-Json
|
||||
|
||||
$this.InvokeRestMethod($url, 'POST', $null, $body)
|
||||
}
|
||||
|
||||
[string] hidden BuildUrl([string]$Url, [string]$RequestParams) {
|
||||
if ([string]::IsNullOrEmpty($RequestParams)) {
|
||||
return "$($this.BaseUrl)/$($Url)"
|
||||
@@ -117,10 +147,18 @@ class GitHubApi
|
||||
|
||||
function Get-GitHubApi {
|
||||
param (
|
||||
[string] $AccountName,
|
||||
[string] $ProjectName,
|
||||
[Parameter(ParameterSetName = 'RepositorySingle')]
|
||||
[string] $RepositoryFullName,
|
||||
[Parameter(ParameterSetName = 'RepositorySplitted')]
|
||||
[string] $RepositoryOwner,
|
||||
[Parameter(ParameterSetName = 'RepositorySplitted')]
|
||||
[string] $RepositoryName,
|
||||
[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
91
github/run-ci-builds.ps1
Normal 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 Token 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
|
||||
@@ -1,13 +1,10 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generate versions manifest based on repository releases
|
||||
|
||||
.DESCRIPTION
|
||||
Versions manifest is needed to find the latest assets for particular version of tool
|
||||
.PARAMETER GitHubRepositoryOwner
|
||||
Required parameter. The organization which tool repository belongs
|
||||
.PARAMETER GitHubRepositoryName
|
||||
Required parameter. The name of tool repository
|
||||
.PARAMETER RepositoryFullName
|
||||
Required parameter. The owner and repository name. For example, 'actions/versions-package-tools'
|
||||
.PARAMETER GitHubAccessToken
|
||||
Required parameter. PAT Token to overcome GitHub API Rate limit
|
||||
.PARAMETER OutputFile
|
||||
@@ -17,8 +14,7 @@ Path to the json file with parsing configuration
|
||||
#>
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory)] [string] $GitHubRepositoryOwner,
|
||||
[Parameter(Mandatory)] [string] $GitHubRepositoryName,
|
||||
[Parameter(Mandatory)] [string] $RepositoryFullName,
|
||||
[Parameter(Mandatory)] [string] $GitHubAccessToken,
|
||||
[Parameter(Mandatory)] [string] $OutputFile,
|
||||
[Parameter(Mandatory)] [string] $ConfigurationFile
|
||||
@@ -29,7 +25,7 @@ Import-Module (Join-Path $PSScriptRoot "manifest-utils.psm1") -Force
|
||||
|
||||
$configuration = Read-ConfigurationFile -Filepath $ConfigurationFile
|
||||
|
||||
$gitHubApi = Get-GitHubApi -AccountName $GitHubRepositoryOwner -ProjectName $GitHubRepositoryName -AccessToken $GitHubAccessToken
|
||||
$gitHubApi = Get-GitHubApi -RepositoryFullName $RepositoryFullName -AccessToken $GitHubAccessToken
|
||||
$releases = $gitHubApi.GetReleases()
|
||||
$versionIndex = Build-VersionsManifest -Releases $releases -Configuration $configuration
|
||||
$versionIndex | ConvertTo-Json -Depth 5 | Out-File $OutputFile -Encoding UTF8NoBOM -Force
|
||||
|
||||
@@ -4,30 +4,47 @@ Pester extension that allows to run command and validate exit code
|
||||
.EXAMPLE
|
||||
"python file.py" | Should -ReturnZeroExitCode
|
||||
#>
|
||||
|
||||
function Get-CommandResult {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $Command,
|
||||
[switch] $Multiline
|
||||
)
|
||||
# Bash trick to suppress and show error output because some commands write to stderr (for example, "python --version")
|
||||
$stdout = & bash -c "$Command 2>&1"
|
||||
$exitCode = $LASTEXITCODE
|
||||
return @{
|
||||
Output = If ($Multiline -eq $true) { $stdout } else { [string]$stdout }
|
||||
ExitCode = $exitCode
|
||||
}
|
||||
}
|
||||
|
||||
function ShouldReturnZeroExitCode {
|
||||
Param(
|
||||
[Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()]
|
||||
[String]$ActualValue,
|
||||
[switch]$Negate
|
||||
[String] $ActualValue,
|
||||
[switch] $Negate,
|
||||
[string] $Because # This parameter is unused by we need it to match Pester asserts signature
|
||||
)
|
||||
|
||||
Write-Host "Run command '${ActualValue}'"
|
||||
Invoke-Expression -Command $ActualValue | ForEach-Object { Write-Host $_ }
|
||||
$actualExitCode = $LASTEXITCODE
|
||||
$result = Get-CommandResult $ActualValue
|
||||
|
||||
[bool]$succeeded = $actualExitCode -eq 0
|
||||
[bool]$succeeded = $result.ExitCode -eq 0
|
||||
if ($Negate) { $succeeded = -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
|
||||
FailureMessage = $failureMessage
|
||||
}
|
||||
}
|
||||
|
||||
Add-AssertionOperator -Name ReturnZeroExitCode `
|
||||
-Test $function:ShouldReturnZeroExitCode
|
||||
if (Get-Command -Name Add-AssertionOperator -ErrorAction SilentlyContinue) {
|
||||
Add-AssertionOperator -Name ReturnZeroExitCode -InternalName ShouldReturnZeroExitCode -Test ${function:ShouldReturnZeroExitCode}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user