SNFR23 - GitHub Repo Labels

ID: SNFR23 - Category: Contribution/Support - GitHub Repo Labels

GitHub repositories where modules are held MUST use the below labels and SHOULD not use any additional labels:

โž• AVM Standard GitHub Labels

These labels are available in a CSV file from here

NameDescriptionHEX
AZD ๐Ÿง‘โ€๐Ÿ’ปThese modules are requested/used by the AZD team.
E0BFFA
Needs: Attention ๐Ÿ‘‹Reply has been added to issue, maintainer to review
E99695
Needs: Immediate Attention โ€ผ๏ธImmediate attention of module owner / AVM team is needed
FF0000
Needs: Author Feedback ๐Ÿ‘‚Awaiting feedback from the issue/PR author
F18A07
Needs: External Changes โš’๏ธWhen an issue/PR requires changes that are outside of the control of the module. e.g. to an RP.
DE389D
Needs: More Evidence โš–We are looking for more evidence to make a decision on this
F64872
Needs: Triage ๐Ÿ”Maintainers need to triage still
FBCA04
Needs: Module Owner ๐Ÿ“ฃIn the AVM repository: this module needs an owner to develop or maintain it. In the BRM repository: the module owner needs to review a PR.
FF0019
Needs: Module Contributor ๐Ÿ“ฃThis module needs secondary owner(s) or contributor(s) to develop or maintain it
C95474
Needs: Core Team ๐Ÿงžโ€โ™‚๏ธThis item needs the AVM Core Team to review it
DB4503
Status: Awaiting Release To Be Cut โœ‚๏ธThis is fixed in the main branch but not in the latest release, will be fixed with next release cut
800080
Status: Do Not Merge โ›”Do not merge PRs with this label attached as they are not ready or aligned to future direction etc.
8B4513
Status: External Contribution ๐ŸŒThis is being worked on by someone outside of the AVM module owners/contributors or AVM core team
D8FA2C
Status: Fixed โœ…Auto label applied when issue fixed by merged PR
90EE90
Status: Help Wanted ๐Ÿ†˜Extra attention is needed
FF4500
Status: In Triage ๐Ÿ”Picked up for triaging by an AVM core team member
D4AF37
Status: In PR ๐Ÿ‘‰This is when an issue is due to be fixed in an open PR
EDEDED
Status: Invalid โŒThis doesn't seem right
E4E669
Status: Long Term โณWe will do it, but will take a longer amount of time due to complexity/priorities
B60205
Status: No Recent Activity ๐Ÿ’คWhen an issue/PR has not been modified for X amount of days
808080
Status: Won't Fix ๐Ÿ’”This will not be worked on
FFFFFF
Status: Owners Identified ๐Ÿค˜This module has its owners identified
FBEF2A
Status: Module Available ๐ŸŸขThe module is published
C8E6C9
Status: Module Orphaned ๐Ÿ‘€The module has no owner and is therefore orphaned at this time
F4A460
Status: Response Overdue ๐ŸšฉWhen an issue/PR has not been responded to for X amount of days
850000
Status: Looking For Assistance ๐Ÿฆ†This item is looking for anyone to help develop the code and submit a PR for resolution
03FCC2
Type: Bug ๐Ÿ›Something isn't working
D73A4A
Type: CI ๐Ÿš€This issue is related to the AVM CI
74CFB0
Type: Documentation ๐Ÿ“„Improvements or additions to documentation
0075CA
Type: Duplicate ๐ŸคฒThis issue or pull request already exists
CFD3D7
Type: Feature Request โž•New feature or request
A2EEEF
Type: Hygiene ๐Ÿงนthings related to testing, issue triage etc.
17016A
Type: New Module Proposal ๐Ÿ’กA new module for AVM is being proposed
ADD8E6
Type: Question/Feedback ๐Ÿ™‹โ€โ™€๏ธFurther information is requested or just some feedback
CB6BA2
Type: Security Bug ๐Ÿ”’This is a security bug
FFFF00
Type: AVM ๐Ÿ…ฐ๏ธ โœŒ๏ธ โ“œ๏ธThis is an AVM related issue
F0FFFF
Language: Terraform ๐ŸŒThis is related to the Terraform IaC language
7740B6
Language: Bicep ๐Ÿ’ชThis is related to the Bicep IaC language
1D73B3
Class: Resource Module ๐Ÿ“ฆThis is a resource module
D3D3D3
Class: Pattern Module ๐Ÿ“ฆThis is a pattern module
A9A9A9
Class: Utility Module ๐Ÿ“ฆThis is a utility module
CAD1DE

