Skip to content

Commit

Permalink
[suppressions.yaml] Create shared component "get-suppressions" (Azure…
Browse files Browse the repository at this point in the history
…#28927)

- Usage: `npx get-suppressions <tool-name> <path-to-file>`
- Returns: JSON array of suppressions, with specified tool name, applying to file (may be empty)
- Example: `npm get-suppressions TypeSpecRequirement specification/foo/data-plane/Foo/stable/2023-01-01/Foo.json`
- Fixes Azure#28069
  • Loading branch information
mikeharder committed May 4, 2024
1 parent a9ace5a commit 3940cd7
Show file tree
Hide file tree
Showing 14 changed files with 2,113 additions and 203 deletions.
54 changes: 54 additions & 0 deletions .github/workflows/suppressions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Suppressions

on:
push:
branches:
- main
- typespec-next
pull_request:
branches:
- main
- typespec-next
paths:
- package-lock.json
- package.json
- tsconfig.json
- eng/tools/package.json
- eng/tools/tsconfig.json
- eng/tools/suppressions

jobs:
ci:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [18, 20]
exclude:
- os: ubuntu-latest
node: 20
- os: windows-latest
node: 18

runs-on: ${{ matrix.os }}

steps:
- name: Enable git long paths
if: runner.os == 'Windows'
run: git config --system core.longpaths true

- uses: actions/checkout@v4
with:
sparse-checkout: eng

- name: Use Node ${{ matrix.node }}.x
uses: actions/setup-node@v4
with:
node-version: '${{ matrix.node }}.x'

- run: npm ci

- run: npm run build
working-directory: ./eng/tools/suppressions

- run: npm test
working-directory: ./eng/tools/suppressions
85 changes: 16 additions & 69 deletions eng/scripts/TypeSpec-Requirement.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,37 @@ param (
[Parameter(Position = 1)]
[string] $TargetCommitish = "HEAD",
[Parameter(Position = 2)]
[string] $SpecType = "data-plane|resource-manager"
[string] $SpecType = "data-plane|resource-manager",
[string] $CheckAllUnder
)
Set-StrictMode -Version 3

. $PSScriptRoot/ChangedFiles-Functions.ps1
. $PSScriptRoot/Logging-Functions.ps1

$script:psYamlInstalled = $false
function Ensure-PowerShell-Yaml-Installed {
if ($script:psYamlInstalled) {
# If already checked once in this script, don't log anything further
return;
}

$script:psYamlInstalled = [bool] (Get-Module -ListAvailable -Name powershell-yaml | Where-Object { $_.Version -eq "0.4.7" })

if ($script:psYamlInstalled) {
LogInfo "Module powershell-yaml@0.4.7 already installed"
}
else {
LogInfo "Installing module powershell-yaml@0.4.7"
Install-Module -Name powershell-yaml -RequiredVersion 0.4.7 -Force -Scope CurrentUser
$script:psYamlInstalled = $true
}
}

function Find-Suppressions-Yaml {
param (
[string]$fileInSpecFolder
)

$currentDirectory = Get-Item (Split-Path -Path $fileInSpecFolder)

while ($currentDirectory) {
$suppressionsFile = Join-Path -Path $currentDirectory.FullName -ChildPath "suppressions.yaml"

if (Test-Path $suppressionsFile) {
return $suppressionsFile
} else {
$currentDirectory = $currentDirectory.Parent
}
}

return $null
}

function Get-Suppression {
param (
[string]$fileInSpecFolder
)

$suppressionsFile = Find-Suppressions-Yaml $fileInSpecFolder
if ($suppressionsFile) {
Ensure-PowerShell-Yaml-Installed

$suppressions = Get-Content -Path $suppressionsFile -Raw | ConvertFrom-Yaml
foreach ($suppression in $suppressions) {
$tool = $suppression["tool"]
$path = $suppression["path"]

if ($tool -eq "TypeSpecRequirement") {
# Paths in suppressions.yml are relative to the file itself
$fullPath = Join-Path -Path (Split-Path -Path $suppressionsFile) -ChildPath $path
# -NoEnumerate to prevent single-element arrays from being collapsed to a single object
# -AsHashtable is closer to raw JSON than PSCustomObject
$suppressions = npx get-suppressions TypeSpecRequirement $fileInSpecFolder | ConvertFrom-Json -NoEnumerate -AsHashtable

# If path is not specified, suppression applies to all files
if (!$path -or ($fileInSpecFolder -like $fullPath)) {
return $suppression
}
}
}
}

return $null
return $suppressions ? $suppressions[0] : $null;
}

$repoPath = Resolve-Path "$PSScriptRoot/../.."
$pathsWithErrors = @()

$filesToCheck = (Get-ChangedSwaggerFiles (Get-ChangedFiles $BaseCommitish $TargetCommitish)).Where({
$filesToCheck = $CheckAllUnder ?
(Get-ChildItem -Path $CheckAllUnder -Recurse -File | Resolve-Path -Relative | ForEach-Object { $_ -replace '\\', '/' }) :
(Get-ChangedSwaggerFiles (Get-ChangedFiles $BaseCommitish $TargetCommitish))

$filesToCheck = $filesToCheck.Where({
($_ -notmatch "/(examples|scenarios|restler|common|common-types)/") -and
($_ -match "specification/[^/]+/($SpecType).*?/(preview|stable)/[^/]+/[^/]+\.json$")
})
})

if (!$filesToCheck) {
LogInfo "No OpenAPI files found to check"
Expand Down Expand Up @@ -138,7 +87,7 @@ else {
}
else {
LogError ("OpenAPI was generated from TypeSpec, but folder 'specification/$rpFolder' contains no files named 'tspconfig.yaml'." `
+ " The TypeSpec used to generate OpenAPI must be added to this folder.")
+ " The TypeSpec used to generate OpenAPI must be added to this folder.")
LogJobFailure
exit 1
}
Expand Down Expand Up @@ -170,7 +119,7 @@ else {
$urlToStableFolder = "https://github.com/Azure/azure-rest-api-specs/tree/main/specification/$servicePath/stable"

# Avoid conflict with pipeline secret
$logUrlToStableFolder = $urlToStableFolder -replace '^https://',''
$logUrlToStableFolder = $urlToStableFolder -replace '^https://', ''

LogInfo " Checking $logUrlToStableFolder"

Expand Down Expand Up @@ -209,15 +158,13 @@ else {
}
}

if ($pathsWithErrors.Count -gt 0)
{
if ($pathsWithErrors.Count -gt 0) {
# DevOps only adds the first 4 errors to the github checks list so lets always add the generic one first
# and then as many of the individual ones as can be found afterwards
LogError "New specs must use TypeSpec. For more detailed docs see https://aka.ms/azsdk/typespec"
LogJobFailure

foreach ($path in $pathsWithErrors)
{
foreach ($path in $pathsWithErrors) {
LogErrorForFile $path "OpenAPI was not generated from TypeSpec, and spec appears to be new"
}
exit 1
Expand Down
1 change: 1 addition & 0 deletions eng/tools/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "azure-rest-api-specs-eng-tools",
"devDependencies": {
"@azure-tools/suppressions": "file:suppressions",
"@azure-tools/typespec-validation": "file:typespec-validation"
},
"private": true
Expand Down
5 changes: 5 additions & 0 deletions eng/tools/suppressions/cmd/get-suppressions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env node

import { main } from "../dist/src/index.js"

await main();
29 changes: 29 additions & 0 deletions eng/tools/suppressions/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "@azure-tools/suppressions",
"private": true,
"version": "0.0.1",
"type": "module",
"main": "dist/src/index.js",
"bin": {
"get-suppressions": "cmd/get-suppressions.js"
},
"dependencies": {
"minimatch": "^9.0.4",
"yaml": "^2.4.2",
"zod": "^3.23.6",
"zod-validation-error": "^3.2.0"
},
"devDependencies": {
"@types/node": "^18.19.31",
"typescript": "~5.4.5",
"vitest": "^1.5.3"
},
"scripts": {
"build": "tsc",
"postinstall": "npm run build",
"test": "vitest"
},
"engines": {
"node": ">= 18.0.0"
}
}
Loading

0 comments on commit 3940cd7

Please sign in to comment.