Pitfalls of Serverless Framework with GitHub Actions

2021.09.07

Since its inception; GitHub Actions is becoming the de-facto platform to automate developer workflows.

I feel it's not just a CI/CD tool, but instead a platform for many kinds of workflows.

This article talks about, two subtle issues which can spoil your fun with GitHub Actions.

Prequesites

  • Understanding of GitHub Actions terminologies and concept.
  • Experience with creating CI/CD workflow using the serverless framework in GitHub Actions.

About the Workflow or Pipeline

  • Whenever a user pushes to the main branch (on their GitHub repository), it will trigger an event for an action, which result in automatic deployment of a lambda function using serverless framework.

Issues

Serverless GitHub-action fails with sub-directories.

  • Serverless github-action, works perfectly well, if serverless.yml file is present in the root of the project structure.

  • As the app grows and mature, it's in the best interest ( Best practices too) for a developer to split serverless app and microservices into separate directories.

  • Using this Github action with sub-directories, will result in the error where the action is unable to deploy lambda as it couldn't find serverless.yml with the correct path.

    Solution:- DROP this GitHub action and GO FOR MANUAL APPROACH.

    name: For Production
    
    on:
    push:
        branches: [main]
    jobs:
    build:
        runs-on: ubuntu-latest
    
        strategy:
        matrix:
            node-version: [16.x]
            # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
    
        steps:
        - uses: actions/checkout@v2
        - name: Use Node.js ${{ matrix.node-version }}
            uses: actions/setup-node@v2
            with:
            node-version: ${{ matrix.node-version }}
            cache: 'npm'
            cache-dependency-path: ./backend-operations/package-lock.json
        - name: Create env file
            run: |
            touch ./backend-operations/.env
            echo JWKS_URI=${{secrets.JWKS_URI}} >> ./backend-operations/.env
            echo AUDIENCE=${{ secrets.AUDIENCE }} >> ./backend-operations/.env
            echo TOKEN_ISSUER=${{ secrets.TOKEN_ISSUER }} >> ./backend-operations/.env
        - run: npm ci
            working-directory: ./backend-operations
        - run: npm run build --if-present
            working-directory: ./backend-operations
        - run: npm test
            working-directory: ./backend-operations
        - name: Install Serverless Framework
            run: npm install -g serverless
        - name: Serverless Authentication
            run: sls config credentials --provider aws --key ${{secrets.AWS_ACCESS_KEY_ID}} --secret ${{secrets.AWS_SECRET_ACCESS_KEY}}
        - name: Deploy to AWS
            run: serverless deploy --verbose
            working-directory: './backend-operations'
        - name: Upload coverage to Codecov
            uses: codecov/codecov-action@v1

org in serverless.yml results in Login Error.

  • serverless framework template generate a serverless.yml which has org property.
    • Even after adding AWS credentials, org in serverless.yml results in:-
    You are not currently logged in. Follow instructions in http://slss.io/run-in-cicd to setup env vars for authentication
  • The issue is Serverless Framework tries to log you into your Serverless Pro account when you have a Serverless organization specified in your serverless.yml.

  • If the org is specified but you have not logged in to Serverless, you will get this error.

    Solution:- Either comment out or remove the org.

    service: node-serverless-api
    
    app: node-serverless-api
    
    frameworkVersion: '2'
    
    provider:
    name: aws
    runtime: nodejs12.x
    lambdaHashingVersion: 20201221
    region: ap-southeast-1
    iam:
        role:
        statements:
            - Effect: Allow
            Action:
                - dynamodb:DescribeTable
                - dynamodb:Query
                - dynamodb:Scan
                - dynamodb:GetItem
                - dynamodb:PutItem
                - dynamodb:UpdateItem
                - dynamodb:DeleteItem
            Resource: arn:aws:dynamodb:ap-southeast-1:*:*
    
    resources:
    Resources:
        Table:
        Type: 'AWS::DynamoDB::Table'
        Properties:
            AttributeDefinitions:
            - AttributeName: userId
                AttributeType: S
            - AttributeName: originalUrl
                AttributeType: S
            KeySchema:
            - AttributeName: userId
                KeyType: HASH
            - AttributeName: originalUrl
                KeyType: RANGE
            ProvisionedThroughput:
            ReadCapacityUnits: 1
            WriteCapacityUnits: 1
            TableName: 'table_name'
    
    functions:
    customAuthorizer:
        handler: authorizer/authorizer.auth
    hello:
        handler: serverless.handler
        events:
        - http:
            path: /
            method: ANY
        - http:
            path: /{proxy+}
            method: ANY
        - http:
            path: /auth-ops
            method: ANY
            authorizer: customAuthorizer
            cors: true
        - http:
            path: /auth-ops/{proxy+}
            method: ANY
            authorizer: customAuthorizer
            cors: true

Sum-up

In this article, we saw that there are always some advantages and disadvantages of a new tool, technology, even GitHub actions too. After all, somebody rightly said, the technology of tomorrow is the result of today's bugs.

Till then, Happy Learning!