通过.NET Core WebAPI的终结点公开TFS内部版本号

时间:2019-06-16 16:12:23

标签: c# docker asp.net-core tfs asp.net-core-webapi

在一个解决方案中,我有一个.NET Core 2.2 WebAPI项目(以及其他项目)。 该解决方案在TFS中设置了相应的构建管道。每个TFS内部版本都有内部版本号,例如“ 20190615.15”。我想做的是通过Web-API端点公开此内部版本号,以实现维护和跟踪目的。

作为一个预解决方案,我设法从构建管道中设置了AssemblyInformationalVersion属性,并且使用以下控制器,我可以轻松地获取所需的构建号:

[Route("api/[controller]")]
[ApiController]
public class VersionController : ControllerBase
{
    [HttpPut(Name = "version")]
    public Task<ApplicationVersion> Version()
    {
        return Task.FromResult(new ApplicationVersion
        {
            Version = ReadVersionFromAssemblyInfo()
        });
    }

    private string ReadVersionFromAssemblyInfo()
    {
        return Assembly.GetEntryAssembly()
            .GetCustomAttribute<AssemblyInformationalVersionAttribute>()
            .InformationalVersion;
    }

    public class ApplicationVersion
    {
        public string Version { get; set; }
    }
}

我所做的很简单: 首先,我在Web-API的Dockerfile中引入了一个名为“ VERSION_NUMBER”的新ARG,并在最后一个发布步骤中设置了InformationalVersion

FROM microsoft/dotnet:2.2-sdk AS build
ARG VERSION_NUMBER
WORKDIR /src
COPY SomeAPI/SomeAPI.csproj SomeAPI/
RUN dotnet restore SomeAPI/SomeAPI.csproj
COPY . .
WORKDIR /src/SomeAPI
RUN dotnet publish SomeAPI.csproj -c Release -o /app -p:InformationalVersion=$VERSION_NUMBER

然后在docker-compose.yml文件中设置相同的arg

services:
  someapi:
    image: someApi:${TAG:-latest}
    build:
      context: .
      dockerfile: SomeAPI/Dockerfile
      args:
        VERSION_NUMBER: ${VERSION_NUMBER}

最后,在TFS构建的Docker-Compose任务中,我设置了上述参数: Docker-Compose task of TFS build

它的工作原理就像魅力一样,如果我访问端点https://somedomain.com/api/version,那么我会得到一个带有所需内部编号的json。

问题在于,在我的解决方案中,我重用/利用了AssemblyInformationalVersion属性,但是我想将此属性设置为正确的版本号(例如:1.0.1)。因此最终https://somdomain.com/api/version端点将返回一个.json,如:

{
    "Version": "1.0.1",
    "BuildNumber": "20190615.15"
}

通过Web-API端点公开内部版本号(来自TFS内部版本)的最佳方法是什么?是否可以在.csproj文件中设置自定义属性(xml标记),因此我可以将AssemblyInformationalVersion用于预期目的?感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我已经成功地找到了解决问题的方法。有两种好的方法可以做到这一点:

第一种方法::引入可在运行时访问的自定义.csproj属性。首先创建一个属性类:

namespace MyNamespace
{
    /// <summary>
    /// A run-time-accessible property specified in .csproj file in order to store the build-number of the CI build-pipeline.
    /// </summary>
    [AttributeUsage(AttributeTargets.Assembly)]
    public sealed class BuildNumberAttribute : Attribute
    {
        public BuildNumberAttribute(string buildNumber)
        {
            BuildNumber = buildNumber;
        }

        public string BuildNumber { get; }
    }
}

将以下项目组添加到.csproj文件中,以使该属性可访问:

  <ItemGroup>
    <AssemblyAttribute Include="MyNamespace.BuildNumberAttribute">
      <_Parameter1>"$(BuildNumber)"</_Parameter1>
    </AssemblyAttribute>
  </ItemGroup>

最后在dockerfile中,传递build参数

RUN dotnet publish SomeAPI.csproj -c Release -o /app -p:BuildNumber=$VERSION_NUMBER

请注意,在TFS构建管道的docker-compose任务中,VERSION_NUMBER设置为$(Build.BuildNumber)

要访问此新添加的属性,请执行以下操作:

private string ReadBuildNumber()
{
    return Assembly.GetEntryAssembly()
        .GetCustomAttribute<BuildNumberAttribute>()
        .BuildNumber.Trim('"');
}

第二种方法: 在TFS构建管道中使用“已替换令牌”任务。这样,您可以在appsettings.json中设置模板,并且该模板可以由任务替换。有关详细信息,请检查this stackoverflow question