Alexa for Bitrise CI/CD: Introduction to serverless with AWS Lambda and Bitrise API - Part 1

In this tutorial, we will share some hands-on experience on how to use the AWS Lambda, learn to design and build a Serverless function to trigger Bitrise builds with Bitrise API via the custom Lambda function.

In the early days of software development, anyone seeking to develop a web, mobile, or backend application had to own the hardware required to run a server, which is an expensive process.

Then, when cloud computing came, it became possible to lease server space or a number of servers remotely. The developers and companies who rent these fixed units of server space generally overbuy to ensure that a spike in traffic or activity won't exceed their monthly limits and break their applications. Because of this, a lot of the server space that gets paid for can be wasted.

As a result of this, serverless computing allows developers to purchase backend services on a pay-per-use basis, which means that only what they use must be paid for.

What is serverless?

In a serverless environment, a cloud provider (AWS, Azure, or Google Cloud) dynamically allocates resources to run code. The cost is only incurred when the code is actually executed. The code that is usually executed is called stateless containers, which can be triggered by a variety of events, for instance: database events, call API endpoint, and cron jobs.

Serverless computing refers to the ability to run these functions without maintaining your own servers. 

The term "serverless" doesn't refer to the absence of servers, but rather to the fact that the servers, operating systems, network layer, and rest of the infrastructure have already been configured so you can focus on writing the application code.

What is AWS Lambda?

AWS Lambda is a compute service that lets you run code without provisioning or managing servers. Lambda runs your code on a high-availability compute infrastructure and performs all of the administration of the compute resources, including server and operating system maintenance, capacity provisioning and automatic scaling, code monitoring and logging. “  — AWS Lambda Documentation.

You don't have to worry about any infrastructure with AWS Lambda since it's a fully managed service.

For instance, You can develop backends using AWS Lambda and Amazon API Gateway to authenticate and process API requests.

Image source https://aws.amazon.com/de/lambda/

The Lambda functions can perform a variety of tasks, from serving web pages to processing streams of data to calling APIs and integrating with other AWS services such as CloudWatch, API Gateway, S3, SNS, and more. 

How does AWS Lambda work?

When a function is created, Lambda packages it into a new container and then executes that container on a multi-tenant cluster of machines managed by AWS. Before the functions start running, each function’s container is allocated its necessary RAM and CPU capacity. Once the functions finish running, the RAM allocated at the beginning is multiplied by the amount of time the function spent running. The customers then get charged based on the allocated memory and the amount of run time the function took to complete.

Supported languages and runtimes

AWS Lambda supports a number of the most popular languages and runtimes such as Nodejs, Python, Ruby, Java, Go, and C# This is the full list of what’s supported.

AWS Lambda pricing

With AWS Free Tier, you can run 1 million requests for free. Also if you’d like to estimate your AWS Lambda architecture cost you can use the AWS Pricing Calculator. More info about Lambda pricing can be found in the pricing section. 

Getting started with AWS Lambda

You can create, invoke, and manage the Lambda functions using any of the following interfaces:

  • AWS Management Console 
  • AWS Command Line Interface (AWS CLI)
  • AWS SDKs
  • AWS CloudFormation

In this tutorial, I will use the AWS Management Console to create our Lambda function using NodeJS. 

Before we get started you should have the following prerequisites: 

Now let’s start with our first Lambda function:

  • Log in to the AWS Management Console with your AWS account
  • Choose AWS Lambda from the Compute Services
  • Click on Create function
  • Choose Author from scratch option because we will build our own function and not use a template or a blueprint
  •  Add the function name i.e “HelloBitrise” select the Runtime to be Node.js 14.x and leave the Architecture with the default option.
  • In the Permissions section, we will select Create a new role with basic Lambda permissions and click Create function

Congratulations: you just created your first Lambda function and you have the Function overview and the code source with an online editor.

Now you can do everything you want with your function such as change the code, test the function, monitor the traffic using CloudWatch, configure the Environment Variables and deploy the function. 

In the Function Overview, you will find two options: 

  • Add trigger: to specify which service will invoke the function. In our case it will be the Alexa Skills Kit. 
  • Add destination: to send invocation records to a destination when your function is invoked asynchronously, or if your function’s processes record from a stream such as an SNS topic.

