eng/common/scripts/TypeSpec-Project-Process.ps1 (210 lines of code) (raw):

# For details see https://github.com/Azure/azure-sdk-tools/blob/main/doc/common/TypeSpec-Project-Scripts.md [CmdletBinding()] param ( [Parameter(Position = 0)] [ValidateNotNullOrEmpty()] [string] $TypeSpecProjectDirectory, # A directory of `tspconfig.yaml` or a remoteUrl of `tspconfig.yaml` [Parameter(Position = 1)] [string] $CommitHash, [Parameter(Position = 2)] [string] $RepoUrl, [switch] $SkipSyncAndGenerate ) . $PSScriptRoot/common.ps1 . $PSScriptRoot/Helpers/PSModule-Helpers.ps1 Install-ModuleIfNotInstalled "powershell-yaml" "0.4.7" | Import-Module function CreateUpdate-TspLocation([System.Object]$tspConfig, [string]$TypeSpecProjectDirectory, [string]$CommitHash, [string]$repo, [string]$repoRoot, [ref]$isNewSdkProject) { $additionalDirs = @() if ($tspConfig["parameters"]["dependencies"] -and $tspConfig["parameters"]["dependencies"]["additionalDirectories"]) { $additionalDirs = $tspConfig["parameters"]["dependencies"]["additionalDirectories"]; } # Create service-dir if not exist $serviceDir = Get-ServiceDir $tspConfig $repoRoot if (!(Test-Path -Path $serviceDir)) { New-Item -Path $serviceDir -ItemType Directory | Out-Null Write-Host "created service folder $serviceDir" } # Create package-dir if not exist $packageDir = Get-PackageDir $tspConfig $packageDir = Join-Path $serviceDir $packageDir if (!(Test-Path -Path $packageDir)) { New-Item -Path $packageDir -ItemType Directory | Out-Null Write-Host "created package folder $packageDir" $isNewSdkProject.Value = $true } # Load tsp-location.yaml if exist $tspLocationYamlPath = Join-Path $packageDir "tsp-location.yaml" $tspLocationYaml = @{} if (Test-Path -Path $tspLocationYamlPath) { $tspLocationYaml = Get-Content -Path $tspLocationYamlPath -Raw | ConvertFrom-Yaml } else { Write-Host "creating tsp-location.yaml in $packageDir" } # Update tsp-location.yaml $tspLocationYaml["commit"] = $CommitHash Write-Host "updated tsp-location.yaml commit to $CommitHash" $tspLocationYaml["repo"] = $repo Write-Host "updated tsp-location.yaml repo to $repo" $tspLocationYaml["directory"] = $TypeSpecProjectDirectory Write-Host "updated tsp-location.yaml directory to $TypeSpecProjectDirectory" $tspLocationYaml["additionalDirectories"] = $additionalDirs Write-Host "updated tsp-location.yaml additionalDirectories to $additionalDirs" $tspLocationYaml |ConvertTo-Yaml | Out-File $tspLocationYamlPath Write-Host "finished updating tsp-location.yaml in $packageDir" return $packageDir } function Get-ServiceDir([System.Object]$tspConfig, [string]$repoRoot) { $serviceDir = "" if ($tspConfig["parameters"] -and $tspConfig["parameters"]["service-dir"]) { $serviceDir = $tspConfig["parameters"]["service-dir"]["default"]; } else { Write-Error "Missing service-dir in parameters section of tspconfig.yaml. Please refer to https://github.com/Azure/azure-rest-api-specs/blob/main/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml for the right schema." exit 1 } # Create service-dir if not exist $serviceDir = Join-Path $repoRoot $serviceDir return $serviceDir } function Get-PackageDir([System.Object]$tspConfig) { $emitterName = "" if (Test-Path "Function:$GetEmitterNameFn") { $emitterName = &$GetEmitterNameFn } else { Write-Error "Missing $GetEmitterNameFn function in {$Language} SDK repo script." exit 1 } $packageDir = "" if ($tspConfig["options"] -and $tspConfig["options"]["$emitterName"] -and $tspConfig["options"]["$emitterName"]["package-dir"]) { $packageDir = $tspConfig["options"]["$emitterName"]["package-dir"] } else { Write-Error "Missing package-dir in $emitterName options of tspconfig.yaml. Please refer to https://github.com/Azure/azure-rest-api-specs/blob/main/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml for the right schema." exit 1 } return $packageDir } function Get-TspLocationFolder([System.Object]$tspConfig, [string]$repoRoot) { $serviceDir = Get-ServiceDir $tspConfig $repoRoot $packageDir = Get-PackageDir $tspConfig $packageDir = Join-Path $serviceDir $packageDir return $packageDir } $sdkRepoRootPath = (Join-Path $PSScriptRoot .. .. ..) $sdkRepoRootPath = Resolve-Path $sdkRepoRootPath $sdkRepoRootPath = $sdkRepoRootPath -replace "\\", "/" $tspConfigPath = Join-Path $sdkRepoRootPath 'tspconfig.yaml' $tmpTspConfigPath = $tspConfigPath $repo = "" $specRepoRoot = "" $generateFromLocalTypeSpec = $false $isNewSdkProject = $false # remote url scenario # example url of tspconfig.yaml: https://github.com/Azure/azure-rest-api-specs-pr/blob/724ccc4d7ef7655c0b4d5c5ac4a5513f19bbef35/specification/containerservice/Fleet.Management/tspconfig.yaml if ($TypeSpecProjectDirectory -match '^https://github.com/(?<repo>[^/]*/azure-rest-api-specs(-pr)?)/blob/(?<commit>[0-9a-f]{40})/(?<path>.*)/tspconfig.yaml$') { try { $TypeSpecProjectDirectory = $TypeSpecProjectDirectory -replace "https://github.com/(.*)/(tree|blob)", "https://raw.githubusercontent.com/`$1" Invoke-WebRequest $TypeSpecProjectDirectory -OutFile $tspConfigPath -MaximumRetryCount 3 } catch { Write-Host "Failed to download '$TypeSpecProjectDirectory'" Write-Error $_.Exception.Message return } $repo = $Matches["repo"] $TypeSpecProjectDirectory = $Matches["path"] $CommitHash = $Matches["commit"] # TODO support the branch name in url then get the commithash from branch name } else { # local path scenario $tspConfigPath = Join-Path $TypeSpecProjectDirectory "tspconfig.yaml" if (!(Test-Path $tspConfigPath)) { Write-Error "Failed to find tspconfig.yaml in '$TypeSpecProjectDirectory'" exit 1 } $TypeSpecProjectDirectory = $TypeSpecProjectDirectory.Replace("\", "/") if ($TypeSpecProjectDirectory -match "(?<repoRoot>^.*)/(?<path>specification/.*)$") { $TypeSpecProjectDirectory = $Matches["path"] $specRepoRoot = $Matches["repoRoot"] } else { Write-Error "$TypeSpecProjectDirectory doesn't have 'specification' in path." exit 1 } if (!$CommitHash -or !$RepoUrl) { Write-Warning "Parameter of Commithash or RepoUrl are not provided along with the local path of tspconfig.yaml, trying to re-generate sdk code based on the local type specs." $generateFromLocalTypeSpec = $true } if ($RepoUrl) { if ($RepoUrl -match "^(https://github.com/|git@github.com:)(?<repo>[^/]*/azure-rest-api-specs(-pr)?).*") { $repo = $Matches["repo"] } else { Write-Error "Parameter 'RepoUrl' has incorrect value:$RepoUrl. It should be similar like 'https://github.com/Azure/azure-rest-api-specs'" exit 1 } } } $tspConfigYaml = Get-Content $tspConfigPath -Raw | ConvertFrom-Yaml # delete the tmporary tspconfig.yaml downloaded from github if (Test-Path $tmpTspConfigPath) { Remove-Item $tspConfigPath } $sdkProjectFolder = "" if ($generateFromLocalTypeSpec) { Write-Host "Generating sdk code based on local type specs at specRepoRoot: $specRepoRoot." $sdkProjectFolder = Get-TspLocationFolder $tspConfigYaml $sdkRepoRootPath $tspLocationYamlPath = Join-Path $sdkProjectFolder "tsp-location.yaml" if (!(Test-Path -Path $tspLocationYamlPath)) { # try to create tsp-location.yaml using HEAD commit of the local spec repo Write-Warning "Failed to find tsp-location.yaml in '$sdkProjectFolder'. Trying to create tsp-location.yaml using HEAD commit of the local spec repo then proceed the sdk generation based upon local typespecs at $specRepoRoot. Alternatively, please make sure to provide CommitHash and RepoUrl parameters when running this script." # set default repo to Azure/azure-rest-api-specs $repo = "Azure/azure-rest-api-specs" try { Push-Location $specRepoRoot $CommitHash = $(git rev-parse HEAD) $gitOriginUrl = (git remote get-url origin) if ($gitOriginUrl -and $gitOriginUrl -match '(.*)?github.com:(?<repo>[^/]*/azure-rest-api-specs(-pr)?)(.git)?') { $repo = $Matches["repo"] Write-Host "Found git origin repo: $repo" } else { Write-Warning "Failed to find git origin repo of the local spec repo at specRepoRoot: $specRepoRoot. Using default repo: $repo" } } catch { Write-Error "Failed to get HEAD commit or remote origin of the local spec repo at specRepoRoot: $specRepoRoot." exit 1 } finally { Pop-Location } $sdkProjectFolder = CreateUpdate-TspLocation $tspConfigYaml $TypeSpecProjectDirectory $CommitHash $repo $sdkRepoRootPath -isNewSdkProject ([ref]$isNewSdkProject) } } else { # call CreateUpdate-TspLocation function $sdkProjectFolder = CreateUpdate-TspLocation $tspConfigYaml $TypeSpecProjectDirectory $CommitHash $repo $sdkRepoRootPath -isNewSdkProject ([ref]$isNewSdkProject) } # checking skip switch, only skip when it's not a new sdk project as project scaffolding is supported by emitter if ($SkipSyncAndGenerate -and !$isNewSdkProject) { Write-Host "Skip calling TypeSpec-Project-Sync.ps1 and TypeSpec-Project-Generate.ps1." } else { # call TypeSpec-Project-Sync.ps1 $syncScript = Join-Path $PSScriptRoot TypeSpec-Project-Sync.ps1 Write-Host "Calling TypeSpec-Project-Sync.ps1" & $syncScript $sdkProjectFolder $specRepoRoot | Out-Null if ($LASTEXITCODE) { Write-Error "Failed to sync sdk project from $specRepoRoot to $sdkProjectFolder" exit $LASTEXITCODE } # call TypeSpec-Project-Generate.ps1 Write-Host "Calling TypeSpec-Project-Generate.ps1" $generateScript = Join-Path $PSScriptRoot TypeSpec-Project-Generate.ps1 & $generateScript $sdkProjectFolder | Out-Null if ($LASTEXITCODE) { Write-Error "Failed to generate sdk project at $sdkProjectFolder" exit $LASTEXITCODE } } return $sdkProjectFolder