1+ # Copyright (c) Microsoft Corporation. All rights reserved.
2+ # Licensed under the MIT License.
3+
4+ name : $(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)
5+
6+ parameters :
7+ - name : BuildAgent
8+ default : 1es-windows-ps-compute-m
9+ displayName : Build Agent
10+ - name : PackageVersion
11+ type : string
12+ default : 3.0.0
13+ displayName : Package version
14+ - name : Sign
15+ type : boolean
16+ default : true
17+ - name : Publish
18+ type : boolean
19+ default : false
20+ - name : InternalFeed
21+ type : string
22+ # The feed is PROJECT-scoped (dev.azure.com/microsoftgraph/Graph Developer Experiences/
23+ # _artifacts/feed/MSGraph_PowerShell_V3_Build), so publishVstsFeed needs the project
24+ # qualifier - a bare feed name only resolves for organization-scoped feeds.
25+ default : Graph Developer Experiences/MSGraph_PowerShell_V3_Build
26+ displayName : Internal NuGet feed
27+
28+ variables :
29+ BuildAgent : ${{ parameters.BuildAgent }}
30+ WrapperConfiguration : Release
31+ WrapperPrerelease : alpha$(Build.BuildId)
32+
33+ trigger : none
34+ pr : none
35+
36+ resources :
37+ repositories :
38+ - repository : 1ESPipelineTemplates
39+ type : git
40+ name : 1ESPipelineTemplates/1ESPipelineTemplates
41+ ref : refs/tags/release
42+
43+ extends :
44+ template : v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates
45+ parameters :
46+ pool : $(BuildAgent)
47+ settings :
48+ networkIsolationPolicy : Permissive
49+ sdl :
50+ binskim :
51+ enabled : false
52+ justificationForDisabling : " Matches sdk-release.yml; BinSkim currently blocks internal-feed publishing."
53+ credscan :
54+ suppressionsFile : $(Build.SourcesDirectory)/.azure-pipelines/config/credscan/credscan-suppressions.json
55+ policheck :
56+ exclusionFile : $(Build.SourcesDirectory)/.azure-pipelines/config/policheck/policheck-exclusions.xml
57+ customBuildTags :
58+ - ES365AIMigrationTooling
59+ stages :
60+ - stage : Build
61+ displayName : Build wrapper modules
62+ jobs :
63+ - job : Wrapper_Build
64+ displayName : Generate, build, pack, and sign wrapper modules
65+ timeoutInMinutes : 840
66+ templateContext :
67+ outputs :
68+ - output : pipelineArtifact
69+ displayName : Publish wrapper module artifacts
70+ targetPath : $(Build.ArtifactStagingDirectory)
71+ artifactName : drop
72+ publishLocation : Container
73+ steps :
74+ - script : git submodule update --init --recursive
75+ displayName : Initialize submodules
76+
77+ # Deliberately NOT install-tools.yml: that template is the AutoRest toolchain - Node,
78+ # the private npm feed, AutoRest, Rush and a full rush rebuild - none of which this
79+ # pipeline uses. The wrapper modules compile from committed sources, so the whole
80+ # toolchain is the .NET SDK, feed auth for restore, and the kiota CLI.
81+ - task : UseDotNet@2
82+ displayName : Use .NET SDK 10
83+ retryCountOnTaskFailure : 2
84+ inputs :
85+ version : 10.x
86+ - task : NuGetAuthenticate@1
87+ # Under 1ES network isolation api.nuget.org is not reliably reachable, so every restore
88+ # on this pipeline - the kiota tool below and the module build after it - resolves
89+ # through the team's own feed first, whose upstream proxies nuget.org. The config is
90+ # written at the sources root so dotnet picks it up everywhere; NuGetAuthenticate above
91+ # supplies the credentials.
92+ - task : PowerShell@2
93+ displayName : Route NuGet through the internal feed
94+ inputs :
95+ targetType : inline
96+ pwsh : true
97+ script : |
98+ $cfg = @'
99+ <?xml version="1.0" encoding="utf-8"?>
100+ <configuration>
101+ <packageSources>
102+ <clear />
103+ <add key="MSGraphV3" value="https://pkgs.dev.azure.com/microsoftgraph/Graph%20Developer%20Experiences/_packaging/MSGraph_PowerShell_V3_Build/nuget/v3/index.json" />
104+ </packageSources>
105+ </configuration>
106+ '@
107+ Set-Content -Path '$(Build.SourcesDirectory)/nuget.config' -Value $cfg -Encoding utf8
108+ Write-Host "wrote $(Build.SourcesDirectory)/nuget.config"
109+ # Build-WrapperModule.ps1 refuses to run without kiota on PATH even under -SkipKiota
110+ # (the guard is unconditional), and future -Generate runs need it anyway.
111+ - task : PowerShell@2
112+ displayName : Install kiota CLI
113+ retryCountOnTaskFailure : 2
114+ inputs :
115+ targetType : inline
116+ pwsh : true
117+ workingDirectory : $(Build.SourcesDirectory)
118+ script : |
119+ dotnet tool install --global Microsoft.OpenApi.Kiota --configfile '$(Build.SourcesDirectory)/nuget.config' --ignore-failed-sources
120+ if ($LASTEXITCODE -ne 0) { throw "kiota install failed with exit code $LASTEXITCODE" }
121+ Write-Host "##vso[task.prependpath]$env:USERPROFILE\.dotnet\tools"
122+ - template : .azure-pipelines/common-templates/security-pre-checks.yml@self
123+
124+ # Version and prerelease go to the script directly (-ModuleVersion/-Prerelease); the
125+ # script owns package identity. Nothing here edits ModuleMetadata.json - that file
126+ # belongs to the v2 release train.
127+ - task : PowerShell@2
128+ displayName : Build and pack wrapper modules
129+ inputs :
130+ targetType : inline
131+ pwsh : true
132+ script : |
133+ $params = @{
134+ ApiVersion = 'v1.0'
135+ Configuration = '$(WrapperConfiguration)'
136+ ArtifactsLocation = '$(Build.ArtifactStagingDirectory)'
137+ ModuleVersion = '${{ parameters.PackageVersion }}'
138+ Prerelease = '$(WrapperPrerelease)'
139+ # Deliberately NOT -SkipKiota: the pipeline runs the whole chain - kiota client
140+ # generation from the committed OpenAPI docs, wrapper generation on top, then
141+ # compile - so a change in any step is built and tested end to end, and the run
142+ # can never fail on committed clients lagging the docs. Clients are still
143+ # committed to the repo for reviewable diffs and clean local checkouts.
144+ Pack = $true
145+ }
146+ & '$(Build.SourcesDirectory)/tools/Build-WrapperModule.ps1' @params
147+ if ($LASTEXITCODE -ne 0) { throw "Wrapper build failed with exit code $LASTEXITCODE." }
148+
149+ - task : PowerShell@2
150+ displayName : Verify wrapper packages were produced
151+ inputs :
152+ targetType : inline
153+ pwsh : true
154+ script : |
155+ $packages = @(Get-ChildItem '$(Build.ArtifactStagingDirectory)' -Recurse -Filter 'Microsoft.Graph.Wrapper.*.nupkg')
156+ Write-Host "Wrapper packages produced: $($packages.Count)"
157+ $packages | ForEach-Object { Write-Host " $($_.FullName)" }
158+ if ($packages.Count -eq 0) { throw 'No wrapper packages were produced.' }
159+
160+ - template : .azure-pipelines/common-templates/guardian-analyzer.yml@self
161+
162+ - ${{ if eq(parameters.Sign, true) }} :
163+ - template : .azure-pipelines/common-templates/esrp/codesign-nuget.yml@self
164+ parameters :
165+ FolderPath : $(Build.ArtifactStagingDirectory)
166+ Pattern : Microsoft.Graph.Wrapper.*.nupkg
167+
168+ - template : .azure-pipelines/common-templates/security-post-checks.yml@self
169+
170+ - ${{ if eq(parameters.Publish, true) }} :
171+ - stage : Deploy_to_Internal_Feed
172+ displayName : Deploy wrapper packages to internal feed
173+ dependsOn : Build
174+ jobs :
175+ - deployment : DeployToInternalFeed
176+ displayName : Publish to MSGraph PowerShell V3 build feed
177+ environment : PowerShellInternalFeed
178+ templateContext :
179+ type : releaseJob
180+ isProduction : true
181+ inputs :
182+ - input : pipelineArtifact
183+ artifactName : drop
184+ targetPath : $(System.DefaultWorkingDirectory)/drop
185+ strategy :
186+ runOnce :
187+ deploy :
188+ steps :
189+ - task : 1ES.PublishNuget@1
190+ displayName : Publish wrapper packages to internal feed
191+ inputs :
192+ useDotNetTask : false
193+ packageParentPath : $(System.DefaultWorkingDirectory)
194+ packagesToPush : $(System.DefaultWorkingDirectory)/**/drop/**/Microsoft.Graph.Wrapper.*.nupkg
195+ publishVstsFeed : ${{ parameters.InternalFeed }}
196+ nuGetFeedType : internal
197+ allowPackageConflicts : false
0 commit comments