Let’s now learn how to test our function. 

  • Click on Test and Create new event with an event name (hello) and the template will be hello-world because there are different templates but we will use it in part 3 when integrating the function with our Alexa Skills kit. 
  • Click the Save button and click the Test button again to trigger the test event

And the execution results will be displayed in a new tab in the online editor. 

After you’ve explored the Lambda function, and know how to trigger and test it, it’s time to know how to implement our function to trigger Bitrise builds. 

The next step in this tutorial requires that you have a Bitrise account and have an API Key to access it. To know more about Bitrise API and how to get your API Key you can read our article.

AWS Lambda and Bitrise API

To implement a NodeJS function to trigger a Bitrise build we need to install different node modules because we will create the project locally and then upload it to Lambda to include the node_modules folder as a part of our service. 

Let’s get started!

  • Open your terminal and create a new folder:
mkdir LambdaBitrise
cd LambdaBitrise
Copy code
  • Create a nodejs project with the following command: 
npm init
Copy code
  • Leave the default setting in case you don’t need to change anything, you just need to hit return [Enter] key on all the prompts 

The  package.json file that will be generated

  • Open the project in VS Code to be able to manage files within the project. 

Now we need to implement a function that triggers a new build endpoint from the Bitrise API, to do that: 

  • Inside the project and from the terminal install the request module
npm install request 
Copy code
  • In VS Code create a new file with the name index.js at the root of the project 

And add the following code:

var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://api.bitrise.io/v0.1/apps/{YOUR_APP_SLUG}/builds',
  'headers': {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    "build_params": {
      "branch": "chapter-3",
      "workflow_id": "primary"
    },
    "hook_info": {
      "type": "bitrise"
    }
  })
‍
};
‍
exports.handler =  async function(event, response) {
  console.log(response.body);
  return "done..."
}
‍
request(options, function (error,response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
Copy code
  • You can test the function by running the following command: 
node index.js
Copy code

And if it is successful run, you will find the output like the following: 

  • In the package.json file add the above command in the test configuration to be able to test it again.
  • We need to zip the project to be able to upload it to the AWS Lambda function by the following command (Don’t worry about the API Key and App Slug because we can use Lambda Environment variables to replace the hardcoded values) 
zip -r LambdaBitrise.zip index.js node_modules
Copy code

Now it’s time to upload the zipped folder to Lambda by the following steps: 

  • Click on Upload from the list and select zip file (you can also upload the file to the S3 bucket and load it from there)

The folder will be uploaded and extracted successfully and displayed in the online editor you will notice the node_modules folder as well. 

  • Click on the Configuration tab to add the Environment variables: 
  • APP_SLUG
  • API_KEY

Now you can replace the app_slug and API_Key with the Lambda Environment variables:

  • ${process.env.APP_SLUG}
  • ${process.env.Api_KEY}
var request = require('request');
‍
let app_slug = process.env.APP_SLUG
let api_key = process.env.API_KEY
‍
var options = {
  'method': 'POST',
  'url': 'https://api.bitrise.io/v0.1/apps/'+app_slug+'/builds',
  'headers': {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': api_key
  },
  body: JSON.stringify({
   'build_params': {
      'branch': 'chapter-3',
      'workflow_id': 'primary'
    },
    'hook_info': {
      'type': 'bitrise'
    }
  })
‍
};
‍
exports.handler =  async function(event, response) {
  console.log(response.body);
  return "done..."
}
‍
request(options, function (error,response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
Copy code

Click the Deploy button to save the changes and run Test to make sure that everything is working properly. 

Now to be able to test our Lambda function we need to add a trigger, which will be discussed in Part 2 to invoke the function from your terminal you can use the following command but remembers you need to have the AWS CLI: 

aws lambda invoke --function-name HelloBitrise  --cli-binary-format raw-in-base64-out  output.txt
Copy code

And the output should be like the following: 

{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
Copy code

And this is the output when you run the test in the Lambda online editor:

Now you can check your Bitrise dashboard to make sure that a new build is already triggered, then you can abort it to save your credits.

Congratulations, you did it! You created your first serverless function using AWS Lambda to trigger a new Bitrise build using Bitrise API.

Thank you for reading this article! If you have any questions or feedback, please reach out to us on Twitter, email, or join the Bitrise Slack to chat with us directly. 

References

Get Started for free

Start building now, choose a plan later.

Sign Up

Get started for free

Start building now, choose a plan later.