<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Bielen</title>
    <description>The latest articles on DEV Community by Alex Bielen (@alexbielen).</description>
    <link>https://dev.to/alexbielen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F133478%2F0e873f85-505b-48e3-ae21-2e03102e90f3.jpeg</url>
      <title>DEV Community: Alex Bielen</title>
      <link>https://dev.to/alexbielen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexbielen"/>
    <language>en</language>
    <item>
      <title>Deploy a Serverless API with GitHub Actions</title>
      <dc:creator>Alex Bielen</dc:creator>
      <pubDate>Mon, 04 Feb 2019 20:04:21 +0000</pubDate>
      <link>https://dev.to/alexbielen/deploy-a-serverless-api-with-github-actions-3k6o</link>
      <guid>https://dev.to/alexbielen/deploy-a-serverless-api-with-github-actions-3k6o</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Heads up before you read any further:&lt;/strong&gt; this post is out of date! GitHub Actions switched to YAML as its configuration language and changed some of the semantics. Feel free to continue reading if you're interested in why I think GitHub actions is an important step in social coding or looking at how GitHub Actions worked during its beta release. Happy coding!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have you heard the saying “releases should be boring”? This is the unofficial motto of Continuous Integration and Continuous Deployment (CI/CD). GitHub Actions, announced at the 2018 GitHub Universe Conference, aims to bring boring releases to &lt;em&gt;all&lt;/em&gt; users in the GitHub Ecosystem. Today we’ll start by covering why GitHub Actions is an important development in social coding and then we'll look at the core concepts that Actions uses to create an automation system. Lastly, we’ll build and deploy a serverless API using AWS, the Serverless Framework, and GitHub Actions. Note that the following prerequisites are required to complete the  API tutorial: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;a href="https://aws.amazon.com/free/" rel="noopener noreferrer"&gt;AWS Free Tier&lt;/a&gt; Account&lt;/li&gt;
&lt;li&gt;An AWS IAM User with Programmatic Access (see &lt;a href="https://github.com/serverless/serverless/issues/1439" rel="noopener noreferrer"&gt;here&lt;/a&gt; for a good starter IAM Policy. Note that you should always follow the Principle of Least Privilege when setting up an IAM User.) &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; of the user above. &lt;/li&gt;
&lt;li&gt;A GitHub Account enrolled in the &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions Beta&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A clone or fork of the repo &lt;a href="https://github.com/twobulls/github_actions" rel="noopener noreferrer"&gt;https://github.com/twobulls/github_actions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Social Coding
&lt;/h2&gt;

&lt;p&gt;Social coding is a software development practice centered around the belief that community and collaboration build the best software. There are numerous examples of social coding, including GitHub, open source software in general, and package managers like npm. Social coding allows builders to share effort and to work collaboratively on software. GitHub Actions is an important step forward in social coding because it introduces a feasible way to share automation.&lt;/p&gt;

&lt;p&gt;Automation and CI/CD tend to be boilerplate-heavy. This leads to repetitive code and time wasted on work that doesn’t actually differentiate your application. Actions enables streamlined access to automation tools &lt;em&gt;and&lt;/em&gt; the ability to easily share these tools. Actions is Docker-based which affords portability and ease-of-sharing. GitHub takes advantage of this by allowing builders to incorporate Actions from any public GitHub repository or any Docker image on DockerHub. Of course, if a particular Action does not exist a builder can create custom Actions and optionally share them in a public repository. The combination of integrated automation tools and ease-of-sharing is what makes Actions an excellent strategic opportunity for GitHub and a boon for builders in GitHub ecosystem.&lt;/p&gt;

&lt;p&gt;In any large-scale social coding platform it’s important to be aware of potential issues caused by version changes and vulnerabilities introduced accidentally or maliciously. Actions is no exception. GitHub has addressed some of the issues including access control and version-pinning, but there are some other issues which we will explore later. Next, we’ll dive into the core concepts of GitHub Actions. &lt;/p&gt;

&lt;h2&gt;
  
  
  Core Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Visual Editor or Configuration Language
&lt;/h3&gt;

