Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 72 additions & 16 deletions eng/common/pipelines/templates/archetype-typespec-emitter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,56 @@ extends:
$sourceBranch = '$(Build.SourceBranch)'
$buildReason = '$(Build.Reason)'
$buildNumber = '$(Build.BuildNumber)'
$emitterPackagePath = '${{ parameters.EmitterPackagePath }}'

# Create emitter identifier from package path for disambiguation
$emitterIdentifier = ""
if (-not [string]::IsNullOrWhiteSpace($emitterPackagePath)) {
# Resolve emitterPackagePath to absolute path (it's relative to repo root)
# EmitterPackagePath is a directory, so append package.json
$absoluteEmitterPackagePath = Join-Path '$(Build.SourcesDirectory)' $emitterPackagePath
$packageJsonPath = Join-Path $absoluteEmitterPackagePath 'package.json'

# Read the package name from package.json
if (Test-Path $packageJsonPath) {
try {
$packageJson = Get-Content $packageJsonPath -Raw | ConvertFrom-Json
if ($packageJson.name) {
$emitterIdentifier = $packageJson.name
}
} catch {
Write-Host "Warning: Could not read package name from $packageJsonPath"
}
}

# If we still don't have an identifier, fall back to filename
if ([string]::IsNullOrWhiteSpace($emitterIdentifier)) {
Write-Host "Warning: Could not read emitter name from package.json, falling back to package path"
$emitterIdentifier = [System.IO.Path]::GetFileNameWithoutExtension($emitterPackagePath)
}

# Clean up the identifier: remove @ prefix, replace invalid chars
$emitterIdentifier = $emitterIdentifier -replace '^@', ''
$emitterIdentifier = $emitterIdentifier -replace '[^a-zA-Z0-9\-_/]', '-'
$emitterIdentifier = $emitterIdentifier.Trim('-').ToLower()

if (-not [string]::IsNullOrWhiteSpace($emitterIdentifier)) {
$emitterIdentifier = "-$emitterIdentifier"
}
}

if ($buildReason -eq 'Schedule') {
$branchName = 'validate-typespec-scheduled'
$branchName = "validate-typespec-scheduled$emitterIdentifier"
} elseif ($sourceBranch -match "^refs/pull/(\d+)/(head|merge)$") {
$branchName = "validate-typespec-pr-$($Matches[1])"
$branchName = "validate-typespec-pr-$($Matches[1])$emitterIdentifier"
} else {
$branchName = "validate-typespec-$buildNumber"
$branchName = "validate-typespec-$buildNumber$emitterIdentifier"
}

Write-Host "Setting variable 'branchName' to '$branchName'"
Write-Host "##vso[task.setvariable variable=branchName;isOutput=true]$branchName"
Write-Host "Setting variable 'emitterIdentifier' to '$emitterIdentifier'"
Write-Host "##vso[task.setvariable variable=emitterIdentifier;isOutput=true]$emitterIdentifier"
displayName: Set branch name
name: set_branch_name

Expand Down Expand Up @@ -259,27 +298,34 @@ extends:
displayName: Download pipeline artifacts

- pwsh: |
npm install -g @azure-tools/typespec-client-generator-cli@latest
npm ci
displayName: Install tsp-client
workingDirectory: $(Build.SourcesDirectory)/eng/common/tsp-client

- pwsh: |
# Resolve EmitterPackageJsonOutputPath to absolute path if it's relative
$emitterPath = '${{ parameters.EmitterPackageJsonOutputPath }}'
if (-not [System.IO.Path]::IsPathRooted($emitterPath)) {
$emitterPath = Join-Path '$(Build.SourcesDirectory)' $emitterPath
}

Write-Host "Overrides location: $(buildArtifactsPath)/packages/overrides.json"
Write-Host "Resolved emitter package path: $emitterPath"

