node.jstypescriptgithub-actionsmocha.jsvite

MongoDB URI Undefined in GitHub Actions CI/CD Pipeline Despite Working Locally


I’m having trouble with my GitHub Actions CI/CD pipeline when it comes to connecting to MongoDB. The connection works perfectly in my local environment, but when I run the tests in GitHub Actions, I encounter the following error:

Error connecting to MongoDB: MongooseError: The `uri` parameter to `openUri()` must be a string, got "undefined".

Here are the steps I’ve taken to debug the issue:

  1. Environment Variables: • I’ve ensured that the environment variables are correctly set up in the GitHub Secrets. Locally, I use a .env file with dotenv-flow to load the variables, and everything works as expected. 2. Hardcoding the URI: • I tried hardcoding the MongoDB URI directly in the code, bypassing the environment variable, but the error persists. This suggests that the issue might not be related to how the environment variables are passed. 3. GitHub Actions Workflow: • I’ve added steps in my GitHub Actions workflow to log the MongoDB URI before attempting the connection, but it still appears as undefined.

Here’s a snippet of my server.ts where the MongoDB connection is handled:

import mongoose from 'mongoose';

// Log the MongoDB URI to check if it is being set correctly
console.log("MongoDB Connection String (from env):", process.env.DBHOST);

// Temporary hardcoded URI for debugging purposes
const hardcodedUri = "your-hardcoded-mongodb-uri";
console.log("Using hardcoded MongoDB URI:", hardcodedUri);

// Use the hardcoded URI for debugging, replace `process.env.DBHOST` with `hardcodedUri` if needed
mongoose.connect(hardcodedUri, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log("Connected to MongoDB successfully"))
  .catch((error) => console.error("Error connecting to MongoDB:", error));

And here’s the relevant part of my GitHub Actions main.yml:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Use Node.JS ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      - name: Install dependencies
        run: |
          cd backend
          npm install
        env:
          DBHOST: ${{ secrets.DBHOST }}
      - name: Log MongoDB URI
        run: |
          echo "MongoDB URI: $DBHOST" # Log the MongoDB URI to ensure it is set
      - name: Run tests
        run: |
          cd backend
          npx mocha --config .mocharc.json

server.ts:

// Connect to MongoDB using Mongoose
mongoose.set("strictQuery", false);
mongoose
  .connect(process.env.DBHOST as string)
  .catch((error) => console.log("Error connecting to MongoDB:" + error));

.mocharc.json:

{
  "diff": true,
  "extension": ["ts"],
  "ignore": ["test/ignore/**"],
  "package": "./package.json",
  "reporter": "spec",
  "slow": 75,
  "timeout": 5000,
  "ui": "bdd",
  "spec": "src/test/**/*.test.ts",
  "require": "ts-node/register",
  "watch-files": ["src/lib/**/*.ts", "src/test/**/*.ts"],
  "watch-ignore": ["lib/vendor"]
}

My Setup:

•   Node.js: v20.x
•   Mongoose: ^6.1.7
•   dotenv-flow: ^4.1.0
•   GitHub Actions: Runner on ubuntu-latest

What I’ve Tried:

•   Verifying that the environment variables match between local and GitHub Secrets.
•   Hardcoding the MongoDB URI for testing.
•   Logging the URI in the CI pipeline to ensure it’s being set.

Any help or suggestions would be greatly appreciated!

NOTE: Just recently I started using a TypeScript and before with JavaScript I never encountered similar issue.

UPDATE: Incorporating .env VARs only in run tests as suggested bellow indeed helped overvcome the originall issue. However it gets stuck on performing the tests and two of them are apparentnly failling despite that locally everythings passes...

Actions log:

> cross-env NODE_ENV=test mocha --require ts-node/register
[dotenv-flow@4.1.0]: ".env*" files loading failed: no ".env*" files matching pattern ".env[.test][.local]" in "/home/runner/work/slavic.media-2.0/slavic.media-2.0/backend" dir undefined
[dotenv-flow@4.1.0]: ".env*" files loading failed: no ".env*" files matching pattern ".env[.test][.local]" in "/home/runner/work/slavic.media-2.0/slavic.media-2.0/backend" dir undefined
Server is running on port: 4000
  Document workflow tests
Connected successfully to MongoDB
    1) should register + login a user, create document and verify 1 in DB
    2) should register + login a user, create document and delete it from DB
    ✔ Invalid user input test
  1 passing (2s)
  2 failing
  1) Document workflow tests
       should register + login a user, create document and verify 1 in DB:
      Uncaught AssertionError: expected 400 to equal 201
      + expected - actual
      -400
      +201
      
      at fn (src/test/workflow.test.ts:64:42)
      at Test.callback (node_modules/superagent/src/node/index.js:913:12)
      at fn (node_modules/superagent/src/node/index.js:1166:18)
      at IncomingMessage.<anonymous> (node_modules/superagent/src/node/parsers/json.js:19:7)
      at IncomingMessage.emit (node:events:531:35)
      at IncomingMessage.emit (node:domain:488:12)
      at endReadableNT (node:internal/streams/readable:1696:12)
      at processTicksAndRejections (node:internal/process/task_queues:82:21)
  2) Document workflow tests
       should register + login a user, create document and delete it from DB:
      Uncaught AssertionError: expected 400 to equal 201
      + expected - actual
      -400
      +201
      
      at fn (src/test/workflow.test.ts:145:42)
      at Test.callback (node_modules/superagent/src/node/index.js:913:12)
      at fn (node_modules/superagent/src/node/index.js:1166:18)
      at IncomingMessage.<anonymous> (node_modules/superagent/src/node/parsers/json.js:19:7)
      at IncomingMessage.emit (node:events:531:35)
      at IncomingMessage.emit (node:domain:488:12)
      at endReadableNT (node:internal/streams/readable:1696:12)
      at processTicksAndRejections (node:internal/process/task_queues:82:21)

Solution

  • You don't need env for dependencies installation

    - name: Install dependencies
            run: |
              cd backend
              npm install
            env:
              DBHOST: ${{ secrets.DBHOST }} ❌
    

    You have to configure it in run tests step

    - name: Run tests
            run: |
              cd backend
              npx mocha --config .mocharc.json
            env:
              DBHOST: ${{ secrets.DBHOST }} ✅
    

    Each step are isolated process, so they don't share env across them

    If you want to use one env variable for all steps, check out this github-action env