Serverless Plugin: Exporting Environment Variables and Stack Outputs
Tags: showdev, serverless, aws, productivity
Published: 2023-08-21 10:00:00

I recently published my [`serverless-exports-plugin`](https://www.npmjs.com/package/serverless-exports-plugin) for the Serverless Framework. While it shares similarities with existing plugins like [serverless-export-env](https://github.com/arabold/serverless-export-env) and [serverless-export-outputs](https://www.npmjs.com/package/serverless-export-outputs), my plugin supports to export both environment variables and stack outputs.

## What It Does
The plugin retrieves environment variables and stack outputs specified in `serverless.yaml` and saves them to local files during deployment.

Here's a sample Serverless project to illustrate:

```yaml
service: acme-service
frameworkVersion: '3'

plugins:
  - serverless-exports-plugin

custom:  
  exports:
    environment:
      file: .env.${sls:stage}
      format: env
      overwrite: true    
    stack:
      file: .serverless/stack-outputs.txt
      format: env
      overwrite: true    

provider:
  name: aws
  runtime: nodejs18.x
  environment:
    FOO: bar
    STAGE: ${sls:stage}
    REGION: ${aws:region}
    SERVICE: ${self:service}

functions:
  hello:
    handler: index.handler

resources:
  Resources:
    bucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:service}-${sls:stage}-bucket
  Outputs:
    Foo:
      Value: bar
    BucketName:
      Value: !Ref bucket

```

When deployed using `serverless deploy --stage dev`:

![Terminal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zohmxcnocffei02jyey.png)

The defined environment variables are saved in a file `.env.dev`:

```sh
# .env.dev
FOO: bar
STAGE: dev
REGION: us-east-1
SERVICE: acme-service
```

The outputs from the stack are written to the `.serverless/stack-outputs.txt` file.

```sh
# .serverless/stack-outputs.txt
ServerlessDeploymentBucketName: acme-service-dev-serverlessdeploymentbuck-ab4cd786
HelloLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:000000000000:function:acme-service-dev-hello:1
Foo: bar
BucketName: acme-service-dev-bucket
```

Note, that the stack outputs contain additional keys from the Serverless Framework that have not been explicitly defined.

## Why I Created It
Although I designed it for a specific need, there are numerous other applications. For instance, I've set up an S3 bucket and a CloudFront distribution in a Serverless project to host a website. When I need to deploy the website — whether locally or in CI — I first deploy the infrastructure resources and then upload the web assets (HTML, JS, CSS) to S3. To streamline this into a single script, I needed the Serverless environment variables and stack outputs with their evaluated values.

The deploy script is as follows:

```sh
#!/bin/bash

# Verify if the STAGE environment variables is set
if [ -z "$STAGE" ]; then
  echo "Environment variable STAGE is not defined"
  exit 1
fi

# Deploy Serverless service
# This produces a .env.<STAGE> file and a .serverless/stack-outputs.txt file
serverless deploy --stage "$STAGE" 

# Build Vite application
# This loads the .env.<STAGE> file with mode=<STAGE> 
vite build --mode "$STAGE"

# Stack outputs are generated during the Serverless deployment 
# These include the S3 bucket name
STACK_OUTPUTS_FILE=".serverless/stack-outputs.txt"

# Read the file and set each line as an environment variable
while IFS="=" read -r key value; do
    export "$key=$value"
done < "$STACK_OUTPUTS_FILE"

# Upload the bundled app to the S3 bucket
# $BucketName is an output from the stack outputs
aws s3 sync "dist/" "s3://$BucketName"

# Additional steps
# ...
```

## What’s Ahead
There are several features I'm still working on. At present, only the `.env` format is available for exporting. However, I plan to add support for other formats, including JSON, TOML, and YAML. To provide even greater versatility, exports might be relayed to a JavaScript handler function rather than being saved to a file.

Furthermore, only globally specified environment variables are currently exported. I intend to ensure function-level variables are also exported. In addition, I plan to implement support for including and excluding specific keys that are exported.

{% embed https://github.com/zirkelc/serverless-exports-plugin %}

There are likely many bugs I'm not yet aware of, so contributions and feedback are very welcome!

---

I hope you found this post helpful. If you have any questions or comments, feel free to leave them below. If you'd like to connect with me, you can find me on [LinkedIn](https://www.linkedin.com/in/christian-zirkel/) or [GitHub](https://github.com/zirkelc). Thanks for reading!