如何在 GitHub Actions 中使用 env 文件?

Posted

技术标签:

【中文标题】如何在 GitHub Actions 中使用 env 文件?【英文标题】:How do I use an env file with GitHub Actions? 【发布时间】:2020-05-27 06:50:32 【问题描述】:

我有多个环境(dev、qa、prod)并且我正在使用 .env 文件来存储机密等...现在我正在切换到 GitHub Actions,我想使用我的 .env 文件并声明它们进入 github 操作 yml 的 env 部分。

但是从我目前看到的情况来看,我似乎无法设置文件路径,我必须手动重新声明所有变量。

我应该如何进行最佳实践?

【问题讨论】:

嗨,OP!这有什么好运气吗?我也面临着与 Github Actions 相同的问题——试图找出一种方法来以某种方式存储不同环境的秘密变量。 基本上,您必须手动将各个 .env 文件的内容(例如 .env.stage.env.production)复制到相应的 GitHub Actions 秘密变量(例如 WEBSITE_ENV_STAGEWEBSITE_ENV_PRODUCTION)中。然后在您的 GitHub Actions 工作流脚本中,从所需变量(如 echo "$ secrets.WEBSITE_ENV_STAGE " > .env)创建 .env 文件,并在工作流中使用它。 我还有 2 种方法可以让您在项目中使用 .env 文件。见my answer below。 【参考方案1】:

这里的一个快速解决方案可能是在您需要之前手动创建.env 文件。

- 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

【讨论】:

您的解决方案更简单。非常感谢 这是最简单也是最好的解决方案。 我们有相同的解决方案,但这很麻烦,我有 36 个环境变量要编辑。 必须删除多余的 > 才能正常工作 尝试使用此解决方案时,我不断收到以下错误:`line 3: unexpected EOF while looking for matching `'。我能够通过单独传递秘密来解决它。我在下面发布了代码。【参考方案2】:

执行此操作的最简单方法是将 .env 文件创建为 github 机密,然后在您的操作中创建 .env 文件。 因此,第 1 步是在 github 中将 .env 文件创建为秘密文件,作为 base64 编码字符串:openssl base64 -A -in qa.env -out qa.txtcat qa.env | base64 -w 0 > qa.txt 然后在你的行动中,你可以做类似的事情

- 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

有多种方法可以确定$YOUR_ENVIRONMENT,但通常可以从GITHUB_REF 对象中提取。您的应用程序应该能够根据需要从 .env 文件中读取数据。

【讨论】:

Github Secret 不是已经加密了吗?看起来您正在加密一个加密文件,而 Github 已经在进行解密以读取机密文件。 @Brettins 这里的.env 文件可能包含许多键。将它们编码为字符串的目的是,您无需在 github secrets 上逐一声明。 @brian ,这实际上似乎是我的情况的完美解决方案,但是我对 openssl 命令感到困惑,我们需要在哪里运行此命令? @uneebmeer 您可以在终端中运行它以生成 base64 版本字符串。【参考方案3】:

编辑: 您使用的是 Circleci 上下文,因此您拥有每个环境的一组秘密。我知道他们正在努力将秘密带到组织层面,也许是团队层面......没有信息他们是否会创建像我们在 CCI 中那样的上下文。

我考虑过使用 yml 上的 $env_GITHUB_KEY 将 env 添加为秘密名称的前缀,例如 STAGE_GITHUB_KEY 或 INTEGRATION_GITHUB_KEY 作为一种解决方法......你怎么看?

---原始答案: 如果我对您的理解很好,您已经将 dotenv 文件存储在某处,并且您希望将所有这些秘密注入步骤中,而无需手动将它们添加到 github 秘密并在您迁移的每个工作流程中进行映射......对吗?

有人执行了一项操作,该操作读取 dotenv 文件并将其值放入输出中,因此您可以在进一步的步骤中使用它们链接。这是链接:https://github.com/marketplace/actions/dotenv-action

.env 文件中存在的任何内容都将转换为输出变量。例如 .env 文件的内容:

VERSION=1.0
AUTHOR=Mickey Mouse

