Using environment variables with the Slack CLI
Storing and using environment variables in an application allows for certain variables to be maintained outside of the code of the application. You can use environment variables from within Slack functions, triggers, and manifests.
Using environment variables with a custom function
When accessing environment variables from within a custom function, where you store them differs when the app is local versus deployed.
Storing local environment variables
Local environment variables are stored in a .env
file at the root of the project and made available for use in custom functions via the env
context property.
A local .env
file might look like this:
MY_ENV_VAR=asdf1234
Note that changes to your .env
file will be reflected when you restart your local development server.
While the .env
file should never be committed to source control for security reasons, you can see a sample .env
file we've included in the Timesheet approval sample app and the Incident management sample app.
Storing deployed environment variables
When your app is deployed, it will no longer use the .env
file. Instead, you will have to add the environment variables using the env add
command. Environment variables added with env add
will be made available to your deployed app's custom functions just as they are locally; see examples in the next section.
For the above example, we could run the following command before deploying our app:
slack env add MY_ENV_VAR asdf1234
If your token contains non-alphanumeric characters, wrap it in quotes like this:
slack env add SLACK_API_URL "https://dev<yournumber>.slack.com/api/"
Your environment variables are always encrypted before being stored on our servers and will be automatically decrypted when you use them—including when listing environment variables with slack env list
.
Access variables from within function
We can retrieve the MY_ENV_VAR
environment variable from within a custom Slack function via the env
context property like this:
// functions/my_function.ts
import { DefineFunction, SlackFunction } from "deno-slack-sdk/mod.ts";
import { MyFunctionDefinition } from "functions/myfunction.ts"
export default SlackFunction(MyFunctionDefinition, ({ env }) => {
const myEnvVar = env["MY_ENV_VAR"];
// ...
return { outputs: {} };
});
Environment variables also play an important part in making calls to a third-party API. Learn more about how to do that in the FAQ.
Using environment variables with a trigger or manifest
Accessing environment variables from within a trigger definition or when constructing the manifest differs slightly from custom functions.
Whether your app is being run locally or already deployed, constructing these definitions happens entirely on your machine and so the environment variables stored on your machine are used.
Storing environment variables
Environment variables used in trigger or manifest definitions should be saved in the local .env
file for your project as shown above. The values from this file are collected and used when generating these definitions.
Regardless of whether you're working with a local or deployed app, the same values from this file will be used. Read on to learn how to access these stored variables in code.
Accessing variables from a trigger or manifest
The Deno runtime provides a helpful load
function to autoload environment variables as part of the dotenv
module of the standard library. We'll leverage this to easily access our environment variables.
Including this module in code will automatically import local environment variables for immediate use! Start by adding the latest version of this module to your import_map.json
:
{
"imports": {
"deno-slack-sdk/": "https://deno.land/x/deno_slack_sdk@a.b.c/",
"deno-slack-api/": "https://deno.land/x/deno_slack_api@x.y.z/",
"std/": "https://deno.land/std@0.202.0/"
}
}
Then, you can import the module into any file that makes use of environment variables and start accessing the environment with Deno.env.get("VARIABLE_NAME")
like so:
// manifest.ts
import { Manifest } from "deno-slack-sdk/mod.ts";
import ExampleWorkflow from "./workflows/example_workflow.ts";
import "std/dotenv/load.ts";
export default Manifest({
name: "Chatbot4000",
displayName: Deno.env.get("CHATBOT_DISPLAY_NAME"),
description: "Workflows for communicating with an imagined chatbot",
icon: "assets/icon.png",
workflows: [ExampleWorkflow],
outgoingDomains: [
Deno.env.get("CHATBOT_API_URL")!,
],
botScopes: ["commands", "chat:write", "chat:write.public"],
});
After including this new module, you may have to run deno cache manifest.ts
to refresh your local dependency cache.
Variable values such as these are commonly used to specify outgoing domains used by functions, channel IDs for event triggers, or client IDs of an external authentication provider. But, don't let that limit you — environment variables can be used in so many other places!
Requiring environment variables values
Setting values for environment variables can sometimes be forgotten, which can cause problems at runtime. Catching errors for these missing values early is often better than waiting for that runtime problem.
Including a !
with your call to Deno.env.get()
will ensure this value is defined at the time of building a definition and will throw an error otherwise.
The previous example uses this pattern to ensure an outgoing domain is always set:
outgoingDomains: [
Deno.env.get("CHATBOT_API_URL")!,
],
With this addition, running slack deploy
without defining a value for CHATBOT_API_URL
in the .env
file will throw an error to give you a chance to set it before actually deploying!
Enabling debug mode
The included environment variable SLACK_DEBUG
can enable a basic debug mode. Set SLACK_DEBUG
to true
to have all function-related payloads logged.
For local apps, add the following to your .env
file:
SLACK_DEBUG=true
For deployed apps, run the following command before deployment:
slack env add SLACK_DEBUG true
Included local and deployed variables
Slack provides two environment variables by default, SLACK_WORKSPACE
and SLACK_ENV
. The workspace name is specified by SLACK_WORKSPACE
and SLACK_ENV
provides a distinction between the local
and deployed
app. Use these values if you want to have different values based on the workspace or environment that the app is installed in.
These variables are automatically included when generating the manifest or triggers only. For access from within a custom function, these variables can be set from the .env
file or with the env add
command.
A custom WorkspaceMapSchema
can be created and used with these variables to decide which values to use for certain instances of an app. This can be used as an alternative to a local .env
file or in conjunction with it. The following snippet works well for inclusion in your app manifest, or for triggers (for example, to change event trigger channel IDs):
// Custom schemas can be defined for workspace values
type WorkspaceSchema = { channel_id: string };
type WorkspaceMapSchema = {
[workspace: string]: {
[environment: string]: WorkspaceSchema;
};
};
// Custom values can be set for each known workspace
export const workspaceValues: WorkspaceMapSchema = {
beagoodhost: {
deployed: {
channel_id: "C123ABC456",
},
local: {
channel_id: "C123ABC456",
},
},
sandbox: {
deployed: {
channel_id: "C222BBB222",
},
local: {
channel_id: "C222BBB222",
},
},
};
// Fallback options can also be defined
export const defaultValues: WorkspaceSchema = {
channel_id: "{{data.channel_id}}",
};
// Included environment variables will determine which value is used
const environment = Deno.env.get("SLACK_ENV") || "";
const workspace = Deno.env.get("SLACK_WORKSPACE") || "";
const { channel_id } = workspaceValues[workspace]?.[environment] ??
defaultValues;