&lt;p&gt;Workflows can be created in code or using the visual editor. The following examples will use the configuration language that Actions provides.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mifve4bt06sxxjj4hn7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mifve4bt06sxxjj4hn7.png" alt="Visual Editor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Actions
&lt;/h3&gt;

&lt;p&gt;Actions are “code that run in Docker containers”.  Although Actions share their name with the wider service, they are the individual units of work to be performed. Each Action has a unique name and one required attribute, namely  &lt;code&gt;uses&lt;/code&gt;. An Action is defined using the &lt;code&gt;action&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Unique Name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./actions/helloworld"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;uses&lt;/code&gt; attribute can reference an Action in the same repo, a public Action in a GitHub repository, or a public Docker container hosted on Dockerhub. Don't worry too much if you are unfamiliar with Docker. We will do a brief overview of the commands used later on. This Action references the following Docker container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# actions/helloworld/Dockerfile&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.11.4-stretch&lt;/span&gt;

&lt;span class="k"&gt;LABEL&lt;/span&gt;&lt;span class="s"&gt; "com.github.actions.name"="Echo Hello World"&lt;/span&gt;
&lt;span class="k"&gt;LABEL&lt;/span&gt;&lt;span class="s"&gt; "com.github.actions.description"="Say Hello to the World!"&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; echo "Hello World!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can provide other optional attributes depending on your needs. A few common attributes including &lt;code&gt;needs&lt;/code&gt;, &lt;code&gt;secrets&lt;/code&gt;, and &lt;code&gt;args&lt;/code&gt; will be discussed later. For a full list of attributes see the &lt;a href="https://developer.github.com/actions/creating-workflows/workflow-configuration-options/#actions-attributes" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Events
&lt;/h3&gt;

&lt;p&gt;Events are “happenings” within your GitHub repository including &lt;code&gt;pull_request_review&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;, and &lt;code&gt;issues&lt;/code&gt;. Events trigger different workflows and have different environment variables depending on the type of event. This is important because the commit that the Action runs against depends on the event type triggering the Action. &lt;/p&gt;

&lt;p&gt;For example, the &lt;code&gt;release&lt;/code&gt; event resolves the &lt;code&gt;GITHUB_SHA&lt;/code&gt; (the commit hash) by the tag that triggered the release. So, an Action triggered by the &lt;code&gt;release&lt;/code&gt; event uses the latest commit SHA of the branch.&lt;/p&gt;

