Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Branch name always set to HEAD in Gitlab build #362

Closed
demconsido opened this issue Oct 17, 2024 · 4 comments · Fixed by #365
Closed

Branch name always set to HEAD in Gitlab build #362

demconsido opened this issue Oct 17, 2024 · 4 comments · Fixed by #365
Labels
bug need info More info needed to diagnose the issue

Comments

@demconsido
Copy link

demconsido commented Oct 17, 2024

Bug description

When building locally, branch name is correctly filled in. But building on a Gitlab runner, the branch name is always HEAD. This has to do with Gitlab always checking out specific commit and not full branch, which makes sense.

My current workaround is to add following snippet to my .csproj, after including GitInfo, which basically overrides the generated GitBranch property when on CI:

<PropertyGroup Condition="'$(CI)' != ''">
    <GitBranch>$(CI_COMMIT_BRANCH)</GitBranch>
</PropertyGroup>

In GitInfo src/Directory.Build.targets I see:

<PropertyGroup Condition="'$(RepositoryBranch)' == ''">
    <!-- ... -->
    <!-- GitLab: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html -->
    <RepositoryBranch Condition="'$(RepositoryBranch)' == '' and '$(CI_COMMIT_TAG)' != ''">$(CI_COMMIT_TAG)</RepositoryBranch>
    <RepositoryBranch Condition="'$(RepositoryBranch)' == '' and '$(CI_MERGE_REQUEST_IID)' != ''">pr$(CI_MERGE_REQUEST_IID)</RepositoryBranch>
    <RepositoryBranch Condition="'$(RepositoryBranch)' == '' and '$(CI_EXTERNAL_PULL_REQUEST_IID)' != ''">pr$(CI_EXTERNAL_PULL_REQUEST_IID)</RepositoryBranch>
    <RepositoryBranch Condition="'$(RepositoryBranch)' == '' and '$(CI_COMMIT_BRANCH)' != ''">$(CI_COMMIT_BRANCH)</RepositoryBranch>
    <!-- ... -->
  </PropertyGroup>  

So this snipped should (ultimately) set the 'RepositoryBranch' to Gitlab variable CI_COMMIT_BRANCH.
So is this a bug, or am I doing anything wrong?

Steps to Reproduce

Create or use an existing dotnet project and create a branch 'mybranch' in the git repo and use following project configuration.

Current .csproj (or Build.props) snippet:

<PropertyGroup>
    <!-- we'll do our own versioning -->
    <GitVersion>false</GitVersion>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <WarningsNotAsErrors>8002</WarningsNotAsErrors>
</PropertyGroup>

<ItemGroup>
    <PackageReference Include="GitInfo" Version="3.3.4" PrivateAssets="All" />
</ItemGroup>

<!--Override default Version info here with GitInfo values-->
<Target Name="PopulateGitInfo" DependsOnTargets="GitVersion"
        BeforeTargets="GetAssemblyVersion;GenerateNuspec;GetPackageContents">
    <PropertyGroup>
        <Version>$(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)</Version>
        <PackageVersion>$(Version)</PackageVersion>
        <RepositoryBranch>$(GitBranch)</RepositoryBranch>
        <RepositoryCommit>$(GitCommit)</RepositoryCommit>
        <SourceRevisionId Condition="'$(GitBranch)' == '' or '$(GitBranch)' == 'HEAD'">0</SourceRevisionId>
        <SourceRevisionId Condition="'$(GitBranch)' != '' and '$(GitBranch)' != 'HEAD' and '$(GitIsDirty)' != '1'">$(GitBranch)+$(GitCommit)</SourceRevisionId>
        <SourceRevisionId Condition="'$(GitBranch)' != '' and '$(GitBranch)' != 'HEAD' and '$(GitIsDirty)' == '1'">$(GitBranch)+$(GitCommit)M</SourceRevisionId>
    </PropertyGroup>
</Target>

 <!--Display version info during build-->
 <Target Name="TestMessage" AfterTargets="Build">
     <Message
         Text="Version detected: $(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)-$(GitBranch)+$(GitCommit)" Importance="high" />
     <Message Text="Product Version: $(Version).$(SourceRevisionId)" Importance="high" />
 </Target>

gitlab-ci.yml:

default:
  image:
    name: mcr.microsoft.com/dotnet/sdk:8.0-windowsservercore-ltsc2022
  tags:
    - windows
    - docker

stages:
  - build

