Serverless Haskell

Deploying Haskell code onto AWS Lambda using Serverless.
Requirements
Usage
-
Create a Stack package for your code:
stack new mypackage
LTS 9-12 are supported, older versions are likely to work too but untested.
-
Initialise a Serverless project inside the Stack package directory and install
the serverless-haskell
plugin:
cd mypackage
npm init .
npm install --save serverless serverless-haskell@x.y.z
The version of the NPM package to install must match the version of the
Haskell package.
-
Create serverless.yml
with the following contents:
service: myservice
provider:
name: aws
runtime: nodejs8.10
functions:
myfunc:
handler: mypackage.myfunc
# Here, mypackage is the Haskell package name and myfunc is the executable
# name as defined in the Cabal file. The handler field may be prefixed
# with a path of the form `dir1/.../dirn`, relative to `serverless.yml`,
# which points to the location where the Haskell package `mypackage` is
# defined. This prefix is not needed when the Stack project is defined at
# the same level as `serverless.yml`.
plugins:
- serverless-haskell
-
Write your main
function:
import qualified Data.Aeson as Aeson
import AWSLambda
main = lambdaMain handler
handler :: Aeson.Value -> IO [Int]
handler evt = do
putStrLn "This should go to logs"
print evt
pure [1, 2, 3]
-
Use sls deploy
to deploy the executable to AWS Lambda. Note: sls deploy function
is not supported yet.
The serverless-haskell
plugin will build the package using Stack and upload
it to AWS together with a JavaScript wrapper to pass the input and output
from/to AWS Lambda.
You can test the function and see the invocation results with sls invoke myfunc
.
To invoke the function locally, use sls invoke local -f myfunc
.
API Gateway
This plugin supports handling API Gateway requests. Declare the HTTP events
normally in serverless.yml
and use
AWSLambda.Events.APIGateway
in the handler to process them.
Serverless Offline can be used for local testing of API Gateway requests.
Notes
sls deploy function
is not supported yet.
- Only AWS Lambda is supported at the moment. Other cloud providers would
require different JavaScript wrappers to be implemented.
See
AWSLambda
for documentation, including additional options to control the deployment.
Testing
- Haskell code is tested with Stack:
stack test
.
- JavaScript code is linted with
eslint
.
Integration tests
Integration test verifies that the project can build and deploy a complete
function to AWS, and it runs with expected functionality.
Integration test is only automatically run up to deployment due to the need for
an AWS account. To run manually:
- Ensure you have the required dependencies:
curl
, jq, NPM, pwgen
and
Stack.
- Get an AWS account and add the access credentials into your shell environment.
- Run
./integration-test/run.sh
. The exit code indicates success.
- To verify just the packaging, without deployment, run
./integration-test/run.sh --dry-run
.
- By default, the integration test is run with LTS 12. To specify a different
series, use
RESOLVER_SERIES=lts-9
.
Releasing
- Run the integration tests.
- Install bumpversion:
pip install bumpversion
.
- Run
bumpversion major|minor|patch
.
- Run
git push --tags && git push
.