if (Test-Path -Path '$(buildArtifactsPath)/packages/overrides.json') {
Write-Host "Using overrides.json to generate emitter-package.json"
tsp-client generate-config-files `
--package-json '$(buildArtifactsPath)/lock-files/package.json' `
--emitter-package-json-path '${{ parameters.EmitterPackageJsonOutputPath }}' `
--overrides '$(buildArtifactsPath)/packages/overrides.json'
npm exec --no -- tsp-client generate-config-files `
--package-json '$(buildArtifactsPath)/lock-files/package.json' `
--emitter-package-json-path "$emitterPath" `
--overrides '$(buildArtifactsPath)/packages/overrides.json'
} else {
Write-Host "No overrides.json found. Running tsp-client without overrides."

tsp-client generate-config-files `
--package-json '$(buildArtifactsPath)/lock-files/package.json' `
--emitter-package-json-path '${{ parameters.EmitterPackageJsonOutputPath }}'
npm exec --no -- tsp-client generate-config-files `
--package-json '$(buildArtifactsPath)/lock-files/package.json' `
--emitter-package-json-path "$emitterPath"
}
displayName: Generate emitter-package.json and emitter-package-lock files
workingDirectory: $(Build.SourcesDirectory)
workingDirectory: $(Build.SourcesDirectory)/eng/common/tsp-client

- ${{ parameters.InitializationSteps }}

Expand Down Expand Up @@ -361,15 +407,18 @@ extends:
displayName: Create PR
dependsOn:
- Generate
condition: succeededOrFailed()
variables:
generateJobResult: $[dependencies.Generate.result]
emitterVersion: $[stageDependencies.Build.Build.outputs['initialize.emitterVersion']]
emitterIdentifier: $[stageDependencies.Build.Build.outputs['set_branch_name.emitterIdentifier']]
steps:
- template: /eng/common/pipelines/templates/steps/sparse-checkout.yml

- pwsh: |
$generateJobResult = '$(generateJobResult)'
$emitterVersion = '$(emitterVersion)'
$emitterIdentifier = '$(emitterIdentifier)'
$collectionUri = '$(System.CollectionUri)'
$project = '$(System.TeamProject)'
$definitionName = '$(Build.DefinitionName)'
Expand All @@ -381,6 +430,12 @@ extends:
$buildNumber = '$(Build.BuildNumber)'
$preRelease = '${{ parameters.BuildPrereleaseVersion }}' -eq 'true'

# Use emitterIdentifier for PR title (remove leading dash if present)
$emitterName = "TypeSpec emitter"
if (-not [string]::IsNullOrWhiteSpace($emitterIdentifier)) {
$emitterName = $emitterIdentifier.TrimStart('-')
}

$prBody = "Generated by $definitionName build [$buildNumber]($collectionUri/$project/_build/results?buildId=$buildId)<br/>"

