Skip to content

Commit

Permalink
feat: Add additional logic if workflow fails and issue is created (Az…
Browse files Browse the repository at this point in the history
…ure#1403)

More fine grained logic, regarding commenting and assigning new failing
workflow issues
  • Loading branch information
rahalan authored Apr 12, 2024
1 parent 54eb216 commit bed50a4
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 11 deletions.
13 changes: 10 additions & 3 deletions .github/workflows/avm.platform.manage-workflow-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: "avm.platform.manage-workflow-issue"
on:
schedule:
- cron: "30 5 * * *" # Every day at 5:30 am
workflow_dispatch:

jobs:
manage-issues:
Expand All @@ -14,16 +15,22 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- env:
GH_TOKEN: ${{ github.token }}
name: Manage issues
- uses: tibdex/github-app-token@v2
id: generate-token
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Manage issues
shell: pwsh
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
# Load used functions
. (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'platform' 'Set-AvmGithubIssueForWorkflow.ps1')
$functionInput = @{
Repo = "${{ github.repository_owner }}/${{ github.event.repository.name }}"
RepoRoot = $env:GITHUB_WORKSPACE
LimitNumberOfRuns = 500
LimitInDays = 2
IgnoreWorkflows = @()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- env:
GH_TOKEN: ${{ github.token }}
name: "Run scripts"
- uses: tibdex/github-app-token@v2
id: generate-token
with:
app_id: ${{ secrets.TEAM_LINTER_APP_ID }}
private_key: ${{ secrets.TEAM_LINTER_PRIVATE_KEY }}
- name: "Run scripts"
shell: pwsh
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
# Load used functions
. (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'platform' 'Set-AvmGitHubIssueOwnerConfig.ps1')
. (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'platform' 'Set-AvmGitHubIssueOwnerConfig.ps1')
$functionInput = @{
Repo = "${{ github.repository_owner }}/${{ github.event.repository.name }}"
Repo = "${{ github.repository_owner }}/${{ github.event.repository.name }}"
RepoRoot = $env:GITHUB_WORKSPACE
IssueUrl = "${{ github.event.issue.url }}"
}
Expand Down
54 changes: 51 additions & 3 deletions avm/utilities/pipelines/platform/Set-AvmGithubIssueForWorkflow.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ Check for failing pipelines and create issues for those, that are failing.
If a pipeline fails, a new issue will be created, with a link to the failed pipeline. If the issue is already existing, a comment will be added, if a new run failed (with the link for the new failed run). If a pipeline run succeeds and an issue is open for the failed run, it will be closed (and a link to the successful run is added to the issue).
.PARAMETER Repo
Mandatory. The name of the respository to scan. Needs to have the structure "<owner>/<repositioryName>"
Mandatory. The name of the respository to scan. Needs to have the structure "<owner>/<repositioryName>", like 'Azure/bicep-registry-modules/'
.PARAMETER RepoRoot
Optional. Path to the root of the repository.
.PARAMETER LimitNumberOfRuns
Optional. Number of recent runs to scan for failed runs. Default is 100.
Expand All @@ -23,14 +26,17 @@ Set-AvmGithubIssueForWorkflow -Repo 'owner/repo01' -LimitNumberOfRuns 100 -Limit
Check the last 100 workflow runs in the repository 'owner/repo01' that happened in the last 2 days. If the workflow name is 'Pipeline 01', then ignore the workflow run.
.NOTES
The function requires GitHub CLI to be installed.
Will be triggered by the workflow avm.platform.manage-workflow-issue.yml
#>
function Set-AvmGithubIssueForWorkflow {
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory = $true)]
[string] $Repo,

[Parameter(Mandatory = $false)]
[string] $RepoRoot = (Get-Item -Path $PSScriptRoot).parent.parent.parent.parent.FullName,

[Parameter(Mandatory = $false)]
[int] $LimitNumberOfRuns = 100,

Expand All @@ -41,6 +47,10 @@ function Set-AvmGithubIssueForWorkflow {
[String[]] $IgnoreWorkflows = @()
)

# Loading helper functions
. (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'platform' 'helper' 'Get-AvmCsvData.ps1')
. (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'platform' 'helper' 'Add-GithubIssueToProject.ps1')

$issues = gh issue list --state open --limit 500 --label 'Type: AVM :a: :v: :m:,Type: Bug :bug:' --json 'title,url,body,comments,labels' --repo $Repo | ConvertFrom-Json -Depth 100
$runs = gh run list --json 'url,workflowName,headBranch,startedAt' --limit $LimitNumberOfRuns --repo $Repo | ConvertFrom-Json -Depth 100
$workflowRuns = @{}
Expand Down Expand Up @@ -81,7 +91,45 @@ function Set-AvmGithubIssueForWorkflow {

if ($issues.title -notcontains $issueName) {
if ($PSCmdlet.ShouldProcess("Issue [$issueName]", 'Create')) {
gh issue create --title "$issueName" --body "$failedrun" --label 'Type: AVM :a: :v: :m:,Type: Bug :bug:' --repo $Repo
$issueUrl = gh issue create --title "$issueName" --body "$failedrun" --label 'Type: AVM :a: :v: :m:,Type: Bug :bug:' --repo $Repo
$ProjectNumber = 538 # AVM - Issue Triage
$comment = @"
> [!IMPORTANT]
> @Azure/avm-core-team-technical-bicep, the workflow for the ``$moduleName`` module has failed. Please investigate the failed workflow run.
"@

if ($workflowRun.workflowName -match 'avm.(?:res|ptn)') {
$moduleName = $workflowRun.workflowName.Replace('.', '/')
$moduleIndex = $moduleName.StartsWith('avm/res') ? 'Bicep-Resource' : 'Bicep-Pattern'
# get CSV data
$module = Get-AvmCsvData -ModuleIndex $moduleIndex | Where-Object ModuleName -EQ $moduleName

if (($module.ModuleStatus -ne 'Module Orphaned :eyes:') -and (-not ([string]::IsNullOrEmpty($module.PrimaryModuleOwnerGHHandle)))) {
$ProjectNumber = 566 # AVM - Module Issues
$comment = @"
> [!IMPORTANT]
> @$($module.ModuleOwnersGHTeam), the workflow for the ``$moduleName`` module has failed. Please investigate the failed workflow run. If you are not able to do so, please inform the AVM core team to take over.
"@
# assign owner
$assign = gh issue edit $issue.url --add-assignee $module.PrimaryModuleOwnerGHHandle --repo $Repo

if ([String]::IsNullOrEmpty($assign)) {
if ($PSCmdlet.ShouldProcess("missing user comment to issue [$($issue.title)]", 'Add')) {
$comment = @"
> [!WARNING]
> This issue couldn't be assigend due to an internal error. @$($module.PrimaryModuleOwnerGHHandle), please make sure this issue is assigned to you and please provide an initial response as soon as possible, in accordance with the [AVM Support statement](https://aka.ms/AVM/Support).
"@

gh issue comment $issue.url --body $reply --repo $Repo
}
}
}
}

# add issue to project
Add-GithubIssueToProject -Repo $Repo -ProjectNumber $ProjectNumber -IssueUrl $issueUrl
# add comment
gh issue comment $issueUrl --body $comment --repo $Repo
}

$issuesCreated++
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<#
.SYNOPSIS
Adds an existing GitHub issue to an existing GitHub project (the new type, not the classic ones)
.DESCRIPTION
Adds an existing GitHub issue to an existing GitHub project (the new type, not the classic ones)
.PARAMETER Repo
Mandatory. The name of the respository to scan. Needs to have the structure "<owner>/<repositioryName>", like 'Azure/bicep-registry-modules/'
.PARAMETER ProjectNumber
Mandatory. The GitHub project number (see last part of project URL, for example 538 for https://github.com/orgs/Azure/projects/538)
.PARAMETER IssueUrl
Mandatory. The URL of the GitHub issue, like 'https://github.com/Azure/bicep-registry-modules/issues/757'
.EXAMPLE
Add-GithubIssueToProject -Repo 'Azure/bicep-registry-modules' -ProjectNumber 538 -IssueUrl 'https://github.com/Azure/bicep-registry-modules/issues/757'
.NOTES
Needs to run under a context with the permissions to read/write organization projects
#>
function Add-GithubIssueToProject {
param (
[Parameter(Mandatory = $true)]
[string] $Repo,

[Parameter(Mandatory = $true)]
[int] $ProjectNumber,

[Parameter(Mandatory = $true)]
[string] $IssueUrl
)

$Organization = $Repo.Split('/')[0]

$Project = gh api graphql -f query='
query($organization: String! $number: Int!){
organization(login: $organization){
projectV2(number: $number) {
id
}
}
}' -f organization=$Organization -F number=$ProjectNumber | ConvertFrom-Json -Depth 10

$ProjectId = $Project.data.organization.projectV2.id
$IssueId = (gh issue view $IssueUrl --repo $Repo --json 'id' | ConvertFrom-Json -Depth 100).id

gh api graphql -f query='
mutation($project:ID!, $issue:ID!) {
addProjectV2ItemById(input: {projectId: $project, contentId: $issue}) {
item {
id
}
}
}' -f project=$ProjectId -f issue=$IssueId
}
59 changes: 59 additions & 0 deletions avm/utilities/pipelines/platform/helper/Get-AvmCsvData.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<#
.SYNOPSIS
Parses AVM module CSV file
.DESCRIPTION
Depending on the parameter, the correct CSV file will be parsed and returned a an object
.PARAMETER ModuleIndex
Mandatory. Type of CSV file, that should be parsed ('Bicep-Resource', 'Bicep-Pattern')
.EXAMPLE
Get-AvmCsvData -ModuleIndex 'Bicep-Resource'
Parse the AVM Bicep modules
#>
Function Get-AvmCsvData {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[ValidateSet('Bicep-Resource', 'Bicep-Pattern')]
[string] $ModuleIndex
)

# CSV file URLs
$BicepResourceUrl = 'https://aka.ms/avm/index/bicep/res/csv'
$BicepPatternUrl = 'https://aka.ms/avm/index/bicep/ptn/csv'

# Retrieve the CSV file
switch ($ModuleIndex) {
'Bicep-Resource' {
try {
$unfilteredCSV = Invoke-WebRequest -Uri $BicepResourceUrl
} catch {
throw 'Unable to retrieve CSV file - Check network connection.'
}
}
'Bicep-Pattern' {
try {
$unfilteredCSV = Invoke-WebRequest -Uri $BicepPatternUrl
} catch {
throw 'Unable to retrieve CSV file - Check network connection.'
}
}
}

# Convert the CSV content to a PowerShell object
$formattedBicepFullCsv = ConvertFrom-Csv $unfilteredCSV.Content

# Loop through each item in the filtered data
foreach ($item in $formattedBicepFullCsv) {
# Remove '@Azure/' from the ModuleOwnersGHTeam property
$item.ModuleOwnersGHTeam = $item.ModuleOwnersGHTeam -replace '@Azure\/', ''
# Remove '@Azure/' from the ModuleContributorsGHTeam property
$item.ModuleContributorsGHTeam = $item.ModuleContributorsGHTeam -replace '@Azure\/', ''
}

# Return the modified data
return $formattedBicepFullCsv
}

0 comments on commit bed50a4

Please sign in to comment.