Build multiple versions of your app from a single code base

In this track, we'll be learning about environment variables and deploying your app to different workspaces. At any moment in time, you can have multiple versions of your app--say one for staging and another in production. Using slack deploy in conjunction with environment variables, you can have a single code base but deploy multiple versions of your app without having to recreate your app on multiple workspaces. Environment variables also allow you to keep secret things secret, like API keys. By storing these in environment variables, you can keep your app secure and avoid hard coding sensitive data in your app.

For illustrative purposes, we're going to use an imaginary third party API key. This is something that you don't want exposed at runtime. In addition, as is the case with many third-party APIs, you may have multiple API keys used for different purposes and they may be on different pricing plans. In such a scenario, you wouldn't want to accidentally use your production API key while testing, in case it costs money to make API calls. Let's take advantage of Slack CLI's environment variables to separate these two cases.

1Set up Slack CLI

Use the new Slack CLI to create and deploy Slack apps. With the Slack CLI, developers can create an app and generate some boilerplate code in seconds.

This section walks through setting up your environment for next gen platform development.

  • Install the Slack CLI

    We've built a command line interface to make the process of creating new apps, running them, and deploying them easier. Binaries are available for macOS and Windows.

    Deno is currently a pre-requisite for using the CLI — if you do not have Deno installed, please do so first.

    Additionally, the experience of writing an app will be greatly enhanced if your IDE includes support for Deno. Here's a plugin to add Deno capabilities to VS Code.

    To install the Slack CLI:

    1. Download the latest binary for your platform
    2. Decompress the downloaded file. On macOS, copy the slack binary to a destination in your path (we recommend /usr/local/bin). For Windows, copy the .exe file into any location accessible in your path.
    3. Test the app is properly installed by running slack version and verifying the version matches the one you downloaded.

    Now you can now use the Slack CLI to authenticate and create a new app.

  • Authenticate the Slack CLI

    Before you can create an app, you must authenticate.

    1. Run slack login — this will display some instruction text and a string to copy and paste in any channel in the test workspace.

          /hermesauthticket ABC123DEF...XYZ
      
    2. Copy the entire string, including the leading /, and paste it into any channel in your Slack workspace. (You are essentially calling a special slash command that will authenticate your app with Slack).

    3. Run slack auth info for details on your active workspace authorization.

    Now that you've authenticated, you can create a new app.

  • Authenticating Slack CLI again on another workspace

    Follow the steps above once again using another workspace that you want to deploy your app to.

    slack login
    
  • Create a new app

    Now you can create an app! cd to a directory where you have write access and want your app to live, most likely in your home. Then, run

    $ slack create [optional-project-name]
    

    This will create a new project called with a random name like priceless-lemur-123.

    If you want to name your project something specific, include an additional parameter

    $ slack create my-new-project
    

    Once the app has finished running, you'll have a new directory that contains a skeleton app.

    $ cd my-new-project
    

    The structure of these next-generation apps aims to favor convention over configuration. Directories are named logically and the files within those directories map to specific functionality with an app. For example, the functions directory contains a list of an app's functions, with a single file for each function an app defines.

2Setup a simple app that prints env variables to Slack

