From 6500a64a84258cd2709f595da67c4bdc639426f4 Mon Sep 17 00:00:00 2001 From: "azure-sdk-automation[bot]" <191533747+azure-sdk-automation[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 13:53:49 -0700 Subject: [PATCH] Sync eng/common directory with azure-sdk-tools for PR 16858 (#3442) Sync eng/common directory with azure-sdk-tools repository for Tools PR 16858 Co-authored-by: azure-sdk --- .../templates/jobs/apireview-hub-job-base.yml | 75 +++++++++++ .../create-apireview-hub-artifacts-base.yml | 118 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 eng/common/pipelines/templates/jobs/apireview-hub-job-base.yml create mode 100644 eng/common/pipelines/templates/steps/create-apireview-hub-artifacts-base.yml diff --git a/eng/common/pipelines/templates/jobs/apireview-hub-job-base.yml b/eng/common/pipelines/templates/jobs/apireview-hub-job-base.yml new file mode 100644 index 000000000..d89e11edd --- /dev/null +++ b/eng/common/pipelines/templates/jobs/apireview-hub-job-base.yml @@ -0,0 +1,75 @@ +# Base job wrapper for API Review Hub artifact creation. Language-specific job +# templates provide setup steps and the request handler provides orchestration steps. +parameters: + - name: jobName + type: string + default: CreateApiReviewArtifacts + - name: displayName + type: string + default: 'Create API review artifacts' + - name: poolName + type: string + default: 'azsdk-pool' + - name: imageOverride + type: string + default: 'ubuntu-24.04' + - name: variables + type: object + default: [] + - name: sourceRepositoryFullName + type: string + default: '' + - name: sourceCheckoutDir + type: string + default: '' + - name: toolingDir + type: string + default: '$(Pipeline.Workspace)/apireview/tooling' + - name: setupSteps + type: stepList + default: [] + - name: steps + type: stepList + default: [] + +jobs: +- job: ${{ parameters.jobName }} + displayName: ${{ parameters.displayName }} + + pool: + name: ${{ parameters.poolName }} + demands: ImageOverride -equals ${{ parameters.imageOverride }} + + variables: + - template: /eng/pipelines/templates/variables/globals.yml + - name: ApiReviewRepositoryFullName + value: ${{ parameters.sourceRepositoryFullName }} + - name: ApiReviewSourceDir + value: ${{ parameters.sourceCheckoutDir }} + - name: ApiReviewToolingDir + value: ${{ parameters.toolingDir }} + - ${{ each variable in parameters.variables }}: + - ${{ variable }} + + steps: + - ${{ if ne(parameters.sourceCheckoutDir, '') }}: + - bash: | + set -Eeuo pipefail + + source_repo="$SOURCE_CHECKOUT_DIR" + repository_full_name="$SOURCE_REPOSITORY_FULL_NAME" + + rm -rf "$source_repo" + mkdir -p "$(dirname "$source_repo")" + + echo "Cloning $repository_full_name into $source_repo" + git clone --filter=blob:none --no-checkout "https://github.com/$repository_full_name.git" "$source_repo" + env: + SOURCE_CHECKOUT_DIR: ${{ parameters.sourceCheckoutDir }} + SOURCE_REPOSITORY_FULL_NAME: ${{ parameters.sourceRepositoryFullName }} + displayName: 'Clone API review source repository' + + - ${{ parameters.setupSteps }} + + # These steps are assembled by the generic API Review Hub request pipeline. + - ${{ parameters.steps }} \ No newline at end of file diff --git a/eng/common/pipelines/templates/steps/create-apireview-hub-artifacts-base.yml b/eng/common/pipelines/templates/steps/create-apireview-hub-artifacts-base.yml new file mode 100644 index 000000000..6d3cedb86 --- /dev/null +++ b/eng/common/pipelines/templates/steps/create-apireview-hub-artifacts-base.yml @@ -0,0 +1,118 @@ +# Base artifact step for API Review Hub. Language-specific templates provide the +# generation steps and this template enforces the shared artifact contract. +parameters: + - name: requestMode + type: string + - name: operationId + type: string + - name: packageName + type: string + - name: ref + type: string + - name: kind + type: string + - name: outputDir + type: string + - name: workingDir + type: string + - name: sourceDir + type: string + - name: language + type: string + - name: repositoryFullName + type: string + - name: generationSteps + type: stepList + default: [] + +steps: + - pwsh: | + $ErrorActionPreference = 'Stop' + + New-Item -ItemType Directory -Force -Path $env:OUTPUT_DIR | Out-Null + New-Item -ItemType Directory -Force -Path $env:WORKING_DIR | Out-Null + New-Item -ItemType Directory -Force -Path (Join-Path $env:WORKING_DIR 'state') | Out-Null + env: + OUTPUT_DIR: ${{ parameters.outputDir }} + WORKING_DIR: ${{ parameters.workingDir }} + displayName: 'Prepare ${{ parameters.kind }} API review bundle directories' + + - bash: | + set -Eeuo pipefail + + source_repo="$SOURCE_DIR" + ref="$REF" + + if [ ! -d "$source_repo/.git" ]; then + echo "Expected API review source repository was not cloned at $source_repo" >&2 + exit 1 + fi + + # API Review Hub must provide a fully-qualified Git ref in the form refs/heads/ + # or refs/tags/. A bare "refs/tags" or "refs/heads" is not a valid remote ref. + if [[ -z "$ref" || ! "$ref" =~ ^refs/(heads|tags)/.+$ ]]; then + echo "Expected a fully-qualified git ref in the form refs/heads/ or refs/tags/, but received: '$ref'" >&2 + exit 1 + fi + + echo "Checking out $KIND API review source ref $ref in $source_repo" + git -C "$source_repo" fetch --depth=1 origin "$ref" + git -C "$source_repo" checkout --force FETCH_HEAD + git -C "$source_repo" clean -ffd + env: + SOURCE_DIR: ${{ parameters.sourceDir }} + REF: ${{ parameters.ref }} + KIND: ${{ parameters.kind }} + displayName: 'Checkout ${{ parameters.kind }} API review source' + + - ${{ parameters.generationSteps }} + + - pwsh: | + $ErrorActionPreference = 'Stop' + + $outputDir = $env:OUTPUT_DIR + $stateDir = Join-Path $env:WORKING_DIR 'state' + $apiMdPath = Join-Path $outputDir 'api.md' + $apiMetadataPath = Join-Path $outputDir 'api.metadata.yml' + $packageRelativePathPath = Join-Path $stateDir 'package-relative-path.txt' + $versionPath = Join-Path $stateDir 'version.txt' + if (!(Test-Path -Path $apiMdPath -PathType Leaf)) { + Write-Error "Expected api.md was not produced at $apiMdPath." + } + if (!(Test-Path -Path $apiMetadataPath -PathType Leaf)) { + Write-Error "Expected api.metadata.yml was not produced at $apiMetadataPath." + } + if (!(Test-Path -Path $packageRelativePathPath -PathType Leaf)) { + Write-Error "Expected package-relative-path.txt was not produced at $packageRelativePathPath." + } + if (!(Test-Path -Path $versionPath -PathType Leaf)) { + Write-Error "Expected version.txt was not produced at $versionPath." + } + + $packageRelativePath = Get-Content -Raw -Path $packageRelativePathPath + $version = Get-Content -Raw -Path $versionPath + + $metadata = [ordered]@{ + operationId = $env:OPERATION_ID + mode = $env:REQUEST_MODE + language = $env:LANGUAGE + repositoryFullName = $env:REPOSITORY_FULL_NAME + packageName = $env:PACKAGE_NAME + packageRelativePath = $packageRelativePath.Trim() + ref = $env:REF + version = $version.Trim() + kind = $env:KIND + } + $metadata | ConvertTo-Json -Depth 10 | Set-Content -Path (Join-Path $outputDir 'artifact-metadata.json') -Encoding utf8 + Get-Content -Path (Join-Path $outputDir 'artifact-metadata.json') + env: + OUTPUT_DIR: ${{ parameters.outputDir }} + WORKING_DIR: ${{ parameters.workingDir }} + OPERATION_ID: ${{ parameters.operationId }} + REQUEST_MODE: ${{ parameters.requestMode }} + LANGUAGE: ${{ parameters.language }} + REPOSITORY_FULL_NAME: ${{ parameters.repositoryFullName }} + PACKAGE_NAME: ${{ parameters.packageName }} + REF: ${{ parameters.ref }} + KIND: ${{ parameters.kind }} + displayName: 'Validate and write ${{ parameters.kind }} API review bundle metadata' \ No newline at end of file