How do I use an env file with GitHub Actions?

The easiest way to do this is to create the .env file as a github secret and then create the .env file in your action.
So step 1 is to create the .env files as a secret in github as a base64 encoded string:
openssl base64 -A -in qa.env -out qa.txt
or
cat qa.env | base64 -w 0 > qa.txt
Then in you action, you can do something like

- name: Do Something with env files
  env:
    QA_ENV_FILE: ${{ secrets.QA_ENV_FILE }}
    PROD_ENV_FILE: ${{ secrets.PROD_ENV_FILE }}
  run: |
    [ "$YOUR_ENVIRONMENT" = qa ] && echo $QA_ENV_FILE | base64 --decode > .env
    [ "$YOUR_ENVIRONMENT" = prod ] && echo $PROD_ENV_FILE | base64 --decode > .env

There are a number of ways for determining $YOUR_ENVIRONMENT but usually this can be extracted from the GITHUB_REF object. You applications should be able to read from the .env files as needed.


a quick solution here could be having a step to manually create the .env file before you need it.

      - name: 'Create env file'
        run: |
          touch .env
          echo API_ENDPOINT="https://xxx.execute-api.us-west-2.amazonaws.com" >> .env
          echo API_KEY=${{ secrets.API_KEY }} >> .env
          cat .env

I would suggest 3 pretty simple ways to engage your .env file variables in the GitHub Actions workflow. They differ based on whether you store the file in your repository (the worst practice) or keep it out of it (the best practice).

  1. You keep your .env file in the repository:

    • There are some ready-made actions that allow to read the .env variables (e.g. Dotenv Action,Simple Dotenv).
  2. (simple, manual, annoying when update .env variables) You keep your file out of your repository:

    • You manually copy the content of the respective .env files (say .env.stage, .env.production) into the respective GitHub Actions secret variables (say WEBSITE_ENV_STAGE, WEBSITE_ENV_PRODUCTION).

    • Then at your GitHub Actions workflow script create the .env file from the desired variable like this echo "${{secrets.WEBSITE_ENV_STAGE }}" > .env and use it in the workflow.

  3. (a bit more involved though prepare it once, then change your .env variables at the local machine, then sync these at GitHub with one click) As in item 2 above, the file is out of the repository.

    • Now you use the GitHub Actions API to create or update the secrets. On your local machine in the dev environment you write the NodeJS script that calls the API endpoint and write the .env files to the desired GitHub Actions secret variable (say as above into WEBSITE_ENV_STAGE or to both stage and production variables at once);

This is pretty wide choice of ways to engage the .env files's variables in the workflow. Use any matching your preference and circumstances.

Just for information, there is the 4th way which engages some 3rd party services like Dotenv Vault or HasiCorp Vault (there are more of the kind) where you keep you secret variables to read these to create .env file at build time with your CI/CD pipeline. Read there for details.


Edit: You were using Circleci Contexts, so with that you had a set of secrets of each env. I know they are working to bring secrets to org level, and maybe team level... there is no info if they will create sort of contexts like we have in CCI.

I have thought on adding the env as prefix of the secret name like STAGE_GITHUB_KEY or INTEGRATION_GITHUB_KEY using ${env}_GITHUB_KEY on the yml as a workaround for now... What do you think?

--- Original answer: If I understand you well, you already have the dotenv files stored somewhere and you want to inject all those secrets into the steps, without having to manually add them to github secrets and do the mapping in each workflow you migrate... right?

There is an action made by someone that reads a dotenv file and put its values into ouputs, so you can use them linked in further steps. Here is the link: https://github.com/marketplace/actions/dotenv-action

Whatever is present in the .env file will be converted into an output variable. For example .env file with content:

VERSION=1.0
AUTHOR=Mickey Mouse

You do:

id: dotenv
uses: ./.github/actions/dotenv-action

Then later you can refer to the alpine version like this ${{ steps.dotenv.outputs.version }}