Running Git in an AWS Lambda Function

Figure showing a Lambda function that communicates with a Git repository.

Last updated: May 18, 2019

The AWS Lambda execution environment is based on the Amazon Linux AMI release 2018.03. Git client is not pre-installed in the AWS Lambda execution environment.

You can compile the latest sources of Git and include the binaries into the deployment package of your Lambda function (or create an AWS Lambda layer). You must build your binaries for the matching version of Amazon Linux, or link them statically.

Alternatively, you can download Git RPM package from the official Amazon Linux repository of the Amazon Linux AMI release 2018.03. You can do it in the Lambda function itself during its execution. The following procedure describes this approach.

  • This blog post does not apply to the newly introduced Node.js v10 runtime which runs on Amazon Linux 2.

How to Run Git Client in a Lambda Function

The repositories of the Amazon Linux AMI release 2018.03 are defined in the configuration files in the /etc/yum.repos.d directory. You can query the repositories using repoquery utility to get the download URLs of RPM packages.

The download URL of the latest available version of Git RPM package for the Amazon Linux AMI release 2018.03 is http://packages.$awsregion.amazonaws.com/2018.03/updates/91e77b966236/x86_64/Packages/git-2.14.5-1.60.amzn1.x86_64.rpm, where $awsregion can have one of the following values:

  • ap-east-1
  • ap-northeast-1
  • ap-northeast-2
  • ap-south-1
  • ap-southeast-1
  • ap-southeast-2
  • ca-central-1
  • eu-central-1
  • eu-north-1
  • eu-west-1
  • eu-west-2
  • eu-west-3
  • sa-east-1
  • us-east-1
  • us-east-2
  • us-west-1
  • us-west-2

To download and run Git client in your Lambda function during its execution:

  1. Download git-2.14.5-1.60.amzn1.x86_64.rpm package, verify its signature and extract the files from this package to /tmp/git-2.14.5 directory.
    For example, if you invoke your Lambda function in the US East (N. Virginia) region, execute in this function the following commands:
    rm -fr /tmp/git-2.14.5 && \
    mkdir /tmp/git-2.14.5 && \
    cd /tmp/git-2.14.5 && \
    curl -s -O http://packages.us-east-1.amazonaws.com/2018.03/updates/91e77b966236/x86_64/Packages/git-2.14.5-1.60.amzn1.x86_64.rpm && \
    rpm -K git-2.14.5-1.60.amzn1.x86_64.rpm && \
    rpm2cpio git-2.14.5-1.60.amzn1.x86_64.rpm | cpio -id && \
    rm git-2.14.5-1.60.amzn1.x86_64.rpm
    
  2. Run Git client as follows:
    cd /tmp/git-2.14.5 && \
    HOME=/var/task \
    GIT_TEMPLATE_DIR=/tmp/git-2.14.5/usr/share/git-core/templates \
    GIT_EXEC_PATH=/tmp/git-2.14.5/usr/libexec/git-core \
    /tmp/git-2.14.5/usr/bin/git --version 
    

Appendix A, How to Clone a Git Repository in a Lambda Function (Python)

The following Python code snippet shows how you can clone a public Git repository in your Lambda function. In this example you create a shallow clone with a depth of 1 to the /tmp/git-2.14.5 directory. The code is compatible with Python 2.7, Python 3.6 and Python 3.7.

The execution duration of this Lambda function depends on the size of the configured memory and can be as less as 3 seconds.

from __future__ import print_function
import os
import subprocess

def lambda_handler(event, context):
    # Git repository to clone
    remote_repository = 'https://github.com/gohugoio/hugo.git'
    git_command = 'clone --depth 1'

    git_rpm_region = os.environ['AWS_REGION']
    git_rpm_download_url = '/'.join([
        'http://packages.%s.amazonaws.com' % git_rpm_region,
        '2018.03/updates/91e77b966236/x86_64/Packages',
        'git-2.14.5-1.60.amzn1.x86_64.rpm'])

    git_rpm = git_rpm_download_url.split('/')[-1]  # git-2.14.5-1.60.amzn1.x86_64.rpm
    tmp_dir = '/tmp/%s' % '-'.join(git_rpm.split('-')[0:2])  # /tmp/git-2.14.5

    # Download, verify and unpack Git RPM package
    print(subprocess.check_output(
        ' && '.join([
            'rm -fr %s' % tmp_dir,
            'mkdir %s' % tmp_dir,
            'cd %s' % tmp_dir,
            'curl -s -O %s' % git_rpm_download_url,
            'rpm -K %s' % git_rpm,  # Check the GnuPG signature
            'rpm2cpio %s | cpio -id' % git_rpm,
            'rm %s' % git_rpm
        ]),
        stderr=subprocess.STDOUT,
        shell=True))

    # Clone the remote Git repository
    print(subprocess.check_output(
        ' && '.join([
            'cd %s' % tmp_dir,
            ' '.join([
                'HOME=/var/task',
                'GIT_TEMPLATE_DIR=%s/usr/share/git-core/templates' % tmp_dir,
                'GIT_EXEC_PATH=%s/usr/libexec/git-core' % tmp_dir,
                '%s/usr/bin/git %s %s' % (tmp_dir, git_command, remote_repository)
            ])
        ]),
        stderr=subprocess.STDOUT,
        shell=True))