DEV Community


Posted on • Originally published at on

Running a serverless JS project with GitLab

You may have heard of serverless FaaS solutions like AWS Lambda. We tell how it works by the example of launching a JavaScript project with GitLab.

The idea boils down to writing code as a set of discrete functions that can be called up by various events. Concerns about preparing the server, scaling, managing the internal stack and other operational tasks are abstracted. This results in significant cost savings as computing resources are available on demand.

Do you want to learn the secret of serverlessness without executing a single command in the terminal? All you need is GitLab and AWS accounts.

Project creation

First, create a project using a serverless template. Open the page of the new project and select the tab Create from template. Scroll down and select a template Serverless Framework/JS.

We name the project, create using Create project.

Set up an AWS account

The project is created, we transfer access to AWS to deploy it. Open the AWS console, go to the IAM section . Here we select in the left column Usersand create a new user using the button Add userat the top of the list.

Give the user a name, for example gitlab-serverless. Before clicking Next, make sure the box is checked Programmatic access.

Now you need to give the user the appropriate rights to deploy serverless functions. On the page, Permissionsselect Attach existing policies directlyand click Create policy– a new window will open.

Here you need to select the ” JSON ” tab and paste the following:

{ "Statement": [{ "Action": [ "apigateway:\*", "cloudformation:CancelUpdateStack", "cloudformation:ContinueUpdateRollback", "cloudformation:CreateChangeSet", "cloudformation:CreateStack", "cloudformation:CreateUploadBucket", "cloudformation:DeleteStack", "cloudformation:Describe\*", "cloudformation:EstimateTemplateCost", "cloudformation:ExecuteChangeSet", "cloudformation:Get\*", "cloudformation:List\*", "cloudformation:PreviewStackUpdate", "cloudformation:UpdateStack", "cloudformation:UpdateTerminationProtection", "cloudformation:ValidateTemplate", "dynamodb:CreateTable", "dynamodb:DeleteTable", "dynamodb:DescribeTable", "ec2:AttachInternetGateway", "ec2:AuthorizeSecurityGroupIngress", "ec2:CreateInternetGateway", "ec2:CreateNetworkAcl", "ec2:CreateNetworkAclEntry", "ec2:CreateRouteTable", "ec2:CreateSecurityGroup", "ec2:CreateSubnet", "ec2:CreateTags", "ec2:CreateVpc", "ec2:DeleteInternetGateway", "ec2:DeleteNetworkAcl", "ec2:DeleteNetworkAclEntry", "ec2:DeleteRouteTable", "ec2:DeleteSecurityGroup", "ec2:DeleteSubnet", "ec2:DeleteVpc", "ec2:Describe\*", "ec2:DetachInternetGateway", "ec2:ModifyVpcAttribute", "events:DeleteRule", "events:DescribeRule", "events:ListRuleNamesByTarget", "events:ListRules", "events:ListTargetsByRule", "events:PutRule", "events:PutTargets", "events:RemoveTargets", "iam:CreateRole", "iam:DeleteRole", "iam:DeleteRolePolicy", "iam:GetRole", "iam:PassRole", "iam:PutRolePolicy", "iot:CreateTopicRule", "iot:DeleteTopicRule", "iot:DisableTopicRule", "iot:EnableTopicRule", "iot:ReplaceTopicRule", "kinesis:CreateStream", "kinesis:DeleteStream", "kinesis:DescribeStream", "lambda:\*", "logs:CreateLogGroup", "logs:DeleteLogGroup", "logs:DescribeLogGroups", "logs:DescribeLogStreams", "logs:FilterLogEvents", "logs:GetLogEvents", "s3:CreateBucket", "s3:DeleteBucket", "s3:DeleteBucketPolicy", "s3:DeleteObject", "s3:DeleteObjectVersion", "s3:GetObject", "s3:GetObjectVersion", "s3:ListAllMyBuckets", "s3:ListBucket", "s3:PutBucketNotification", "s3:PutBucketPolicy", "s3:PutBucketTagging", "s3:PutBucketWebsite", "s3:PutEncryptionConfiguration", "s3:PutObject", "sns:CreateTopic", "sns:DeleteTopic", "sns:GetSubscriptionAttributes", "sns:GetTopicAttributes", "sns:ListSubscriptions", "sns:ListSubscriptionsByTopic", "sns:ListTopics", "sns:SetSubscriptionAttributes", "sns:SetTopicAttributes", "sns:Subscribe", "sns:Unsubscribe", "states:CreateStateMachine", "states:DeleteStateMachine"], "Effect": "Allow", "Resource": "\*" } ], "Version": "2012-10-17"}