To help apply these to a module GitHub repository you can use the below PowerShell script:

โž• Set-AvmGitHubLabels.ps1

For most scenario this is the command you’ll need to call the below PowerShell script with, replacing the value for RepositoryName:

  Set-AvmGitHubLabels.ps1 -RepositoryName "Org/MyGitHubRepo" -CreateCsvLabelExports $false -NoUserPrompts $true
```shell
# Linux / MacOs
# For Windows replace $PWD with your the local path or your repository
#
docker run -it -v $PWD:/repo -w /repo mcr.microsoft.com/powershell pwsh -Command '
    #Invoke-WebRequest -Uri "https://azure.github.io/Azure-Verified-Modules/scripts/Set-AvmGitHubLabels.ps1" -OutFile "Set-AvmGitHubLabels.ps1"
    $gh_version = "2.44.1"
    Invoke-WebRequest -Uri "https://github.com/cli/cli/releases/download/v2.44.1/gh_2.44.1_linux_amd64.tar.gz" -OutFile "gh_$($gh_version)_linux_amd64.tar.gz"
    apt-get update && apt-get install -y git
    tar -xzf "gh_$($gh_version)_linux_amd64.tar.gz"
    ls -lsa
    mv "gh_$($gh_version)_linux_amd64/bin/gh" /usr/local/bin/
    rm "gh_$($gh_version)_linux_amd64.tar.gz" && rm -rf "gh_$($gh_version)_linux_amd64"
    gh --version
    ls -lsa
    gh auth login
    $OrgProject = "Azure/terraform-azurerm-avm-res-kusto-cluster"
    gh auth status
    ./Set-AvmGitHubLabels.ps1 -RepositoryName $OrgProject -CreateCsvLabelExports $false -NoUserPrompts $true

  '
```

By default this script will only update and append labels on the repository specified. However, this can be changed by setting the parameter -UpdateAndAddLabelsOnly to $false, which will remove all the labels from the repository first and then apply the AVM labels from the CSV only.

Make sure you elevate your privilege to admin level or the labels will not be applied to your repository. Go to repos.opensource.microsoft.com/orgs/Azure/repos/ to request admin access before running the script.

Full Script:

