# Serverless Haskell
[](https://travis-ci.org/seek-oss/serverless-haskell)
[](https://hackage.haskell.org/package/serverless-haskell)
[](https://www.stackage.org/lts/package/serverless-haskell)
[](https://packdeps.haskellers.com/feed?needle=serverless-haskell)
[](https://www.npmjs.com/package/serverless-haskell)
Deploying Haskell code onto [AWS Lambda] using [Serverless].
## Requirements
* AWS account
* [Stack]
* [NPM]
* [Docker]
## Usage
* Create a [Stack] package for your code:
```shell
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:
```shell
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:
```yaml
service: myservice
provider:
name: aws
runtime: haskell
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:
```haskell
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.
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](https://hackage.haskell.org/package/serverless-haskell/docs/AWSLambda-Events-APIGateway.html)
in the handler to process them.
[Serverless Offline] can be used for local testing of API Gateway requests.
### Notes
* Only AWS Lambda is supported at the moment. Other cloud providers would
require different JavaScript wrappers to be implemented.
See
[AWSLambda](https://hackage.haskell.org/package/serverless-haskell/docs/AWSLambda.html)
for documentation, including additional options to control the deployment.
## Development
Currently, apart from the `master` branch, an `v0.6.x` branch is maintained with
no breaking changes since 0.6.0, for inclusion into Stackage LTS 12. For
bugfixes and new features that do not change the existing behavior, please
target `v0.6.x`. For anything else, target `master`.
Changes to the LTS branch will be forward ported to the `master` branch after
releasing.
### 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
* Ensure you are on a correct branch (`v0.6.x` or `master`).
* Ensure that all the changes are reflected in the changelog.
* Run the integration tests.
* Run `./bumpversion major|minor|patch`. This will increment the version number,
update the changelog, create and push the Git tag and the branch.
* If you have released an LTS version, merge the version branch into `master`,
taking care of the conflicts around version numbers and changelog, and release
the latest version as well.
[AWS Lambda]: https://aws.amazon.com/lambda/
[Docker]: https://www.docker.com/
[jq]: https://stedolan.github.io/jq/
[NPM]: https://www.npmjs.com/
[Serverless]: https://serverless.com/framework/
[Serverless Offline]: https://github.com/dherault/serverless-offline
[Stack]: https://haskellstack.org