This policy is an example covering almost everything an AWS serverless platform might need. But most of it will not even be used. You can restrict the platform according to your needs and security requirements. At the very least need to access: cloudformation, iam, lambda, logsand functions s3.

Push Review Policy, come up with a name, for example GitLabServerlessPolicy. We click Create policy.

After that, we return to the tab Add userand find the newly created policy (you may need to click the icon Refresh). Check the box next to this policy and click Next.

Click on Next: Tagsor go to the review. The last page should look like this:

After clicking the button Create user, the credentials page for accessing the new AWS account will be displayed. Select Shownext to secret access keyand copy it along with the ID to a secluded place.

AWS Credential Entry

Back to GitLab. We need to enter data into the CI / CD settings of our project. Select Settings -> CI/CDin the left menu.

On this page, you need to expand the section with the variables and enter the AWS credentials:

Use AWS_ACCESS_KEY_IDand AWS_SECRET_ACCESS_KEYas keys for the two values ​​copied from AWS in the previous step. Do not forget to press the button Save variables.

Deploying the first AWS Lambda feature

Now it’s time to deploy the project. If you do this on, you already have access to the GitLab runner for 2,000 free minutes of CI pipeline. If not, then you need to configure the runner.

Go to the menu CI/CD -> Pipelineson the left and press Run Pipeline. For fun, let’s introduce an environment variable with a key and give it any value. This will be used by our function.

We push Run Pipeline, we see how our tasks begin to be carried out. This project template contains tests that will automatically start each time the pipeline runs. Once completed, the “production” task will deploy the code in AWS Lambda and create a page on GitLab Pages. In a few minutes, the process should be completed, and we will be able to visit Settings -> Pagesto see the link where everything turned out.

As a result, we see the following there:

Enter a value and press Run function. This input will go to the serverless function, the result will be displayed in the field Function Output. Please note that there is also an environment value that we provided with the key A_VARIABLE.


How about a simple calculator? Open the Web IDE and make the following changes.

Inside, src/handler.jsadd the following function:

module.exports.add = async function(event) { const A = Number(event.queryStringParameters.A); const B = Number(event.queryStringParameters.B); const result = A + B; return { statusCode: 200, headers: { "Access-Control-Allow-Origin": "\*" }, body: result };};

Open public/index.htmland replace it with the following:

<!DOCTYPE html><html> <head> <title>GitLab Serverless Framework example</title> </head> <body> <h3>Add two values:</h3> <label>A: <input type="text" id="inputA" placeholder="0" name="A"/></label> <label>B: <input type="text" id="inputB" placeholder="0" name="B"/></label> <strong>=</strong> <span id="functionOutput">?</span> <br /> <button>Calculate!</button> <script> fetch("./stack.json").then(response => { response.json().then(myJson => { const functionUrl = myJson.ServiceEndpoint + "/add"; const inputA = document.querySelector("#inputA"); const inputB = document.querySelector("#inputB"); const output = document.querySelector("#functionOutput"); document.querySelector("button").addEventListener("click", () => { const A = Number(inputA.value); const B = Number(inputB.value); fetch(functionUrl + "?A=" + A + "&amp;B=" + B) .then(response => response.text()) .then(result => (output.textContent = result)); }); }); }); </script> </body></html>

Finally, serverless.ymladd the “add” function under “hello”:

functions: hello: handler: src/handler.hello events: - http: path: hello method: get cors: true add: handler: src/handler.add events: - http: path: add method: get cors: true

Commit to the main branch. This will automatically launch a new pipeline. You can visit CI/CD -> Pipelinesand see how it works.

After the deployment is complete, the project page should look like this:

Voila, we just created your own serverless function and deployed it without a single command in the terminal.

The post Running a serverless JS project with GitLab appeared first on TECHY360.

Discussion (0)