1

I have Teamcity build agent, where I need to extract the git log from a repository. The trouble is, when my shell script runs, it's not in git repository, so git log doesn't work out of the box.

Does anyone know how to achieve this.

I have search the documentation, but I can't seem to find any way of doing it.

Problem solving so far

  1. When Teamcity "clones" a project from Github on to the agent, it doesn't actually clone the whole thing. So the working directory is not a repository.

  2. I do not have SSH access to github when running my shell script, which I need

Thanks in advance.

Solution

See accepted answer below.

  • Possible duplicate of [How do I run a program with a different working directory from current, from Linux shell?](http://stackoverflow.com/questions/786376/how-do-i-run-a-program-with-a-different-working-directory-from-current-from-lin) – CBroe Nov 04 '16 at 20:08
  • Possible duplicate of [git pull while not in a git directory](http://stackoverflow.com/questions/5083224/git-pull-while-not-in-a-git-directory) – pathfinderelite Nov 04 '16 at 20:13
  • Does this answer your question? [Using git commands in a TeamCity Build Step](https://stackoverflow.com/questions/11632624/using-git-commands-in-a-teamcity-build-step) – Leponzo May 07 '21 at 21:18

3 Answers3

3

Use the -C flag of the git command. It allows you to specify the git directory.

git -C 'git-working-dir' log
pathfinderelite
  • 3,047
  • 1
  • 27
  • 30
  • But this would only work if I had the git directory on the build agent, correct? - and I'm wanting to get it from github.com –  Nov 04 '16 at 20:15
  • 1
    @CodeMonkey Correct, this only works for local directories AFAIK. You could clone the directory from GitHub using the `git://` protocol; you would only need SSH access if you wanted to push updates. – pathfinderelite Nov 04 '16 at 20:18
  • Yeah, makes sense about the clone situation. That might be a work-around fix for me. Edit: But since it's not public, I will need to setup SSH .. working on that. –  Nov 04 '16 at 20:20
0

My solution, ended up being as follows:

  1. Register SSH credentials to access Github on the TC Agent.

  2. git clone ssh://git@github.com/account-name/repo.git /var/tmp/projectname_tmp

  3. cd to the directory /var/tmp/projectname_tmp

  4. git log >> output.file

For bonus points, you can extract from a given date like so:

  1. git log --since='2016-11-01 03:00' >> output.log
0

You don't need to clone the repo to get the log. TeamCity already has a list of files and commit messages that triggered the build. You can simply query the TeamCity API in a script step and get the log. Here are the two Powershell functions I use to do this.

TeamCityGetChangeLog, requires the server url, the username, password, and a build ID (which you can pass in from the TeamCity parameters).

# Gets the change log for the specified build ID
function TeamCityGetChangeLog([string] $serverUrl, [string] $username, [string] $password, [int] $buildId){
    $changelog = ''

    # If the build is running inside TeamCity
    if ($env:TEAMCITY_VERSION) {
        $buildUrl = "$serverUrl/httpAuth/app/rest/changes?build=id:$($buildId)"
        $authToken = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($username + ":" + $password))

        # Get all the changes
        $request = [System.Net.WebRequest]::Create($buildUrl)
        $request.Headers.Add("Authorization", "Basic $authToken");
        $xml = [xml](new-object System.IO.StreamReader $request.GetResponse().GetResponseStream()).ReadToEnd()

        # Get all commit messages for each of them
        $changelog = Microsoft.PowerShell.Utility\Select-Xml $xml -XPath `
            "/changes/change" | Foreach {
                TeamCityGetCommitMessage $serverUrl $username $password $_.Node.id
            }
    }

    return $changelog
}

That relies on TeamCityGetCommitMessage which also requires the change set ID.

# Get the commit messages, and files changed for the specified change id
# Ignores empty lines, lines containing "#ignore", "merge branch"" or "TeamCity"
function TeamCityGetCommitMessage([string]$serverUrl, [string]$username, [string]$password, [int]$changeId)
{
    $getFilesChanged = $false;
    $request = [System.Net.WebRequest]::Create("$serverUrl/httpAuth/app/rest/changes/id:$changeId")
    $authToken = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($username + ":" + $password))
    $request.Headers.Add("Authorization", "Basic $authToken");

    $xml = [xml](new-object System.IO.StreamReader $request.GetResponse().GetResponseStream()).ReadToEnd()

    Microsoft.PowerShell.Utility\Select-Xml $xml -XPath "/change" |
        where { ($_.Node["comment"].InnerText.Length -ne 0) `
        -and (-Not $_.Node["comment"].InnerText.Contains('#ignore')) `
        -and (-Not $_.Node["comment"].InnerText.StartsWith("Merge branch")) `
        -and (-Not $_.Node["comment"].InnerText.StartsWith("TeamCity change"))} |
        foreach {
            $getFilesChanged = $true
            $username = (&{If($_.Node["user"] -ne $null) {$_.Node["user"].name.Trim()} Else { $_.Node.Attributes["username"].Value }})
            "<br /><strong>$($username + " on " + ([System.DateTime]::ParseExact($_.Node.Attributes["date"].Value, "yyyyMMddTHHmmsszzzz", [System.Globalization.CultureInfo]::InvariantCulture)))</strong><br /><br />"

            "$($_.Node["comment"].InnerText.Trim().Replace("`n", "`n<br />"))"
        }

    if ($getFilesChanged) {
        "<br /><br /><strong>Files Changed</strong><br /><br />"
        Microsoft.PowerShell.Utility\Select-Xml $xml -XPath "/change/files" |
        where { ($_.Node["file"].Length -ne 0)} |
        foreach { Select-Xml $_.Node -XPath 'file' |
            foreach { "$($_.Node.Attributes["file"].Value)<br />" }
        }
    }
}
Ben Richards
  • 3,437
  • 1
  • 14
  • 18
  • Thanks Boyan. Eventhough this is not actually an answer to my question (shell, and terminal (linux implied)), it's still a nice resource for others. –  Nov 18 '16 at 16:05