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 for git detached head #1098

Merged
merged 9 commits into from
Jan 11, 2017
26 changes: 23 additions & 3 deletions Documentation/tutorial/docfx_getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,27 @@ namespace WebApplication1

*Step4.* Right click on the website project, and click *View* -> *View in Browser*, navigate to `/_site` sub URL to view your website!

4. Build from source code
4. Use *DocFX* with a Build Server
---------------

*DocFX* can be used in a Continuous Integration environment.

Most build systems do not checkout the branch that is being built, but
use a `detached head` for the specific commit. DoxFX needs the the branch name to implement the `View Source` link in the API documentation.

Setting the environment variable `DOCFX_SOURCE_BRANCH_NAME` tells DocFX which branch name to use.

Many build systems set an environment variable with the branch name. DocFX uses the following:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support DOCFX_SOURCE_BRANCH_NAME is enough? Use documentation to tell CI users how to configure environment variables with different build systems?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to have docfx run on common the build system without any special instructions.


- `APPVEYOR_REPO_BRANCH` - [AppVeyor](https://www.appveyor.com/)
- `BUILD_SOURCEBRANCHNAME` - [Visual Studio Online](https://www.visualstudio.com/vso/)
- `CI_BUILD_REF_NAME` - [GitLab CI](https://about.gitlab.com/gitlab-ci/)
- `Git_Branch` - [TeamCity](https://www.jetbrains.com/teamcity/)
- `GIT_BRANCH` - [Jenkins](https://jenkins.io/)
- `GIT_LOCAL_BRANCH` - [Jenkins](https://jenkins.io/)


5. Build from source code
----------------
As a prerequisite, you need:
- [Microsoft Build Tools 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48159)
Expand All @@ -80,7 +100,7 @@ As a prerequisite, you need:

*Step4.* Follow steps in #2, #3, #4 to use *DocFX* in command-line, IDE or .NET Core.

5. A seed project to play with *DocFX*
6. A seed project to play with *DocFX*
-------------------------
Here is a seed project https://github.com/docascode/docfx-seed. It contains

Expand All @@ -93,7 +113,7 @@ Here is a seed project https://github.com/docascode/docfx-seed. It contains
> [!Tip]
> It is a good practice to separate files with different type into different folders.

6. Q&A
7. Q&A
-------------------------
1. Q: How do I quickly reference APIs from other APIs or conceptual files?
A: Use `@uid` syntax.
Expand Down
54 changes: 45 additions & 9 deletions src/Microsoft.DocAsCode.Common/Git/GitUtility.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DocAsCode.Common.Git
{
using System;
using System.Linq;
using System.IO;
using System.Text;
using System.Collections.Concurrent;
Expand All @@ -22,6 +23,16 @@ public static class GitUtility
private static readonly string GetOriginUrlCommand = "config --get remote.origin.url";
private static readonly string GetLocalHeadIdCommand = "rev-parse HEAD";
private static readonly string GetRemoteHeadIdCommand = "rev-parse @{u}";

private static readonly string[] BuildSystemBranchName = new[]
{
"APPVEYOR_REPO_BRANCH", // AppVeyor
"Git_Branch", // Team City
"CI_BUILD_REF_NAME", // GitLab CI
"GIT_LOCAL_BRANCH", // Jenkins
"GIT_BRANCH", // Jenkins
"BUILD_SOURCEBRANCHNAME" // VSO Agent
};

private static readonly ConcurrentDictionary<string, GitRepoInfo> Cache = new ConcurrentDictionary<string, GitRepoInfo>();

Expand Down Expand Up @@ -112,22 +123,47 @@ private static GitDetail GetFileDetailCore(string filePath)
private static GitRepoInfo GetRepoInfoCore(string directory)
{
var repoRootPath = RunGitCommandAndGetFirstLine(directory, GetRepoRootCommand);
var localBranch = GetLocalBranchName(repoRootPath);

// The "docfx..". environment variable specifies the branch name to use.
var localBranch = Environment.GetEnvironmentVariable("DOCFX_SOURCE_BRANCH_NAME");
string remoteBranch;
try

// Many build systems use a "detached head", which means that the normal git commands
// to get branch names do not work. Thankfully, they set an environment variable.
if (string.IsNullOrEmpty(localBranch))
{
remoteBranch = RunGitCommandAndGetFirstLine(repoRootPath, GetRemoteBranchCommand);
var index = remoteBranch.IndexOf('/');
if (index > 0)
var isDetached = "HEAD" == RunGitCommandAndGetFirstLine(repoRootPath, GetLocalBranchCommand);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"HEAD" == Run [](start = 32, length = 14)

merge with GetLocalBranchName?

Copy link
Contributor Author

@richardschneider richardschneider Jan 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the addition of GetLocalBranchName is wrong. It changes the semantics of both RepoInfo.LocalBranch and RepoInfo.RemoteBranch. Previously they held a git branch name. Now they can also hold a commit id.

I want nothing to do with this. Its evil.

Not sure what you mean by "HEAD" == Run [](start = 32, length = 14)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However the code here is exactly GetLocalBranchName. And they have duplicate logic checking detached. Please make the code change cleaner rather than more complex.

if (isDetached)
{
remoteBranch = remoteBranch.Substring(index + 1);
localBranch = BuildSystemBranchName
.Select(Environment.GetEnvironmentVariable)
.Where(name => !string.IsNullOrEmpty(name))
.FirstOrDefault();
}
}
catch (Exception ex)

if (!string.IsNullOrEmpty(localBranch))
{
Logger.LogInfo($"Can't find remote branch in this repo and fallback to use local branch [{localBranch}]: {ex.Message}");
remoteBranch = localBranch;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LogInfo to tell users that branch name is found in env

Logger.LogInfo($"Using branch '{localBranch}' from the environment variable.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also log the environment variable name

}
else
{
localBranch = GetLocalBranchName(repoRootPath);
try
{
remoteBranch = RunGitCommandAndGetFirstLine(repoRootPath, GetRemoteBranchCommand);
var index = remoteBranch.IndexOf('/');
if (index > 0)
{
remoteBranch = remoteBranch.Substring(index + 1);
}
}
catch (Exception ex)
{
Logger.LogInfo($"Can't find remote branch in this repo and fallback to use local branch [{localBranch}]: {ex.Message}");
remoteBranch = localBranch;
}
}

var originUrl = RunGitCommandAndGetFirstLine(repoRootPath, GetOriginUrlCommand);
Expand Down
38 changes: 38 additions & 0 deletions test/Microsoft.DocAsCode.Common.Tests/GitUtilityTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DocAsCode.Common.Tests
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using Xunit;
using YamlDotNet.Core;

using Microsoft.DocAsCode.Common.Git;
using Microsoft.DocAsCode.YamlSerialization;

[Trait("Owner", "makaretu")]
public class GitUtilityTest
{
[Fact]
public void Environment_ForBranchName()
{
const string envName = "DOCFX_SOURCE_BRANCH_NAME";
var original = Environment.GetEnvironmentVariable(envName);
try
{
Environment.SetEnvironmentVariable(envName, "special-branch");
var info = GitUtility.GetFileDetail(Directory.GetCurrentDirectory());
Assert.Equal("special-branch", info.RemoteBranch);
}
finally
{
Environment.SetEnvironmentVariable(envName, original);
}
}

}
}