你这样做:

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

然后你可以像这样引用alpine版本 $ steps.dotenv.outputs.version

【讨论】:

那个 .env 文件在哪里?因为它没有保存在 repo 中 - 这就是拥有 .env 文件的意义 好吧,它看起来像一个常见的模式(有一个 CI 任务正在读取的 .env 文件——例如参见circleci.com/orbs/registry/orb/anilanar/dotenv)。如果您可以提供一个变量作为任务的path,这个答案看起来很适合您的问题。 @HRK44 “我想使用我的 .env 文件”我知道你已经有了它们,我想在 S3 或其他东西中。如果您拥有它们并且正在寻找安全存储,您可以存储在 S3 中并使用 aws secret+key 下载并添加到操作中。如果没有,您必须生成它们,将 github 机密打印到文件中,并使用 sed 替换占位符或对文件进行简单的回显,无论您喜欢什么。如果不是这种情况,请澄清您的情况。 nilleb 他正在从 Circleci 迁移到 Github,所以在这种情况下 orb 没有用 @Ayo 在 CircleCi 中很好,我们将环境存储在 CircleCi 中,我们有多个版本的环境(dev、qa、prod 等),但在 GitHub 操作中,我们只能存储一个版本的秘密。现在我们正在使用 Jenkins(其中存储了机密),并且根据构建类型,它将使用 dev/qa/prod 机密。我们如何使用 Github Actions 做到这一点? 好吧,我想我明白了。您使用的是 Circleci 上下文,因此您拥有每个环境的一组秘密。我知道他们正在努力将秘密带到组织级别,也许还有团队级别……没有信息他们是否会创建像我们在 CCI 中那样的上下文。我考虑过在 yml 上使用 $env_GITHUB_KEY 将 env 添加为秘密名称的前缀,例如 STAGE_GITHUB_KEY 或 INTEGRATION_GITHUB_KEY 作为一种解决方法......你怎么看?【参考方案4】:

我看到 3 种非常简单的方法可以让您的 .env 文件变量参与 GitHub 操作工作流程。它们的不同取决于您是将文件存储在存储库中(最差的做法)还是将其保留在存储库中(最佳做法)。

    您将文件保存在存储库中:

    有一些ready-made actions 允许读取.env 变量(例如Dotenv Action、Simple Dotenv)。

    简单,手动,更新时烦人.env 变量)您将文件保留在存储库之外:

    您手动将各个.env 文件(例如.env.stage.env.production)的内容复制到各个GitHub Actions secret variables(例如WEBSITE_ENV_STAGEWEBSITE_ENV_PRODUCTION)中。

    然后在您的 GitHub Actions 工作流脚本中,从所需的变量(如 echo "$secrets.WEBSITE_ENV_STAGE " > .env)创建 .env 文件,并在工作流中使用它。

    虽然准备一次,但涉及更多,然后在本地计算机上更改您的 .env 变量,然后在 GitHub 上一键同步这些变量)如上面的第 2 项,文件是离开存储库。

    现在您使用 GitHub Actions API 到 create or update the secrets。在dev 环境中的本地计算机上,您编写调用API 端点的NodeJS 脚本,并将.env 文件写入所需的GitHub Actions 秘密变量(如上至WEBSITE_ENV_STAGE 或同时写入阶段和生产变量一次);

这是在工作流中使用.env 文件变量的多种方式选择。使用任何符合您的偏好和情况。

【讨论】:

为什么这个投票被否决了?我觉得这是一个很好的答案。 这是最好的答案【参考方案5】:

另一种选择是使用来自 github 的 Environments 功能。尽管免费计划中的私人回购不提供此功能。 您可以在存储库、配置文件/组织级别和环境中设置范围变量。靠近存储库的配置变量优先于其他变量。

【讨论】:

【参考方案6】:

您还可以使用来自 github-marketplace 的专用 github action 创建 .env 文件。

示例用法:

name: Create envfile

on: [push]

