3

I want to verify that the version being used when packing some nuget-packages using dotnet build /p:VERSION=1.2.3 and GeneratePackageOnBuild. My regex expressen is working in LINQPad 6 using C#:

Regex.Match("1.2.3", @"^\d{1,3}\.\d{1,3}\.\d{1,6}(-(beta|rc)(\d{1,1})?)?$")

However in my default.props that is being imported by all csproj-files (which are using the new sdk-style, if that is relevant) I have this and it is not working at all:

<Target Name="ValidateVersion" BeforeTargets="BeforeBuild">
  <PropertyGroup>
    <VersionRegex>^\d{1,3}\.\d{1,3}\.\d{1,6}(-(beta|rc)(\d{1,1})?)?$</VersionRegex>
    <VersionTest>1.2.3</VersionTest> <!-- Just to make it easier during testing -->
  </PropertyGroup>

  <Error
    Text="Version is not following the correct format: $(VersionRegex)"
    Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch('$(VersionTest)', `$(VersionRegex)`)) " />
</Target>

It does not matter if I inline VersionRegex and VersionTest, it is still not working. Any ideas why it is working in C# but not in MSBuild?

6
  • I got nothing on this System (only here because of the C# tag), but usually types have to be properly anotated. And those do not look like they are notated properly as string. How ho the text and condition strings below are anotated. Commented Nov 28, 2019 at 19:46
  • 1
    could be that it's not coming across as expected with xml escaping. try sticking your regex inside a CDATA. Commented Nov 28, 2019 at 19:49
  • @viethoang: there are only 5 characters that need to be escaped/encoded in XML: <, >, & and both single-quote (/apostrophe) and double-quote. I don't see any of those Commented Nov 28, 2019 at 20:21
  • True, next thought is to replace the four single quotes inside IsMatch() with &quot; Commented Nov 29, 2019 at 1:39
  • @Christopher Sounds plausible. How do I annotate them as strings? I tried to inline the variable as [System.String]'^\d{1,3}\.\d{1,3}\.\d{1,6}(-(beta|rc)(\d{1,1})?)?$' and with back ticks but I still get the same result. Commented Nov 29, 2019 at 8:08

2 Answers 2

3

From your original example, you should be able to put the content of the VersionRegex property within CDATA:

<Target Name="ValidateVersion" BeforeTargets="BeforeBuild">
  <PropertyGroup>
    <VersionRegex><![CDATA[^\d{1,3}\.\d{1,3}\.\d{1,6}(-(beta|rc)(\d{1,1})?)?$]]></VersionRegex>
    <VersionTest>1.2.3</VersionTest>
  </PropertyGroup>

  <Error
    Text="Version is not following the correct format: $(VersionRegex)"
    Condition="!$([System.Text.RegularExpressions.Regex]::IsMatch('$(VersionTest)', '$(VersionRegex)'))" />
</Target>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, it seems to be working! Can you add a ! to the beginning of Condition? I will mark your answer as accepted after that.
Funnily enough, I'll likely be using your answer as I'm trying to use named match groups, but MSBuild wont let me access $([System.Text.RegularExpressions.Regex]::Match($(VersionTest), $(VersionRegex)).Groups["my_group"]
Great that my answer still can be useful to others!
3

Workaround

I haven't found the actual issue but a workaround is, as @Viet Hoang mentioned in the comments, to use CDATA:

Targets/ValidateVersioning.targets:

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask
    TaskName="ValidateVersion"
    TaskFactory="RoslynCodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
    <ParameterGroup>
      <Version ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System"/>
      <Using Namespace="System.IO"/>
      <Using Namespace="System.Text.RegularExpressions"/>
      <Code Type="Fragment" Language="cs">
<![CDATA[
if (!Regex.Match(Version, @"^\d{1,3}\.\d{1,3}\.\d{1,6}(-(beta|rc)(\d{1,1})?)?$").Success)
{
    Log.LogError("Version has wrong format: {0}", Version);
    return false;
}
]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

default.props:

<Project>

...

  <Import Project="Targets\ValidateVersioning.targets" />
  <Target Condition="$(VERSION) != ''" Name="ValidateVersion" BeforeTargets="BeforeBuild">
    <ValidateVersion Version="$(VERSION)" />
  </Target>

...

</Project>

> dotnet build --no-restore -p:Version=1.3.4 will work but

> dotnet build --no-restore -p:Version=1.3 will not build

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.