Skip to content
Merged
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
78 changes: 60 additions & 18 deletions .azure-pipelines/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ trigger:
- support/v2
tags:
include:
- 'v*'
- 'v2.*'
pr:
branches:
include:
Expand Down Expand Up @@ -56,6 +56,20 @@ extends:
targetPath: '$(Build.ArtifactStagingDirectory)'
steps:

- pwsh: |
$ErrorActionPreference = 'Stop'
$version = ([xml](Get-Content -LiteralPath Directory.Build.props)).SelectSingleNode('/Project/PropertyGroup/Version').InnerText
if ($version -cnotmatch '^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Invalid OData project version: $version." }
$sourceBranch = $env:BUILD_SOURCEBRANCH
if ($sourceBranch.StartsWith('refs/tags/')) {
if ($sourceBranch -cnotmatch '^refs/tags/v2\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') {
throw "This pipeline only releases OData v2.* tags."
}
if ($sourceBranch -cne "refs/tags/v$version") { throw "OData tag must exactly match Directory.Build.props version." }
}
Write-Host "##vso[task.setvariable variable=ODataVersion]$version"
displayName: 'Verify OData component tag and project version'

- task: UseDotNet@2
displayName: 'Use .NET 6' # needed for ESRP signing
inputs:
Expand Down Expand Up @@ -174,8 +188,13 @@ extends:
displayName: 'pack'
inputs:
command: pack
projects: src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
arguments: '-o $(Build.ArtifactStagingDirectory) --configuration $(BuildConfiguration) --no-build --include-symbols --include-source /p:SymbolPackageFormat=snupkg'
packagesToPack: src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
configuration: '$(BuildConfiguration)'
packDirectory: '$(Build.ArtifactStagingDirectory)'
nobuild: true
includesymbols: true
includesource: true
buildProperties: 'SymbolPackageFormat=snupkg'

- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: 'ESRP CodeSigning Nuget Packages'
Expand All @@ -187,7 +206,7 @@ extends:
AuthAKVName: 'akv-prod-eastus'
AuthCertName: 'ReferenceLibraryPrivateCert'
AuthSignCertName: 'ReferencePackagePublisherCertificate'
Pattern: '*.nupkg'
Pattern: 'Microsoft.OpenApi.OData.$(ODataVersion).nupkg'
signConfigType: inlineSignParams
inlineOperation: |
[
Expand All @@ -212,7 +231,7 @@ extends:
PendingAnalysisWaitTimeoutMinutes: '5'

- stage: deploy
condition: and(contains(variables['build.sourceBranch'], 'refs/tags/v'), succeeded())
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v2.'))
dependsOn: build
jobs:
- deployment: deploy
Expand All @@ -230,10 +249,26 @@ extends:
pool:
vmImage: ubuntu-latest
steps:
- pwsh: |
$ErrorActionPreference = 'Stop'
$sourceBranch = $env:BUILD_SOURCEBRANCH
if ($sourceBranch -cnotmatch '^refs/tags/v2\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Expected an OData v2.* release tag." }
$version = $sourceBranch.Substring('refs/tags/v'.Length)
$packages = @(Get-ChildItem -LiteralPath '$(Pipeline.Workspace)' -Filter '*.nupkg' -File -Recurse)
if ($packages.Count -ne 1 -or $packages[0].Name -cne "Microsoft.OpenApi.OData.$version.nupkg") {
throw "Expected only the exact OData package matching the triggering tag."
}
$symbols = Join-Path $packages[0].DirectoryName "Microsoft.OpenApi.OData.$version.snupkg"
if (-not (Test-Path -LiteralPath $symbols -PathType Leaf)) {
throw "Missing exact OData symbols package for $version."
}
Write-Host "##vso[task.setvariable variable=ODataReleaseVersion]$version"
Write-Host "##vso[task.setvariable variable=ODataPackagePath]$($packages[0].FullName)"
displayName: 'Verify tagged OData package and symbols'
- task: 1ES.PublishNuget@1
displayName: 'NuGet push'
inputs:
packagesToPush: '$(Pipeline.Workspace)/Microsoft.OpenApi.OData.*.nupkg'
packagesToPush: '$(ODataPackagePath)'
nuGetFeedType: external
publishFeedCredentials: 'OpenAPI Nuget Connection'
packageParentPath: '$(Pipeline.Workspace)'
Expand All @@ -255,23 +290,30 @@ extends:
vmImage: ubuntu-latest
steps:
- pwsh: |
$artifacts = @(Get-ChildItem -Path $(Pipeline.Workspace) -Filter Microsoft.OpenApi.OData.*.nupkg -Recurse)
if ($artifacts.Count -ne 1) { throw "Expected exactly one OData package; found $($artifacts.Count)." }
$artifactName = $artifacts[0]
$artifactVersion= $artifactName.Name -replace "Microsoft.OpenApi.OData.", "" -replace ".nupkg", ""
#Set Variable $artifactName and $artifactVersion
Write-Host "##vso[task.setvariable variable=artifactVersion; isSecret=false;]$artifactVersion"
echo "$artifactVersion"
displayName: 'Fetch Artifact Name'
$ErrorActionPreference = 'Stop'
$sourceBranch = $env:BUILD_SOURCEBRANCH
if ($sourceBranch -cnotmatch '^refs/tags/v2\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Expected an OData v2.* release tag." }
$version = $sourceBranch.Substring('refs/tags/v'.Length)
$packages = @(Get-ChildItem -LiteralPath '$(Pipeline.Workspace)' -Filter '*.nupkg' -File -Recurse)
if ($packages.Count -ne 1 -or $packages[0].Name -cne "Microsoft.OpenApi.OData.$version.nupkg") {
throw "Expected only the exact OData package matching the triggering tag."
}
$symbols = Join-Path $packages[0].DirectoryName "Microsoft.OpenApi.OData.$version.snupkg"
if (-not (Test-Path -LiteralPath $symbols -PathType Leaf)) {
throw "Missing exact OData symbols package for $version."
}
Write-Host "##vso[task.setvariable variable=ODataReleaseVersion]$version"
Write-Host "##vso[task.setvariable variable=ODataPackagePath]$($packages[0].FullName)"
displayName: 'Verify tagged OData release artifact'
- task: GitHubRelease@1
displayName: 'GitHub release'
condition: succeededOrFailed()
condition: succeeded()
inputs:
gitHubConnection: 'Github-MaggieKimani1'
action: edit
tagSource: userSpecifiedTag
tag: 'v$(artifactVersion)'
title: 'v$(artifactVersion)'
tag: 'v$(ODataReleaseVersion)'
title: 'v$(ODataReleaseVersion)'
releaseNotesSource: inline
assets: '$(Pipeline.Workspace)\Microsoft.OpenApi.OData.*.nupkg'
assets: '$(ODataPackagePath)'
addChangeLog: false
38 changes: 27 additions & 11 deletions .azure-pipelines/hidi-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ extends:
artifactName: HidiDockerContext
targetPath: '$(Build.ArtifactStagingDirectory)\HidiDockerContext'
steps:
- pwsh: |
$ErrorActionPreference = 'Stop'
$version = ([xml](Get-Content -LiteralPath src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj)).SelectSingleNode('/Project/PropertyGroup/Version').InnerText
if ($version -cnotmatch '^2\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Expected a hidi 2.x version, got $version." }
$sourceBranch = $env:BUILD_SOURCEBRANCH
if ($sourceBranch.StartsWith('refs/tags/') -and $sourceBranch -cne "refs/tags/hidi-v$version") {
throw "This pipeline only releases hidi-v2.* tags exactly matching the hidi project version."
}
Write-Host "##vso[task.setvariable variable=HidiVersion]$version"
displayName: Verify Hidi component tag and project version
- task: CopyFiles@2
displayName: Stage public-only hidi Docker context
inputs:
Expand Down Expand Up @@ -103,12 +113,6 @@ extends:
'@ | Set-Content -Path '$(Build.SourcesDirectory)\nuget.config'
displayName: Configure approved NuGet feed
- pwsh: |
$version = ([xml](Get-Content src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj)).Project.PropertyGroup.Version
if ($version -notmatch '^2\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Expected a hidi 2.x version, got $version." }
if ('$(Build.SourceBranch)' -like 'refs/tags/*' -and '$(Build.SourceBranch)' -ne "refs/tags/hidi-v$version") {
throw "Hidi tag must exactly match the hidi project version."
}
Write-Host "##vso[task.setvariable variable=HidiVersion]$version"
dotnet build src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj -c $(buildConfiguration) -p:GeneratePackageOnBuild=false
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
dotnet run --project test\Microsoft.OpenApi.Hidi.Tests\Microsoft.OpenApi.Hidi.Tests.csproj -c $(buildConfiguration) -- --minimum-expected-tests 1
Expand Down Expand Up @@ -226,12 +230,22 @@ extends:
deploy:
steps:
- pwsh: |
$tag = '$(Build.SourceBranch)' -replace '^refs/tags/hidi-v', ''
$ErrorActionPreference = 'Stop'
$sourceBranch = $env:BUILD_SOURCEBRANCH
if ($sourceBranch -cnotmatch '^refs/tags/hidi-v2\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Expected a Hidi hidi-v2.* release tag." }
$tag = $sourceBranch.Substring('refs/tags/hidi-v'.Length)
if ([version]($tag -split '-')[0] -le [version]'2.12.2') { throw "Never republish the source migration baseline or an older hidi version." }
$package = "$(Pipeline.Workspace)\hidi\Microsoft.OpenApi.Hidi.$tag.nupkg"
if (-not (Test-Path $package)) { throw "Missing exact hidi package: $package" }
if (-not (Test-Path -LiteralPath $package -PathType Leaf)) { throw "Missing exact hidi package: $package" }
$symbols = "$(Pipeline.Workspace)\hidi\Microsoft.OpenApi.Hidi.$tag.snupkg"
if (-not (Test-Path $symbols)) { throw "Missing exact hidi symbols: $symbols" }
if (-not (Test-Path -LiteralPath $symbols -PathType Leaf)) { throw "Missing exact hidi symbols: $symbols" }
$packages = @(Get-ChildItem -LiteralPath '$(Pipeline.Workspace)\hidi' -Filter '*.nupkg' -File)
if ($packages.Count -ne 1 -or $packages[0].Name -cne "Microsoft.OpenApi.Hidi.$tag.nupkg") {
throw "Expected only the exact Hidi package matching the triggering tag."
}
foreach ($artifact in @("$(Pipeline.Workspace)\hidi\Microsoft.OpenApi.Hidi.exe", "$(Pipeline.Workspace)\hidi\hidi-win-x64-$tag.zip")) {
if (-not (Test-Path -LiteralPath $artifact -PathType Leaf)) { throw "Missing exact Hidi executable artifact: $artifact" }
}
Write-Host "##vso[task.setvariable variable=HidiReleaseVersion]$tag"
displayName: Verify new hidi release version and exact package
- task: PowerShell@2
Expand Down Expand Up @@ -303,8 +317,10 @@ extends:
vmImage: ubuntu-latest
steps:
- pwsh: |
$version = ([xml](Get-Content -LiteralPath '$(Pipeline.Workspace)/HidiDockerContext/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj')).Project.PropertyGroup.Version
if ('$(Build.SourceBranch)' -ne "refs/tags/hidi-v$version") { throw "Hidi tag does not match project version." }
$ErrorActionPreference = 'Stop'
$version = ([xml](Get-Content -LiteralPath '$(Pipeline.Workspace)/HidiDockerContext/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj')).SelectSingleNode('/Project/PropertyGroup/Version').InnerText
if ($version -cnotmatch '^2\.\d+\.\d+(-[0-9A-Za-z.-]+)?$') { throw "Expected a hidi 2.x container version, got $version." }
if ($env:BUILD_SOURCEBRANCH -cne "refs/tags/hidi-v$version") { throw "Hidi tag does not match project version." }
if ([version]($version -split '-')[0] -le [version]'2.12.2') { throw "Do not republish the migration baseline or an older hidi version." }
Write-Host "##vso[task.setvariable variable=HidiReleaseVersion]$version"
displayName: Read independent hidi version
Expand Down
22 changes: 0 additions & 22 deletions .github/workflows/release-please-gha.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,3 @@ jobs:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
target-branch: ${{ github.ref_name }}

release-please-hidi:
# Enable only after the destination PR lands and source publishing is cut over.
if: ${{ false }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ vars.RELEASE_PLEASE_TOKEN_PROVIDER_APP_ID }}
private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }}
- name: Release Please (independent hidi version)
uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4
with:
token: ${{ steps.app-token.outputs.token }}
config-file: hidi-release-please-config.json
manifest-file: .hidi-release-please-manifest.json
target-branch: ${{ github.ref_name }}
3 changes: 0 additions & 3 deletions .hidi-release-please-manifest.json

This file was deleted.

3 changes: 2 additions & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
".": "2.2.1"
".": "2.2.1",
"src/Microsoft.OpenApi.Hidi": "2.12.2"
}
44 changes: 40 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,47 @@ public-only signing key preserves assembly identity and friend-assembly access;
never add the source repository's private strong-name key. Production signing
is handled only by the official Azure pipeline.

Hidi's version is in its own project and `.hidi-release-please-manifest.json`.
Hidi's version is in its own project and the
`src/Microsoft.OpenApi.Hidi` entry in `.release-please-manifest.json`.
Its `hidi-v2.*` tags must not trigger OData publishing. Version 2.12.2 is the
already-published migration baseline, not a new release. Hidi release automation
and publishing remain disabled until source cutover. History-import migration
PRs must be merged with a merge commit, never squash or rebase.
already-published migration baseline, not a new release. Production publishing
remains disabled until source cutover. History-import migration PRs must be
merged with a merge commit, never squash or rebase.

### Independent automated versions

The standard Release Please action uses one `release-please-config.json` and
one `.release-please-manifest.json` with two components: root OData (`.`) and
Hidi (`src/Microsoft.OpenApi.Hidi`). Their versions advance independently in
the generated release PRs. The stock `separate-pull-requests` option preserves
OData's existing release branch and avoids the stock engine's componentless-root
parsing issue with combined release PRs.

Hidi source changes update its project `<Version>` and local `CHANGELOG.md`;
the root component excludes Hidi source and tests. OData changes update
`Directory.Build.props` and the root `CHANGELOG.md`, without changing Hidi.
Hidi keeps `hidi-v2.*` tags; OData keeps componentless `v2.*` tags. Hidi's
published OpenAPI dependency versions are not changed by its version updater.

Routing follows component paths, not commit scopes. Hidi-only tests do not
create a release by themselves, and root-level distribution/helper files remain
root-owned under this standard configuration. Production package, executable,
and container publishing remains gated in the official Azure pipeline.

### Component-tagged Azure releases

On `support/v2`, `.azure-pipelines/ci-build.yml` releases only the OData package
and attaches only its artifact for `v2.*` tags.
`.azure-pipelines/hidi-release.yml` handles only `hidi-v2.*` tags for Hidi's
NuGet package, Windows executable/ZIP, and container. Hidi publishing stays
disabled until the protected cutover; this routing does not enable it.

Tag runs must exactly match the component's project version before staging
artifacts. Release jobs require the exact tag-derived package and symbols;
Hidi also requires its executable/ZIP or matching Docker-context version.
Wrong-component, malformed, other-major, or version-mismatched manually selected
tags fail validation instead of publishing. Ordinary branch/PR builds still
validate both projects as before, without running tag-only release stages.

OpenAPI.net.OData is open to contributions. There are a couple of different recommended paths to get contributions into the released version of this library.

Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,12 @@ tests requires the .NET 10 SDK. Existing OData tests still use .NET 8 and VSTest
Hidi's filtered history was imported with a merge, not squashed. **Merge this
migration PR using a merge commit, not squash or rebase**, so the canonical
imported commits can also be retained by the later main-branch migration.
Destination hidi release and production publishing are disabled until source
cutover; OpenAPI.NET remains the publisher in the meantime.
The standard Release Please config and manifest track Hidi and OData as separate
components on `support/v2`, updating their project versions and changelogs
independently. Production publishing remains disabled until source cutover;
OpenAPI.NET remains the package publisher in the meantime.
See [independent automated versions](CONTRIBUTING.md#independent-automated-versions)
for component paths and version-file ownership.

The gated hidi NuGet release uses `EsrpRelease@14`, staging only the exact
`Microsoft.OpenApi.Hidi` package and its `.snupkg` symbols from the Hidi build
Expand Down
37 changes: 0 additions & 37 deletions hidi-release-please-config.json

This file was deleted.

Loading
Loading