jobs:

  create-envfile:
 
    runs-on: ubuntu-18.04
 
    steps:
    - name: Make envfile
      uses: SpicyPizza/create-envfile@v1
      with:
        envkey_DEBUG: false
        envkey_SOME_API_KEY: "123456abcdef"
        envkey_SECRET_KEY: $ secrets.SECRET_KEY 
        file_name: .env

根据您在 github 存储库中为机密定义的值,这将创建一个 .env 文件,如下所示:

DEBUG: false
SOME_API_KEY: "123456abcdef"
SECRET_KEY: password123

更多信息:https://github.com/marketplace/actions/create-env-file

【讨论】:

【参考方案7】:

我遇到了同样的问题。我想要的是将 .env 文件上传到我的服务器,而不是在我的 Github 存储库中定义 env 变量。由于我没有跟踪我的 .env 文件,所以每次我的工作流程运行时 .env 文件都会被删除。所以我所做的是:

    在我的服务器项目根目录中添加了.env文件。 在我的工作流程中的actions/checkout@v2 中的with 键下添加了clean: false

例如:

jobs:
  build:

    runs-on: self-hosted

    strategy:
      matrix:
        node-version: [14.x]
       
    - uses: actions/checkout@v2
      with: 
        clean: 'false'

这可以防止 git 删除未跟踪的文件,例如 .env。欲了解更多信息,请参阅:actions/checkout

【讨论】:

【参考方案8】:

我尝试使用公认的解决方案,但 GitHub 操作抱怨 shell 命令。我不断收到此错误:line 3: unexpected EOF while looking for matching ``'

我没有直接在 shell 脚本中引用秘密,而是将它们单独传递。

  - name: Create env file
    run: |
      touch .env
      echo POSTGRES_USER=$POSTGRES_USER > .env
      echo POSTGRES_PASSWORD=$POSTGRES_PASSWORD > .env
      cat .env
    env: 
      POSTGRES_USER: $ secrets.POSTGRES_USER  
      POSTGRES_PASSWORD: $ secrets.POSTGRES_PASSWORD  

【讨论】:

【参考方案9】:

另一种方法是按照https://docs.github.com/en/actions/security-guides/encrypted-secrets#limits-for-secrets 中的描述进行操作

所以基本上将您的.env 文件视为“大秘密”。在这种情况下,加密的.env 文件会保留在您的存储库中,这应该没问题。然后在您的操作中有一个步骤来解密.env 文件。

这消除了必须在 .env 中创建每个单独的秘密作为 Github 秘密的开销。在这种情况下,唯一需要维护的 Github 密码是加密密码。如果您有多个.env 文件,例如qa.envprod.env 等...我强烈建议为每个文件使用不同的加密密码,然后将每个加密密码作为“环境机密”存储在 Github 中,而不是“repo secret”(如果您喜欢使用 Github 环境。请参阅https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment)。

如果您不想在您的存储库中提交(加密的).env 文件,那么我将使用https://***.com/a/64452700/1806782 中描述的 base64 方法(类似于https://docs.github.com/en/actions/security-guides/encrypted-secrets#storing-base64-binary-blobs-as-secrets 中的内容),然后创建用于托管编码内容的新 Github 密码。

对于像我这样讨厌手动重复性任务的人来说,如今可以使用 Github CLI 工具轻松编写 Github 秘密创建脚本。看 https://cli.github.com/manual/gh_secret_set 。它还支持从 env 文件“批量”创建秘密(参见 -f--env-file 标志)

【讨论】:

【参考方案10】:

您需要在存储库的“秘密”部分定义环境变量。然后,您可以在工作流程中简单地使用您的秘密。

示例用法:

- uses: some-action@v1
  env:
    API_KEY: $ secrets.API_KEY 
    SECRET_ID: $ secrets.SECRET_ID 
  with:
    password: $ secrets.MY_PASSWORD 

这是文档:

https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets

【讨论】:

这没有回答我的问题,我说的是如何用这个系统以最好的方式处理多个环境(dev、qa、stage、prod 等)?跨度>

以上是关于如何在 GitHub Actions 中使用 env 文件?的主要内容,如果未能解决你的问题,请参考以下文章