Search code examples
yamlgithub-actionsfirebase-tools

Run firebase emulators + vitest at once


I'm trying to run two jobs at the same time. First I need to run firebase emulators and when the ports are open, I need to run vitest.

This is what I'm doing at the moment:

name: Run Tests

on:
  pull_request:
    branches: [develop]
  workflow_dispatch:

jobs:
  job1:
    name: Run Emulator
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js 18.14.0
        uses: actions/setup-node@v3
        with:
          node-version: 18.14.0
          cache: 'npm'
      - name: Execute Emulator
        env:
          VITE_RELEASE_STAGE: testing
        run: |
          npm ci
          npm install --save firebase-tools
          npm run emulators
  job2:
    name: Run Unit Tests
    needs: job1
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js 18.14.0
        uses: actions/setup-node@v3
        with:
          node-version: 18.14.0
          cache: 'npm'
      - name: Execute Unit Tests
        env:
          VITE_RELEASE_STAGE: testing
        run: |
          npm ci
          npm run test

The doors open perfectly, but the second job never runs.

Here lies my doubt. Because if I don't use needs the two will run at the same time and I will get an error in job2 because the ports will not be open in job 1.

Running emulators

I would like to run job 2 as soon as the emulator ports are open and finish job 1 only after job 2 finishes.

Does anyone know how I can resolve this?

Running jobs


EDIT

These are the two executed scripts that are in my package.json:

"test": "vitest",
"emulators": "firebase emulators:start --project celebrityfanalizer --import emulatorData"

Solution

  • In your workflow, the job1 never finishes because the emulators are running in it and that's why the job2 never runs when you add its dependency on job1 i.e. needs: job1.

    You need to combine both jobs in one:

    1. set up the environment
    2. start the emulators in the background
    3. wait for the emulators to start
      • add some delay (along with a dump of its STDOUT/STDERR to a file and keep checking its contents for success logs e.g. "Emulator hub running")
    4. and, finally, run tests

    Here's an example with a delay of 1 minute after starting the emulators in the background:

    name: Run Tests in the Emulators
    
    on:
      pull_request:
        branches: [develop]
      workflow_dispatch:
    
    jobs:
      ci:
        runs-on: ubuntu-latest
    
        steps:
        - name: Checkout
          uses: actions/checkout@v3
    
        - name: Set up NodeJS 18.14.0
          uses: actions/setup-node@v3
          with:
            node-version: 18.14.0
            cache: 'npm'
    
        - name: Start the emulators and run tests
          env:
            VITE_RELEASE_STAGE: testing
          run: |
            npm ci
            npm install --save firebase-tools
            nohup npm run emulators &> emulators.log &
            sleep 1m
            npm run test
    

    Relevant:


    Apart from that, you can use jobs.<job_id>.services and run the emulators in a container if it's available.


    UPDATE

    As pointed out by sceee in the comments below, alternatively you may use firebase emulators:exec by configuring it under scripts in your package.json:

    {
      "scripts": {
        "test:emulators": "firebase emulators:exec \"npm test\""
      }
    }
    

    and then invoke it as needed:

    npm run test:emulators
    

    This will automate the process of starting the emulators, running tests, and then stopping the emulators after the tests are complete.