如何在 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 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 GitHub Actions 中使用最新发布标签?

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

如何在 GitHub Actions 中构建的 Dockerfile 中使用 github 令牌并尝试克隆私有存储库?

如何在 GitHub Actions 中使用 bash 表达式设置 env var?

如何在 GitHub Actions 中缓存纱线包

如何在推送事件中跳过 GitHub Actions 作业?