build:
  stage: build
  script:
  - dotnet restore
  - dotnet build -c Release --no-restore
  artifacts:
    paths:
    - 'src/*/bin/'
    - 'src/*/obj/'
    - 'test/*/bin/'
    expire_in: 1 day

Then push to Gitlab.

Expected Behavior

Gitlab runner should display Version detected and Product Version during build, which should be something like 0.0.1-mybranch+03d5aff
and not:
0.0.1-HEAD+03d5aff

Version Info

GitInfo Version="3.3.4"

Back this issue
Back this issue

@demconsido demconsido added the bug label Oct 17, 2024
@kzu
Copy link
Member

kzu commented Oct 22, 2024

Could you try building locally and setting the CI envvars to arbitrary values locally until you can reproduce the issue locally? See https://docs.gitlab.com/ee/ci/variables/predefined_variables.html.

Also, a binlog from that repro would be super helpful to determine what actually is being set and where during the build. Just dun dotnet build -bl and attach the resulting .binlog 🙏

@kzu kzu added the need info More info needed to diagnose the issue label Oct 22, 2024
@demconsido
Copy link
Author

demconsido commented Oct 29, 2024

I created a new clean project to only emphasize on the GitInfo issue. It gives the same result.

Directory.Build.props in root folder:

<?xml version="1.0" encoding="utf-8"?>

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <SignAssembly>False</SignAssembly>
        <ImplicitUsings>enable</ImplicitUsings>
        <Authors>Yournamehere</Authors>
        <Copyright>
            TODO: Add specific Copyright notice here
        </Copyright>
    </PropertyGroup>

    <!-- To be redefined by GitInfo after restore. -->
    <Target Name="GitVersion" />

    <ItemGroup>
        <InternalsVisibleTo Include="$(AssemblyName).Tests.Unit" />
        <InternalsVisibleTo Include="$(AssemblyName).Tests.Integration" />
        <InternalsVisibleTo Include="$(AssemblyName).Tests.System" />
        <InternalsVisibleTo Include="$(AssemblyName).Tests.TestApplication" />
    </ItemGroup>
</Project>

Directory.Build.props in src subfolder:

<?xml version="1.0" encoding="utf-8"?>

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <Import Project="..\Directory.Build.props" />

    <PropertyGroup>
        <!-- we'll do our own versioning -->
        <GitVersion>false</GitVersion>
        <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
        <WarningsNotAsErrors>8002</WarningsNotAsErrors>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="GitInfo" Version="3.3.4" PrivateAssets="All" />
    </ItemGroup>

    
    <!--Override default Version info here with GitInfo values. Note that the GitInfo source code is already generated here-->
    <Target Name="PopulateGitInfo" DependsOnTargets="GitVersion"
            BeforeTargets="GetAssemblyVersion;GenerateNuspec;GetPackageContents">
        <PropertyGroup>
            <Version>$(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)</Version>
            <PackageVersion>$(Version)</PackageVersion>
            <RepositoryBranch Condition="'$(GitBranch)' == '$(GitBranchPostfix)' or '$(GitBranch)' == 'HEAD$(GitBranchPostfix)'"></RepositoryBranch>
            <RepositoryBranch Condition="'$(GitBranch)' != '$(GitBranchPostfix)' and '$(GitBranch)' != 'HEAD$(GitBranchPostfix)'">$(GitBranch)"</RepositoryBranch>
            <RepositoryCommit>$(GitCommit)</RepositoryCommit>
            <SourceRevisionId Condition="'$(GitBranch)' == '$(GitBranchPostfix)' or '$(GitBranch)' == 'HEAD$(GitBranchPostfix)'">0</SourceRevisionId>
            <SourceRevisionId Condition="'$(GitBranch)' != '$(GitBranchPostfix)' and '$(GitBranch)' != 'HEAD$(GitBranchPostfix)' and '$(GitIsDirty)' != '1'">$(GitBranch).$(GitCommit)</SourceRevisionId>
            <SourceRevisionId Condition="'$(GitBranch)' != '$(GitBranchPostfix)' and '$(GitBranch)' != 'HEAD$(GitBranchPostfix)' and '$(GitIsDirty)' == '1'">$(GitBranch).$(GitCommit)M</SourceRevisionId>
        </PropertyGroup>
    </Target>

</Project>

