dotenv-gcloud-secrets-resolver
v0.1.0
Published
Resolve .env files whose values are literals or ${secret:NAME} references to Google Cloud Secret Manager. Two modes: resolve (local) and translate (CI).
Maintainers
Readme
dotenv-gcloud-secrets-resolver
One parser for .env files whose values are either literals or
${secret:NAME} references to Google Cloud Secret Manager — two modes.
Declare each environment variable once, in a committed file, and consume
it identically for a local run and a Cloud Run deploy.
- resolve — for local use. Literals pass through; every
${secret:NAME}is fetched from gcloud Secret Manager. Output: a flat env object for the process. - translate — for CI, via the bundled GitHub Action. Literals become
gcloud run deploy --set-env-varsentries;${secret:NAME}references become--set-secretsentries. The secret value is never fetched or inlined — the reference becomes Cloud Run's native Secret Manager mount.
The gcloud project and the secret names are inputs, never baked in — the package is parsing logic only.
The .env file format
# literals — committed in clear, non-sensitive config only
SERVER_PORT=8080
LOG_LEVEL=info
CORS_ALLOWED_ORIGINS=https://app.example.com,https://example.com
# secret references — resolved from gcloud Secret Manager
DB_PASSWORD=${secret:DATABASE_PASSWORD}
JWT_SECRET_KEY=${secret:JWT_SIGNING_KEY:7} # pinned to version 7- A value is a literal or a single secret reference. A value that
mixes literal text with
${secret:…}is rejected — a secret must map cleanly onto one--set-secretsentry. ${secret:NAME}uses versionlatest;${secret:NAME:VERSION}pins it.#lines are comments; an optionalexportprefix is tolerated; surrounding quotes are stripped.
See examples/service.env.example.
Library API
const { resolve, translate, toGcloudFlags } = require('dotenv-gcloud-secrets-resolver');
// resolve mode — secrets fetched from gcloud
const env = resolve('envs/local.env', { project: 'my-gcp-project' });
// translate mode — no secret value ever touched
const flags = toGcloudFlags(translate('envs/staging.env'));
// → ['--set-env-vars=^@^SERVER_PORT=8080@…', '--set-secrets=DB_PASSWORD=…:latest']resolve(file, opts) accepts opts.fetchSecret(secret, version, project)
for testing without gcloud.
Secret bytes are used verbatim.
resolvereturns exactly what gcloud returns, with no trimming — the same bytes Cloud Run mounts via--set-secrets. Never store a secret value with a stray trailing newline; it would break a local run and a deploy identically.
CLI
env-resolver resolve envs/local.env --project my-gcp-project
env-resolver translate envs/staging.env
env-resolver translate envs/staging.env --jsonGitHub Action
- id: env
uses: super-cache-money/dotenv-gcloud-secrets-resolver@v1
with:
file: envs/staging.env
- run: |
gcloud run deploy my-service \
--set-env-vars='${{ steps.env.outputs.set-env-vars }}' \
--set-secrets='${{ steps.env.outputs.set-secrets }}'Tests
npm test # node --testLicense
MIT
