如何让MSBuild的MakeDir任务在Azure Pipeline YAML模板中正常运行?
问题根因
- 首先你PostBuild事件中
MakeDir的路径存在笔误:路径开头写了.../../(三个点),Linux系统对路径格式要求严格,无法识别三个点的路径片段,会直接判定为无效路径,导致目录创建失败 - 相对路径依赖MSBuild执行时的工作目录,移入YAML模板后,若DotNetCoreCLI任务的工作目录、构建的项目路径(比如直接构建解决方案而非单个项目)发生变化,相对路径的基准目录就会偏移,导致目录创建位置和swagger命令写入的位置不一致
修复现有PostBuild方案
将相对路径替换为MSBuild内置属性生成的绝对路径,规避工作目录变动的影响,修改后的csproj配置如下:
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Exec Command="dotnet tool restore" /> <!-- MSBuildProjectDirectory 固定为当前csproj文件所在的目录,路径计算不会受执行环境影响 --> <MakeDir Directories="$(MSBuildProjectDirectory)/../../artifacts/swagger/v1" Condition="!Exists('$(MSBuildProjectDirectory)/../../artifacts/swagger/v1')" /> <Exec Command="dotnet swagger tofile --output $(MSBuildProjectDirectory)/../../artifacts/swagger/v1/swagger.json "$(TargetPath)" v1" /> </Target>
同时可以在YAML模板的构建任务中强制指定工作目录为源码根目录,进一步保证路径一致性:
- task: DotNetCoreCLI@2 displayName: Build inputs: command: build projects: ${{ parameters.projectsToBuild }} arguments: --no-restore --configuration ${{ parameters.configuration }} /p:Version=$(GitVersion.FullSemVer) /p:ContinuousIntegrationBuild=true workingDirectory: $(Build.SourcesDirectory)
跨平台替代方案
可以把swagger生成逻辑从csproj中剥离,放到流水线中作为独立步骤执行,完全规避构建逻辑变动的影响,实现更稳定的跨平台兼容:
- 新增目录创建步骤,PowerShell Core原生支持跨平台运行:
- task: PowerShell@2 displayName: Create swagger output directory inputs: targetType: inline script: New-Item -ItemType Directory -Path $(Build.SourcesDirectory)/artifacts/swagger/v1 -Force pwsh: true
- 新增swagger生成步骤:
- task: DotNetCoreCLI@2 displayName: Generate swagger.json inputs: command: custom custom: swagger # 替换下面的dll路径为你项目实际的构建输出路径即可 arguments: tofile --output $(Build.SourcesDirectory)/artifacts/swagger/v1/swagger.json $(Build.SourcesDirectory)/src/YourProject/bin/$(parameters.configuration)/net6.0/YourProject.dll v1
如果不想拆分步骤,也可以简化MSBuild写法,直接在命令中创建目录,省去单独的MakeDir任务:
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Exec Command="dotnet tool restore" /> <Exec Command="dotnet swagger tofile --output $([System.IO.Directory]::CreateDirectory('$(MSBuildProjectDirectory)/../../artifacts/swagger/v1').FullName)/swagger.json "$(TargetPath)" v1" /> </Target>
内容的提问来源于stack exchange,提问作者user3119533
相关产品推荐
相关产品推荐