These Set-AvmGitHubLabels.ps1 can be downloaded from here.

  [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Justification = "Coloured output required in this script")]
  
  <#
  .SYNOPSIS
    This script can be used to create the Azure Verified Modules (AVM) standard GitHub labels to a GitHub repository.
  
  .DESCRIPTION
    This script can be used to create the Azure Verified Modules (AVM) standard GitHub labels to a GitHub repository.
  
    By default, the script will remove all pre-existing labels and apply the AVM labels. However, this can be changed by using the -RemoveExistingLabels parameter and setting it to $false. The tool will also output the labels that exist in the repository before and after the script has run to a CSV file in the current directory, or a directory specified by the -OutputDirectory parameter.
  
    The AVM labels to be created are documented here: TBC
  
  .NOTES
    Please ensure you have specified the GitHub repositry correctly. The script will prompt you to confirm the repository name before proceeding.
  
  .COMPONENT
    You must have the GitHub CLI installed and be authenticated to a GitHub account with access to the repository you are applying the labels to before running this script.
  
  .LINK
    TBC
  
  .Parameter RepositoryName
    The name of the GitHub repository to apply the labels to.
  
  .Parameter RemoveExistingLabels
    If set to $true, the default value, the script will remove all pre-existing labels from the repository specified in -RepositoryName before applying the AVM labels. If set to $false, the script will not remove any pre-existing labels.
  
  .Parameter UpdateAndAddLabelsOnly
    If set to $true, the default value, the script will only update and add labels to the repository specified in -RepositoryName. If set to $false, the script will remove all pre-existing labels from the repository specified in -RepositoryName before applying the AVM labels.
  
  .Parameter OutputDirectory
    The directory to output the pre-existing and post-existing labels to in a CSV file. The default value is the current directory.
  
  .Parameter CreateCsvLabelExports
    If set to $true, the default value, the script will output the pre-existing and post-existing labels to a CSV file in the current directory, or a directory specified by the -OutputDirectory parameter. If set to $false, the script will not output the pre-existing and post-existing labels to a CSV file.
  
  .Parameter GitHubCliLimit
    The maximum number of labels to return from the GitHub CLI. The default value is 999.
  
  .Parameter LabelsToApplyCsvUri
    The URI to the CSV file containing the labels to apply to the GitHub repository. The default value is https://raw.githubusercontent.com/jtracey93/label-source/main/avm-github-labels.csv.
  
  .Parameter NoUserPrompts
    If set to $true, the default value, the script will not prompt the user to confirm they want to remove all pre-existing labels from the repository specified in -RepositoryName before applying the AVM labels. If set to $false, the script will prompt the user to confirm they want to remove all pre-existing labels from the repository specified in -RepositoryName before applying the AVM labels.
  
    This is useful for running the script in automation workflows
  
  .EXAMPLE
    Create the AVM labels in the repository Org/MyGitHubRepo and remove all pre-existing labels.
  
    Set-AvmGitHubLabels.ps1 -RepositoryName "Org/MyGitHubRepo"
  
  .EXAMPLE
    Create the AVM labels in the repository Org/MyGitHubRepo and do not remove any pre-existing labels, just overwrite any labels that have the same name.
  
    Set-AvmGitHubLabels.ps1 -RepositoryName "Org/MyGitHubRepo" -RemoveExistingLabels $false
  
  .EXAMPLE
    Create the AVM labels in the repository Org/MyGitHubRepo and output the pre-existing and post-existing labels to the directory C:\GitHubLabels.
  
    Set-AvmGitHubLabels.ps1 -RepositoryName "Org/MyGitHubRepo" -OutputDirectory "C:\GitHubLabels"
  
  .EXAMPLE
    Create the AVM labels in the repository Org/MyGitHubRepo and output the pre-existing and post-existing labels to the directory C:\GitHubLabels and do not remove any pre-existing labels, just overwrite any labels that have the same name.
  
    Set-AvmGitHubLabels.ps1 -RepositoryName "Org/MyGitHubRepo" -OutputDirectory "C:\GitHubLabels" -RemoveExistingLabels $false
  
  .EXAMPLE
    Create the AVM labels in the repository Org/MyGitHubRepo and do not create the pre-existing and post-existing labels CSV files and do not remove any pre-existing labels, just overwrite any labels that have the same name.
  
    Set-AvmGitHubLabels.ps1 -RepositoryName "Org/MyGitHubRepo" -RemoveExistingLabels $false -CreateCsvLabelExports $false
  
  .EXAMPLE
    Create the AVM labels in the repository Org/MyGitHubRepo and do not create the pre-existing and post-existing labels CSV files and do not remove any pre-existing labels, just overwrite any labels that have the same name. Finally, use a custom CSV file hosted on the internet to create the labels from.
  
    Set-AvmGitHubLabels.ps1 -RepositoryName "Org/MyGitHubRepo" -OutputDirectory "C:\GitHubLabels" -RemoveExistingLabels $false -CreateCsvLabelExports $false -LabelsToApplyCsvUri "https://example.com/csv/avm-github-labels.csv"
  
  #>
  
  #Requires -PSEdition Core
  
  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [string]$RepositoryName,
  
    [Parameter(Mandatory = $false)]
    [bool]$RemoveExistingLabels = $true,
  
    [Parameter(Mandatory = $false)]
    [bool]$UpdateAndAddLabelsOnly = $true,
  
    [Parameter(Mandatory = $false)]
    [bool]$CreateCsvLabelExports = $true,
  
    [Parameter(Mandatory = $false)]
    [string]$OutputDirectory = (Get-Location),
  
    [Parameter(Mandatory = $false)]
    [int]$GitHubCliLimit = 999,
  
    [Parameter(Mandatory = $false)]
    [string]$LabelsToApplyCsvUri = "https://azure.github.io/Azure-Verified-Modules/governance/avm-standard-github-labels.csv",
  
    [Parameter(Mandatory = $false)]
    [bool]$NoUserPrompts = $false
  )
  
  # Check if the GitHub CLI is installed
  $GitHubCliInstalled = Get-Command gh -ErrorAction SilentlyContinue
  if ($null -eq $GitHubCliInstalled) {
    throw "The GitHub CLI is not installed. Please install the GitHub CLI and try again."
  }
  Write-Host "The GitHub CLI is installed..." -ForegroundColor Green
  
  # Check if GitHub CLI is authenticated
  $GitHubCliAuthenticated = gh auth status
  if ($LASTEXITCODE -ne 0) {
    Write-Host $GitHubCliAuthenticated -ForegroundColor Red
    throw "Not authenticated to GitHub. Please authenticate to GitHub using the GitHub CLI, `gh auth login`, and try again."
  }
  Write-Host "Authenticated to GitHub..." -ForegroundColor Green
  
  # Check if GitHub repository name is valid
  $GitHubRepositoryNameValid = $RepositoryName -match "^[a-zA-Z0-9-]+/[a-zA-Z0-9-]+$"
  if ($false -eq $GitHubRepositoryNameValid) {
    throw "The GitHub repository name $RepositoryName is not valid. Please check the repository name and try again. The format must be <OrgName>/<RepoName>"
  }
  
  # List GitHub repository provided and check it exists
  $GitHubRepository = gh repo view $RepositoryName
  if ($LASTEXITCODE -ne 0) {
    Write-Host $GitHubRepository -ForegroundColor Red
    throw "The GitHub repository $RepositoryName does not exist. Please check the repository name and try again."
  }
  Write-Host "The GitHub repository $RepositoryName exists..." -ForegroundColor Green
  
  # PRE - Get the current GitHub repository labels and export to a CSV file in the current directory or where -OutputDirectory specifies if set to a valid directory path and the directory exists or can be created if it does not exist already
  if ($RemoveExistingLabels -or $UpdateAndAddLabelsOnly) {
    Write-Host "Getting the current GitHub repository (pre) labels for $RepositoryName..." -ForegroundColor Yellow
    $GitHubRepositoryLabels = gh label list -R $RepositoryName -L $GitHubCliLimit --json name,description,color
  
    if ($null -ne $GitHubRepositoryLabels -and $CreateCsvLabelExports -eq $true) {
      $csvFileNamePathPre = "$OutputDirectory\$($RepositoryName.Replace('/', '_'))-Labels-Pre-$(Get-Date -Format FileDateTime).csv"
      Write-Host "Exporting the current GitHub repository (pre) labels for $RepositoryName to $csvFileNamePathPre" -ForegroundColor Yellow
      $GitHubRepositoryLabels | ConvertFrom-Json | Export-Csv -Path $csvFileNamePathPre -NoTypeInformation
    }
  }
  
  # Remove all pre-existing labels if -RemoveExistingLabels is set to $true and user confirms they want to remove all pre-existing labels
  if ($null -ne $GitHubRepositoryLabels) {
    $GitHubRepositoryLabelsJson = $GitHubRepositoryLabels | ConvertFrom-Json
    if ($RemoveExistingLabels -eq $true -and $NoUserPrompts -eq $false -and $UpdateAndAddLabelsOnly -eq $false) {
      $RemoveExistingLabelsConfirmation = Read-Host "Are you sure you want to remove all $($GitHubRepositoryLabelsJson.Count) pre-existing labels from $($RepositoryName)? (Y/N)"
      if ($RemoveExistingLabelsConfirmation -eq "Y") {
        Write-Host "Removing all pre-existing labels from $RepositoryName..." -ForegroundColor Yellow
        $GitHubRepositoryLabels | ConvertFrom-Json | ForEach-Object {
          Write-Host "Removing label $($_.name) from $RepositoryName..." -ForegroundColor DarkRed
          gh label delete -R $RepositoryName $_.name --yes
        }
      }
    }
    if ($RemoveExistingLabels -eq $true -and $NoUserPrompts -eq $true -and $UpdateAndAddLabelsOnly -eq $false) {
      Write-Host "Removing all pre-existing labels from $RepositoryName..." -ForegroundColor Yellow
      $GitHubRepositoryLabels | ConvertFrom-Json | ForEach-Object {
        Write-Host "Removing label $($_.name) from $RepositoryName..." -ForegroundColor DarkRed
        gh label delete -R $RepositoryName $_.name --yes
      }
    }
  }
  if ($null -eq $GitHubRepositoryLabels) {
    Write-Host "No pre-existing labels to remove or not selected to be removed from $RepositoryName..." -ForegroundColor Magenta
  }
  
  # Check LabelsToApplyCsvUri is valid and contains a CSV content
  Write-Host "Checking $LabelsToApplyCsvUri is valid..." -ForegroundColor Yellow
  $LabelsToApplyCsvUriValid = $LabelsToApplyCsvUri -match "^https?://"
  if ($false -eq $LabelsToApplyCsvUriValid) {
    throw "The LabelsToApplyCsvUri $LabelsToApplyCsvUri is not valid. Please check the URI and try again. The format must be a valid URI."
  }
  Write-Host "The LabelsToApplyCsvUri $LabelsToApplyCsvUri is valid..." -ForegroundColor Green
  
  # Create AVM lables from the AVM labels CSV file stored on the web using the convertfrom-csv cmdlet
  $avmLabelsCsv = Invoke-WebRequest -Uri $LabelsToApplyCsvUri | ConvertFrom-Csv
  
  # Check if the AVM labels CSV file contains the following columns: Name, Description, HEX
  $avmLabelsCsvColumns = $avmLabelsCsv | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
  $avmLabelsCsvColumnsValid = $avmLabelsCsvColumns -contains "Name" -and $avmLabelsCsvColumns -contains "Description" -and $avmLabelsCsvColumns -contains "HEX"
  if ($false -eq $avmLabelsCsvColumnsValid) {
    throw "The labels CSV file does not contain the required columns: Name, Description, HEX. Please check the CSV file and try again. It contains the following columns: $avmLabelsCsvColumns"
  }
  Write-Host "The labels CSV file contains the required columns: Name, Description, HEX" -ForegroundColor Green
  
  # Create the AVM labels in the GitHub repository
  Write-Host "Creating/Updating the $($avmLabelsCsv.Count) AVM labels in $RepositoryName..." -ForegroundColor Yellow
  $avmLabelsCsv | ForEach-Object {
    if ($GitHubRepositoryLabelsJson.name -contains $_.name) {
      Write-Host "The label $($_.name) already exists in $RepositoryName. Updating the label to ensure description and color are consitent..." -ForegroundColor Magenta
      gh label create -R $RepositoryName "$($_.name)" -c $_.HEX -d $($_.Description) --force
    }
    else {
      Write-Host "The label $($_.name) does not exist in $RepositoryName. Creating label $($_.name) in $RepositoryName..." -ForegroundColor Cyan
      gh label create -R $RepositoryName "$($_.Name)" -c $_.HEX -d $($_.Description) --force
    }
  }
  
  # POST - Get the current GitHub repository labels and export to a CSV file in the current directory or where -OutputDirectory specifies if set to a valid directory path and the directory exists or can be created if it does not exist already
  if ($CreateCsvLabelExports -eq $true) {
    Write-Host "Getting the current GitHub repository (post) labels for $RepositoryName..." -ForegroundColor Yellow
    $GitHubRepositoryLabels = gh label list -R $RepositoryName -L $GitHubCliLimit --json name,description,color
  
    if ($null -ne $GitHubRepositoryLabels) {
      $csvFileNamePathPre = "$OutputDirectory\$($RepositoryName.Replace('/', '_'))-Labels-Post-$(Get-Date -Format FileDateTime).csv"
      Write-Host "Exporting the current GitHub repository (post) labels for $RepositoryName to $csvFileNamePathPre" -ForegroundColor Yellow
      $GitHubRepositoryLabels | ConvertFrom-Json | Export-Csv -Path $csvFileNamePathPre -NoTypeInformation
    }
  }
  
  # If -RemoveExistingLabels is set to $true and user confirms they want to remove all pre-existing labels check that only the avm labels exist in the repository
  if ($RemoveExistingLabels -eq $true -and ($RemoveExistingLabelsConfirmation -eq "Y" -or $NoUserPrompts -eq $true) -and $UpdateAndAddLabelsOnly -eq $false) {
    Write-Host "Checking that only the AVM labels exist in $RepositoryName..." -ForegroundColor Yellow
    $GitHubRepositoryLabels = gh label list -R $RepositoryName -L $GitHubCliLimit --json name,description,color
    $GitHubRepositoryLabels | ConvertFrom-Json | ForEach-Object {
      if ($avmLabelsCsv.Name -notcontains $_.name) {
        throw "The label $($_.name) exists in $RepositoryName but is not in the CSV file."
      }
    }
    Write-Host "Only the CSV labels exist in $RepositoryName..." -ForegroundColor Green
  }
  
  Write-Host "The CSV labels have been created/updated in $RepositoryName..." -ForegroundColor Green