How to download Jenkins artifacts using C#

Here is a simple example of how to download Jenkins build artifact as an array of bytes using C#:

public async Task<byte[]> GetBuildArtifactAsync(Uri uri)
    using (var webClient = new WebClient())
        var authInfo = <Jenkins Username> + ":" + <Jenkins Password>;
        authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
        webClient.Headers.Add(HttpRequestHeader.Authorization, "Basic " + authInfo);

        ServicePointManager.SecurityProtocol =
            SecurityProtocolType.Tls |
            SecurityProtocolType.Tls11 |

        return await

Change Jenkins Username and Jenkins Password accordingly.

You can use DownloadFileTaskAsync instead of DownloadDataTaskAsync if you want to download the file to the local machine.

Note: ServicePointManager.SecurityProtocol is only needed when you are accessing Jenkins via HTTPS.


Perforce Visual Client (P4V) – Baseless merges before version 2012.1

I needed to merge two branches without a common ancestor using Perforce Visual Client (P4V) 2015.2 but for my surprise the “-i” flag for p4 integrate has been removed. This flag is used to do indirect integrations. Indirect integration is when two branches are not directly related to each other like in the following example:

Indirect integration

Merging Y to Z is trivial because the two branches are directly related. However, going from X to Z is an indirect integration.

p4 integrate for release 2004.2 and later always considers (no need for “-i”) indirect integrations through intermediate branches when determining that files are related and what changes need to be integrated and I think that is the reason why the flag has been removed from P4V.

The problem happens when you need to do a baseless merge when the two branches are not related at all. In this case, you can’t use P4V and you will need to run the command with the “-i” flag.

Luckily, this has been fixed in version 2012.1 of Perforce and p4 integrate will now automatically schedule baseless merges to be performed with an empty base file. The “-i” flag is still accepted but has been deprecated.

I thought it was worth to write about it as there might be other people using an old version of Perforce.

For more information:

Python – Generators

Do you know the difference between the following lines in Python?

square_numbers_1 = [x*x for x in [1,2,3,4,5,6]]
square_numbers_2 = (x*x for x in [1,2,3,4,5,6])

The first line will create a list of squares for each element of [1,2,3,4,5,6] in memory which means you can access it by using square brackets:

# This will return 1
print square_numbers_1[0]

The second line will return a Generator object which means you cannot use the square brackets.
You can access the values using a for loop or the next() method.

# This will print all items:
# 1
# 4
# 9
# 16
# 25
# 36
for number in square_numbers_2:
    print number 

# This will return one item each time.
# The following line will return 1.
print next(square_numbers_2)

You need to call ‘next’ whenever you need an item and you will receive an exception (StopIteration) when you call it more than the number of items. More than six times for square_numbers_2.

You can also create a Generator by calling yield as in the following example:

def square_numbers(numbers):
    for n in numbers:
        yield (n*n)

square_numbers_generator = square_numbers([1,2,3,4,5,6])

for number in square_numbers_generator:
    print number

Why is Generators useful?

  • Reduce the amount of memory used as it will only allocate memory when you retrieve an item
  • Run faster because it stops when it gets to the first yield in the above example

Python – httplib

You might want to use the requests module instead which is easier to use.
If you need to use httplib, this article is for you.

Here is a basic example on how to use httplib to access TeamCity REST API using just GET and POST:

Global variables:


Method for the HTTP request with basic HTTP authentication.
It returns a tuple with the following fields: status, reason and body:

def teamcity_api_request(url, data=None):
    Send a TeamCity request using REST API
        verb = 'POST' if data else 'GET'
        print "Sending HTTP " + verb + ": " + TEAMCITY_SERVER + url
        conn = httplib.HTTPConnection(TEAMCITY_SERVER)
        user_and_pass = b64encode(TEAMCITY_USER + ":" + TEAMCITY_PASSWD).decode("ascii")
        headers = {'Authorization':'Basic %s' %  user_and_pass, "Content-Type": "application/xml", "Accept": "application/json"}
        if data:
            print "HTTP Message Body: " + data
            conn.request(verb, url, data, headers=headers)
            conn.request(verb, url, headers=headers)
        res = conn.getresponse()
        print "Unexpected error:"
        print sys.exc_info()[0]
        print sys.exc_info()[1]
        print sys.exc_info()[2]
        print "Error while retrieving TeamCity information!"

    res_status = res.status
    res_reason = res.reason
    res_body =

    # Dumping out request
    print "--------------- HTTP response --------------------"
    print "Status: " + str(res_status)
    print "Reason: " + res_reason
    print "Body: "   + res_body
    print "--------------------------------------------------"

    # Stop execution if HTTP code is different than 200
    if res_status != 200:
        print "HTTP code is different than 200. Aborting..."

    request = collections.namedtuple('Request', ['status', 'reason', 'body'])
    # Convert body to json if request was successful
    if res_status == 200:
        res_body = json.loads(res_body)
    req = request(status=res_status, reason=res_reason, body=res_body)
    return req

How to use it:

# GET - get a list of builds
request = teamcity_api_request("/builds")
print request.status

# POST - cancel a build
request = teamcity_api_request("/buildQueue/id:<build ID>", "<buildCancelRequest comment='<comment>' readdIntoQueue='true' />")
print request.status

Linux – How to cut a log file based on timestamp

You can use the command ‘sed’ to specify an interval to cut a log file. ‘sed’ performs editing operations on information coming from standard input or a file. It edits line-by-line and in a non-interactive way.

Example to cut a log file based on timestamp:

sed '1,/2017\/01\/11 09\:00/ d;/2017\/01\/11 10\:00/,$ d' <logfile>

This command will just show lines between ‘2017/01/11 09:00’ and ‘2017/01/11 10:00’.
In reality, the command is removing all lines before ‘2017/01/11 09:00’ and after ‘2017/01/11 10:00’ (including lines with ‘2017/01/11 10:00’).

You need to modify the command to match your log file and your needs.

Bash – How to return a value in a function

Here are some ways to return a value in a function in a Bash script:

1. Strings

function foo()
    echo "true"


if [ "$retval" == "true" ];
     echo "true"

2. Exit status

function foo()
    return 0


if [ $retval == 0 ];
     echo "okay"

3. Shared variable


function foo()


if [ "$retval" == 0 ]
     echo "okay"

Adapted from:

TeamCity agent doesn’t show the application window when a build is run

If you are running TeamCity agent as a service in Windows you probably noticed that you cannot see any application window that your build agent is running.

You don’t see any window because, for security reasons, the latest versions of Windows runs services in Session0 and not Session1. Sometimes you need to see it, specially if you running tests. If you need to run TeamCity agent on Session1 and not Session0 and be able to see what is going on without having to access Session0 you shouldn’t be running your TeamCity agent as a service.

In the installation wizard, you should untick the option to install the agent as a service:


After installing it, you need to configure the build agent to be run automatically when the machine starts. You need to add a shortcut to “<installation path>\bin\agent.bat start” in “C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup” for all users.