&lt;p&gt;But, the &lt;code&gt;push&lt;/code&gt; event’s &lt;code&gt;GITHUB_SHA&lt;/code&gt; is “Event specific unless deleting a branch (when it's the default branch)”. This means that it grabs the commit SHA directly from the triggering event. &lt;/p&gt;

&lt;p&gt;You can read more about the available events and the SHA resolutions in the &lt;a href="https://developer.github.com/actions/creating-workflows/workflow-configuration-options/#events-supported-in-workflow-files" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Workflows
&lt;/h3&gt;

&lt;p&gt;Workflows are composed of Actions and are triggered by Events. Put another way, Workflows combine Events and Actions. Workflows are defined using the &lt;code&gt;workflow&lt;/code&gt; block. Each &lt;code&gt;workflow&lt;/code&gt; block needs a unique name and has two required attributes: &lt;code&gt;on&lt;/code&gt; and &lt;code&gt;resolves&lt;/code&gt;. In the &lt;code&gt;on&lt;/code&gt; attribute you define the Event type that triggers the Workflow. In the &lt;code&gt;resolves&lt;/code&gt; attribute you describe the Actions to be “resolved” by the workflow. The &lt;code&gt;workflow&lt;/code&gt; block definition reads like a sentence in English: “The workflow named Deploy Staging, on the release event, resolves build, test and deploy.”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;workflow&lt;/span&gt; &lt;span class="s2"&gt;"Deploy Staging"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"release"&lt;/span&gt;
  &lt;span class="nx"&gt;resolves&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"deploy"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;resolves&lt;/code&gt; attribute deserves a little more attention, which we will cover next.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency
&lt;/h3&gt;

&lt;p&gt;Dependency between Actions can be expressed using the &lt;code&gt;needs&lt;/code&gt; attribute.  In the example below, “Deploy” is dependent on the successful completion of “Build”, “Test”, and “Lint”. You’ll notice that we include only the “Deploy” action in the &lt;code&gt;resolves&lt;/code&gt; attribute of the Workflow block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;workflow&lt;/span&gt; &lt;span class="s2"&gt;"Deploy to Staging"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"release"&lt;/span&gt;
  &lt;span class="nx"&gt;resolves&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Deploy"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Build"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"docker://image1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Test"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"docker://image2"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Lint"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"docker://image3"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Deploy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;needs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Lint"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"docker://image4"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because the “Deploy” Action is dependent on the completion of the “Build”, “Test”, and “Lint” actions. We can express complex dependencies using this style.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Parallelism
&lt;/h3&gt;

&lt;p&gt;My initial assumption was that, in the workflow above, “Build”, “Test”, and “Lint” would run in parallel considering they are independent Actions. In practice, this hasn’t been the case. I tried the following workflow format, which I also expected would run in parallel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;workflow&lt;/span&gt; &lt;span class="s2"&gt;"Deploy to Staging"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"release"&lt;/span&gt;
  &lt;span class="nx"&gt;resolves&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Build"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"docker://image1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Test"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"docker://image2"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again, this was not the case and the above did not run in parallel. According to the documentation “[w]hen more than one action is listed [in the &lt;code&gt;resolves&lt;/code&gt; attribute] the actions are executed in parallel.” This may just be a limitation of the Public Beta and I imagine Actions will allow parallelism in the future. &lt;/p&gt;

&lt;h3&gt;
  
  
  Workspace
&lt;/h3&gt;

&lt;p&gt;The Workspace is the directory in which your Action will do its work. The workspace directory contains a copy of the repository set to the &lt;code&gt;GITHUB_SHA&lt;/code&gt;  from the Event that triggered the workflow. An Action can modify this directory, access the contents, create binaries, etc. We’ll use the Workspace to store the compiled Go binary generated by our Action. &lt;/p&gt;

&lt;h3&gt;
  
  
  Secrets Management
&lt;/h3&gt;

&lt;p&gt;Actions allow access to secrets through the &lt;code&gt;secrets&lt;/code&gt; attribute. You have to explicitly list which secrets an Action has permission to access. In the following example the “Deploy Hello World” Action is given permission to access the &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and the &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Deploy Hello World"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;needs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Build Hello World"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Lint Hello World"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"serverless/github-action@master"&lt;/span&gt;
    &lt;span class="nx"&gt;secrets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"AWS_ACCESS_KEY_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"AWS_SECRET_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"deploy"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secrets are added through the repository settings panel and are exposed as environment variables to the Action. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjg77xjdxc2u27gdv5zx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjg77xjdxc2u27gdv5zx.png" alt="Secrets."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: GitHub Actions recommends that during the Public Beta you do not store any production secrets at this time. For more information read the &lt;a href="https://developer.github.com/actions/creating-workflows/storing-secrets/" rel="noopener noreferrer"&gt;official documentation.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Deploy a Serverless API Using GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Next, we’ll build a serverless API. The Workflow will build, lint, and deploy on each &lt;code&gt;push&lt;/code&gt; to the master branch in our repository.&lt;/p&gt;
&lt;h3&gt;
  
  
  Secrets
&lt;/h3&gt;

&lt;p&gt;Grab the &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; from the IAM user you created. In the “Settings” page in your repository click on “Secrets” and add the &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;. Note: during the public beta do not store any production secrets in the repository. &lt;/p&gt;
&lt;h3&gt;
  
  
  Serverless API Code
&lt;/h3&gt;

&lt;p&gt;Serverless Framework handles infrastructure and provisioning of Serverless Applications. The infrastructure is defined in the &lt;code&gt;serverless.yml&lt;/code&gt; file, so that’s where we’ll look first. Serverless uses a minimal configuration language to link events with the desired computation. Here we are creating an http api &lt;code&gt;GET /hello&lt;/code&gt; and handling the API event with the Go binary in  &lt;code&gt;bin/hello&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# serverless.yml&lt;/span&gt;

&lt;span class="nn"&gt;...&lt;/span&gt;

&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bin/hello&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we’ll view the source code for the &lt;code&gt;bin/hello&lt;/code&gt; binary. This code uses Serverless Framework’s default Go template with a slight modification to the &lt;code&gt;message&lt;/code&gt; body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// hello/main.go&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyResponse&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;

    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
        &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello From Two Bulls!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;404&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTMLEscape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IsBase64Encoded&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;Headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function returns an &lt;code&gt;APIGatewayProxyResponse&lt;/code&gt; which defines the http status code, headers, and response body.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Makefile&lt;/code&gt; defines the build steps that the Action will run. Two things worth noting: This is using Go 1.11 module system and we’re setting the &lt;code&gt;GOOS&lt;/code&gt; environment variable to &lt;code&gt;linux&lt;/code&gt; since we’ll be running this function in AWS Lambda.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GO111MODULE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;on
    &lt;span class="nb"&gt;env &lt;/span&gt;&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build &lt;span class="nt"&gt;-ldflags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-s -w"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; bin/hello hello/main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GitHub Actions Code
&lt;/h3&gt;

&lt;p&gt;Next we’ll take a look at the GitHub Actions Workflow and Action definitions. Here we’ve defined a Workflow that is triggered on every &lt;code&gt;push&lt;/code&gt; event and resolves the “Deploy Hello World” Action. The “Deploy Hello World” Action &lt;code&gt;uses&lt;/code&gt; an external Action, maintained by the Serverless GitHub organization. To refer to this external Action we use the organization name, the repo name, and the commit-ish that we’d like pin the version to. Additionally, we explicitly grant this Action access to the &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; secrets that we created earlier. The &lt;code&gt;args&lt;/code&gt; attribute is the argument that we pass to the Action -- since this Action is wrapping the Serverless Framework we want to pass the &lt;code&gt;deploy&lt;/code&gt; argument, but any Serverless command can be run here.  The “Deploy Hello World” Action &lt;code&gt;needs&lt;/code&gt; the “Build Hello World” and “Lint Hello World” Actions, but these are defined in our repository and thus can be referenced using the relative path syntax. These will complete &lt;em&gt;before&lt;/em&gt; the “Deploy Hello World Action”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;workflow&lt;/span&gt; &lt;span class="s2"&gt;"New workflow"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"push"&lt;/span&gt;
    &lt;span class="nx"&gt;resolves&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Deploy Hello World"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Build Hello World"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./actions/build"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Lint Hello World"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./actions/lint"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="s2"&gt;"Deploy Hello World"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;needs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Build Hello World"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Lint Hello World"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;uses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"serverless/github-action@master"&lt;/span&gt;
    &lt;span class="nx"&gt;secrets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"AWS_ACCESS_KEY_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"AWS_SECRET_ACCESS_KEY"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"deploy"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;p&gt;The Actions defined in our repository reference Docker files. We’ll do a quick overview of the Docker syntax used here and what it means.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FROM&lt;/code&gt; defines the base image that we’ll use for our container. We’re using &lt;code&gt;golang:1.11.4-stretch&lt;/code&gt; which comes with the dependencies necessary for building Go. Additionally, it comes with the &lt;code&gt;go&lt;/code&gt; tool installed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LABEL&lt;/code&gt; provides metadata about our container. We can include a name, description, and other metadata, including how the Action should appear in the visual editor. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;CMD&lt;/code&gt; is the command that we’d like to run when the Docker container starts. This is where we’ll spend most of our time writing the commands we’d like our container to perform. &lt;/p&gt;

&lt;p&gt;With that quick introduction we can look at the &lt;code&gt;Dockerfile&lt;/code&gt;s in our repository. The “Build Hello World” container runs &lt;code&gt;make&lt;/code&gt; . Make runs the steps in the &lt;code&gt;Makefile&lt;/code&gt; discussed above. The “Lint Hello World” container runs &lt;code&gt;go vet&lt;/code&gt; against the Go source code in our repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# actions/build/Dockerfile&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.11.4-stretch&lt;/span&gt;

&lt;span class="k"&gt;LABEL&lt;/span&gt;&lt;span class="s"&gt; "com.github.actions.name"="Build Hello World"&lt;/span&gt;
&lt;span class="k"&gt;LABEL&lt;/span&gt;&lt;span class="s"&gt; "com.github.actions.description"="Run make to build the Golang binary."&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; make&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# action/lint/Dockerfile&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.11.4-stretch&lt;/span&gt;

&lt;span class="k"&gt;LABEL&lt;/span&gt;&lt;span class="s"&gt; "com.github.actions.name"="Lint Hello World"&lt;/span&gt;
&lt;span class="k"&gt;LABEL&lt;/span&gt;&lt;span class="s"&gt; "com.github.actions.description"="Lint the hello world application using go vet."&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; cd hello &amp;amp;&amp;amp; go vet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy!
&lt;/h3&gt;

&lt;p&gt;With everything set up, we’re ready to deploy the API. You can make a change to &lt;code&gt;README.md&lt;/code&gt;, commit, and push. Open the Actions panel in the repository and you can watch as the actions queue and begin work. You can open the logs and watch the log output as well. When an Action completes successfully you’ll see a green checkmark on each of the Actions. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mifve4bt06sxxjj4hn7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mifve4bt06sxxjj4hn7.png" alt="Workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, view the logs of the “Deploy Hello World” Action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Serverless: Stack update finished...
Service Information
service: go-github-actions
stage: dev
region: us-east-1
stack: go-github-actions-dev
api keys:
  None
endpoints:
  GET - https://xxrefpqkp2.execute-api.us-east-1.amazonaws.com/dev/hello
functions:
  hello: go-github-actions-dev-hello
layers:
  None
Serverless: Removing old service artifacts from S3...

### SUCCEEDED Deploy Hello World 23:54:39Z (1m23.488s)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The URL for your API is listed in endpoints. Open the url and you’ll see the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Hello From Two Bulls!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! A serverless API deployed by GitHub Actions. &lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;There are a few limitations to be aware of when using GitHub Actions. First, it is still in a limited public beta, so changes to APIs, features, and limits can be expected to change. &lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow Limitations
&lt;/h3&gt;

&lt;p&gt;Additionally, there are limits to concurrency, computation, and total time. Make sure that these limitation fit your current use case before deciding to use GitHub actions. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run for 58 minutes (queueing AND execution time) &lt;/li&gt;
&lt;li&gt;Each workflow can run up to 100 actions&lt;/li&gt;
&lt;li&gt;Two workflows concurrently per repository&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read the full list in the &lt;a href="https://developer.github.com/actions/creating-workflows/workflow-configuration-options/#workflow-limitations" rel="noopener noreferrer"&gt;official documentation.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Limitations
&lt;/h3&gt;

&lt;p&gt;As hinted at earlier, Actions mitigates some potential security issues by allowing version-pinning and explicit access control to secrets. When using external actions you need to trust the author. When integrating an external Action you should ask a few questions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is there a way to know that an Action is compromised from a security perspective? &lt;/li&gt;
&lt;li&gt;How much access does an external action need?&lt;/li&gt;
&lt;li&gt;What is the external action doing with your secrets if you grant access? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These problems are not necessarily unique to GitHub Actions, but instead, are a wider problem in the social coding era. A few potential mitigations for this problem would be alerts about compromised external Actions and a freeze on Workflows using compromised Actions. But until those features are implemented, be sure to trust the Actions that you're using. &lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Today you learned about GitHub Actions and deployed a serverless API. GitHub Actions is extremely flexible and this just scratches the surface of what is possible. Because of the diversity of events available, Actions can integrate with GitHub Issues and with external communication tools like Slack. You can build automation for lots of common tasks. But most importantly, you can share that automation and use automation that others have already built. &lt;/p&gt;

</description>
      <category>github</category>
      <category>go</category>
      <category>serverless</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