This section walks you through the structure of a simple app that uses a shortcut and prints the value of a environment variable in Slack. Since we want to focus on environment variables here, information on how Functions, Workflows and Triggers may be a bit brief. Links to more detailed information will be found within in each step.

  • Adding a new function to your app
    1. Create a env_getter.ts file under the functions/ directory of your project.
    2. Copy and paste the following code into it:
    import { DefineFunction, Schema } from "slack-cloud-sdk/mod.ts";
    
    export const EnvFunction = DefineFunction(
      "env-var-tester",
      {
        title: "Environment Variable Tester",
        description: "Prints out environment variables",
        input_parameters: {},
        output_parameters: {
          api_key: {
            type: Schema.types.string,
            description: "The value of API_KEY",
          },
        },
      },
      async ({ env }) => {
        // This is where you can use your environment variables.
        console.log(`API_KEY_FREE is ${env["API_KEY"]}`);
        return await {
          outputs: {
            api_key: `${env["API_KEY"]}`,
          },
        };
      },
    );
    

    This code defines a Function that will access your environment variable. You can access environment variables through the env object:

    ${env["FOO"]}
    

    For more information on how environment variables work with the Slack CLI, refer to the docs.

  • Adding a new workflow to your app

    Next we'll add a Workflow. A single step in a Workflow corresponds to a Function and a Workflow can have multiple steps.

    This Workflow is given the name of the environment variable and a channel where the value will be posted. The Function does the work and returns with the variable value and we send that value to Slack.

    1. Create a env_me.ts file under the workflows/ directory of your project.
    2. Copy and paste the following code into it:
    import { DefineWorkflow, Schema } from "slack-cloud-sdk/mod.ts";
    import { EnvFunction } from "../functions/env_getter.ts";
    
    export const EnvMeWorkflow = DefineWorkflow("env_me", {
      input_parameters: {
        channel: {
          type: Schema.slack.types.channel_id,
          description: "Channel where the shortcut is triggered.",
        },
      },
      title: "Env me!",
      description: "Finds out the API_KEY environment variable and prints it.",
    });
    
    const getEnvStep = EnvMeWorkflow.addStep(EnvFunction, {});
    
    EnvMeWorkflow.addStep(Schema.slack.functions.SendMessage, {
      channel_id: EnvMeWorkflow.inputs.channel,
      message:
        `The value of API_KEY is: *${getEnvStep.outputs.api_key}* on this workspace`,
    });
    
  • Adding a new trigger to your app

    Now that we have a Function that will do some logical work for us, we'll want to be able to trigger it. Here we'll use a Shortcut, but there are other methods to trigger a Workflow.

    1. Create a envme_shortcut.ts file under the triggers/ directory of your project.
    2. Copy and paste the following code into it:
    import { DefineTrigger, TriggerTypes } from "slack-cloud-sdk/mod.ts";
    import { EnvMeWorkflow } from "../workflows/env_me.ts";
    
    export const EnvMeShortcut = DefineTrigger("env_me", {
      type: TriggerTypes.Shortcut,
      name: "EnvMe",
      description:
        "Returns the value of the API_KEY environment variable",
    })
      .runs(EnvMeWorkflow)
      .withInputs((ctx) => ({
        channel: ctx.data.channel_id,
      }));
    
    

    More detailed information about Triggers can be found here.

  • Review the project.ts file

    Lastly you'll want to review your project.ts and make sure that it reads in the Function, Workflow and Trigger that you just wrote.

    import { Project } from "slack-cloud-sdk/mod.ts";
    import { EnvFunction } from "./functions/env_getter.ts";
    import { EnvMeWorkflow } from "./workflows/env_me.ts";
    import { EnvMeShortcut } from "./triggers/envme_shortcut.ts";
    
    Project({
      name: "dreamy-panther-555",
      description: "A very basic app that prints environment variables",
      icon: "assets/icon.png",
      runtime: "deno1.x",
      botScopes: ["commands", "chat:write", "chat:write.public"],
      functions: [EnvFunction],
      workflows: [EnvMeWorkflow],
      triggers: [EnvMeShortcut],
      outgoingDomains: [],
    });
    
    

    This concludes the setting up the app!

3Run your app locally and add environment variables

These commands illustrate how to add your own local environment variables.

  • Adding local environment variables

    When developing locally using the slack run command, environment variables found in the .env file at the root of your project will be read in and available at runtime. Make sure that the .env is not committed to version control in case you expose something secret that you shouldn't. You can define variables in the familiar UNIX environment variable format:

    KEY=VALUE
    
    1. Create an .env file in the root directory of your project.
    2. Add in the following variables:
    API_KEY=my-dev-key
    
  • Test using slack run locally

    Let's make sure that this all works before we deploy our app. Use the following command to create a secure connection (using Socket Mode) from your local machine to Slack, which you can use to test and develop:

    slack run
    

    For this particular step, you only need to choose one of your workspaces. Once this has been run, head to that workspace and click on the thunderbolt icon in the bottom left. Type "EnvMe" and click or hit Enter on your shortcut and you should get a message in Slack that says The value of API_KEY is: my-dev-key on this workspace. Perfect.

    You may have noticed that your app has (dev) appended to it, this is because this is a separate app that is created when you use slack run that is used for development purposes.

4Deploy your app and add environment variables using the Slack CLI

Once your app is deployed, these commands illustrate how to add your own environment variables to a particular workspace.

  • Deploying your app

    While you've created your app locally, you'll also need to deploy it. Use the following to deploy your app to both your staging and prod workspaces.

    slack deploy -w your_staging_workspace
    slack deploy -w your_prod_workspace
    
  • Example commands for adding env variables

    Next to add in environment variables, you'll use the following command:

    slack var add <key> <value> --workspace <workspace_name>
    

    Feel free to add as many variables as you like but for this particular track, we're going to do something like this:

    slack var add API_KEY 1234_my_staging_key --workspace your_staging_workspace
    
    slack var add API_KEY 1234_my_prod_key --workspace your_prod_workspace
    
  • Check the values of the added environment variables

    Within your staging workspace, check to see if the environment variable has been set by using the EnvMe Shortcut and do the same on your production workspace as well. Hopefully if everything is in order, you should see 1234_my_staging_key on your staging workspace and 1234_my_prod_key on your production workspace!

    If that's the case then some congratulations are in order 🎉! You are now a proud owner of two apps built from the same code base, on two different workspaces!

Was this page helpful?