if ($sourceBranch -match "^refs/heads/(.+)$") {
Expand All @@ -397,9 +452,9 @@ extends:
$prTitle = "Scheduled code regeneration test"
} else {
if ($preRelease) {
$prTitle = "Update TypeSpec emitter version to prerelease $emitterVersion"
$prTitle = "Update $emitterName version to prerelease $emitterVersion"
} else {
$prTitle = "Update TypeSpec emitter version to $emitterVersion"
$prTitle = "Update $emitterName version to $emitterVersion"
}

if ($generateJobResult -ne 'Succeeded') {
Expand All @@ -424,7 +479,8 @@ extends:
Write-Error "Build.Repository.Name not in the expected {Owner}/{Name} format"
}

$openAsDraft = -not ($reason -eq 'IndividualCI' -and $sourceBranch -eq 'refs/heads/main')
# Open PR as draft if generation failed, or if it's not an IndividualCI build from main
$openAsDraft = ($generateJobResult -ne 'Succeeded') -or (-not ($reason -eq 'IndividualCI' -and $sourceBranch -eq 'refs/heads/main'))
Write-Host "Setting OpenAsDraftBool = $openAsDraft"
Write-Host "##vso[task.setvariable variable=OpenAsDraft]$openAsDraft"
if ($openAsDraft) {
Expand Down
52 changes: 36 additions & 16 deletions eng/common/pipelines/templates/steps/create-apireview.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,47 @@
parameters:
ArtifactPath: $(Build.ArtifactStagingDirectory)
Artifacts: []
ConfigFileDir: $(Build.ArtifactStagingDirectory)/PackageInfo
MarkPackageAsShipped: false
GenerateApiReviewForManualOnly: false
ArtifactName: 'packages'
PackageName: ''
SourceRootPath: $(Build.SourcesDirectory)
- name: ArtifactPath
type: string
default: $(Build.ArtifactStagingDirectory)
- name: Artifacts
type: object
default: []
- name: ConfigFileDir
type: string
default: $(Build.ArtifactStagingDirectory)/PackageInfo
- name: MarkPackageAsShipped
type: boolean
default: false
- name: GenerateApiReviewForManualOnly
type: boolean
default: false
- name: ArtifactName
type: string
default: 'packages'
- name: PackageName
type: string
default: ''
- name: SourceRootPath
type: string
default: $(Build.SourcesDirectory)
- name: PackageInfoFiles
type: object
default: []

steps:
# ideally this should be done as initial step of a job in caller template
# We can remove this step later once it is added in caller
- template: /eng/common/pipelines/templates/steps/set-default-branch.yml
parameters:
WorkingDirectory: ${{ parameters.SourceRootPath }}

# Automatic API review is generated for a package when pipeline runs irrespective of how pipeline gets triggered.
# Below condition ensures that API review is generated only for manual pipeline runs when flag GenerateApiReviewForManualOnly is set to true.
# Below condition ensures that API review is generated only for manual pipeline runs when flag GenerateApiReviewForManualOnly is set to true.
- ${{ if or(ne(parameters.GenerateApiReviewForManualOnly, true), eq(variables['Build.Reason'], 'Manual')) }}:
# ideally this should be done as initial step of a job in caller template
# We can remove this step later once it is added in caller
- template: /eng/common/pipelines/templates/steps/set-default-branch.yml
parameters:
WorkingDirectory: ${{ parameters.SourceRootPath }}

- task: Powershell@2
inputs:
filePath: ${{ parameters.SourceRootPath }}/eng/common/scripts/Create-APIReview.ps1
arguments: >
-PackageInfoFiles ('${{ convertToJson(parameters.PackageInfoFiles) }}' | ConvertFrom-Json -NoEnumerate)
-ArtifactList ('${{ convertToJson(parameters.Artifacts) }}' | ConvertFrom-Json | Select-Object Name)
-ArtifactPath '${{parameters.ArtifactPath}}'
-ArtifactName ${{ parameters.ArtifactName }}
Expand All @@ -31,7 +51,7 @@ steps:
-DefaultBranch '$(DefaultBranch)'
-ConfigFileDir '${{parameters.ConfigFileDir}}'
-BuildId '$(Build.BuildId)'
-RepoName '$(Build.Repository.Name)'
-RepoName '$(Build.Repository.Name)'
-MarkPackageAsShipped $${{parameters.MarkPackageAsShipped}}
pwsh: true
displayName: Create API Review
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ steps:
$apiChangeDetectRequestUrl = "https://apiview.dev/api/PullRequests/CreateAPIRevisionIfAPIHasChanges"
echo "##vso[task.setvariable variable=ApiChangeDetectRequestUrl]$apiChangeDetectRequestUrl"
displayName: "Set API change detect request URL"
condition: and(succeeded(), ${{ parameters.Condition}}, eq(variables['ApiChangeDetectRequestUrl'], ''))
condition: and(succeededOrFailed(), ${{ parameters.Condition}}, eq(variables['ApiChangeDetectRequestUrl'], ''))

- task: Powershell@2
inputs:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
parameters:
PackageName: ''
PackageNames: ''
ServiceDirectory: ''
TagSeparator: '_'
TestPipeline: false
- name: PackageName
type: string
default: ''
- name: PackageNames
type: string
default: ''
- name: ServiceDirectory
type: string
default: ''
- name: TagSeparator
type: string
default: '_'
- name: TestPipeline
type: boolean
default: false
- name: ArtifactsJson
type: string
default: ''

steps:
- ${{ if eq(parameters.TestPipeline, 'true') }}:
- ${{ if eq(parameters.TestPipeline, true) }}:
- task: PowerShell@2
displayName: Prep template pipeline for release
condition: and(succeeded(), ne(variables['Skip.SetTestPipelineVersion'], 'true'))
Expand All @@ -18,4 +31,5 @@ steps:
-PackageNames '${{ coalesce(parameters.PackageName, parameters.PackageNames) }}'
-ServiceDirectory '${{ parameters.ServiceDirectory }}'
-TagSeparator '${{ parameters.TagSeparator }}'
-ArtifactsJson '${{ parameters.ArtifactsJson }}'
pwsh: true
Loading
Loading