Actual .csproj in subfolder in src folder:

Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net8.0-windows</TargetFramework>
        <UseWPF>true</UseWPF>
    </PropertyGroup>

    <!--Display version info during build-->
    <Target Name="TestMessage" AfterTargets="Build">
        <!--Create a property with the constructed version info-->
        <PropertyGroup>
            <VersionInfoProp Condition="('$(GitBranch)' == '$(GitBranchPostfix)' or '$(GitBranch)' == 'HEAD$(GitBranchPostfix)') and '$(GitIsDirty)' != '1'">$(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)</VersionInfoProp>
            <VersionInfoProp Condition="('$(GitBranch)' == '$(GitBranchPostfix)' or '$(GitBranch)' == 'HEAD$(GitBranchPostfix)') and '$(GitIsDirty)' == '1'">$(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)M</VersionInfoProp>
            <VersionInfoProp Condition="'$(GitBranch)' != '$(GitBranchPostfix)' and '$(GitBranch)' != 'HEAD$(GitBranchPostfix)' and '$(GitIsDirty)' != '1'">$(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)+$(GitBranch).$(GitCommit)</VersionInfoProp>
            <VersionInfoProp Condition="'$(GitBranch)' != '$(GitBranchPostfix)' and '$(GitBranch)' != 'HEAD$(GitBranchPostfix)' and '$(GitIsDirty)' == '1'">$(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)+$(GitBranch).$(GitCommit)M</VersionInfoProp>
        </PropertyGroup>

        <!--Display the version info in the build -->
        <Message Text="CI: $(CI)" Importance="high" />
        <Message Text="CI Branch: $(CI_COMMIT_BRANCH)" Importance="high" />
        <Message Text="Branch: $(GitBranch)" Importance="high" />
        <Message Text="Version: $(VersionInfoProp)" Importance="high" />
        <Message Text="Product Version: $(Version).$(SourceRevisionId)" Importance="high" />
        <Message Text="RepositoryBranch: $(RepositoryBranch)" Importance="high" />


        <!--Create an intermediate ItemGroup for writing Version Info to file -->
        <ItemGroup>
            <CiVersionInfo Include="$(VersionInfoProp)" />
        </ItemGroup>
        <WriteLinesToFile File="$(OutputPath)\version.txt" Lines="@(CiVersionInfo)" Overwrite="true" Encoding="Unicode" />
    </Target>

     ... removed irrelevant part...

</Project>

Output local build:

CI:
CI Branch:
Branch: master
Version: 0.0.1+master.d9a6c68
Product Version: 0.0.1.master.d9a6c68
RepositoryBranch: master

Output local checkout specific commit:

CI:
CI Branch:
Branch: HEAD
Version: 0.0.1
Product Version: 0.0.1.0
RepositoryBranch:

Set environment variables locally to simulate Gitlab environment and build with buildlog:

set CI=true
set CI_COMMIT_BRANCH=master
set CI_COMMIT_TAG=master
dotnet build -bl

Ouput with these manually set environment variables:

CI: true
CI Branch: master
Branch: HEAD
Version: 0.0.1
Product Version: 0.0.1.0
RepositoryBranch:

Ouput Gitlab build:

CI: true
CI Branch: master
Branch: HEAD
Version: 0.0.1
Product Version: 0.0.1.0
RepositoryBranch:

Note: the latter two indeed produce the same result.
Note2: above code contains multiple references to $(GitBranchPostfix), but in this example project it always evaluates to empty string.
Note3: github does not allow me to attach the resulting .binlog. I will mail it to you.

@kzu
Copy link
Member

kzu commented Oct 29, 2024

GitInfo does not populate RepositoryBranch. What you are seeing is MY way of defaulting it when I build GitInfo (and that's a generic targets file I use across all my OSS projects).

The GitInfo way is strictly through git commands: https://github.com/devlooped/GitInfo/blob/main/src/GitInfo/build/GitInfo.targets#L405-L435

My approach to defaulting RepositoryBranch is sprinkled in a few PRs here and there, see https://github.com/search?q=repositorybranch%20author%3Akzu&type=issues.

Personally, I think this should be done by dotnet/sourcelink since that's the one providing source control info nowadays.

@kzu
Copy link
Member

kzu commented Oct 29, 2024

The package that does this for you, is ThisAssembly.Git.

Which, I'd say is the natural successor to this package.

@kzu kzu closed this as completed in #365 Oct 29, 2024
@devlooped devlooped locked and limited conversation to collaborators Nov 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug need info More info needed to diagnose the issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants