skip to Main Content

I have 2 repo, one is for my NextJS app let’s call it repo A. Another one for my testing suite that uses cucumber and playwright, let’s call it repo B.

I want to run a Github Actions workflow, whenever there is a pull request to the Main branch of the repo A. In the workflow, the following should happen:

  1. Check out the code from the head of the PR branch from repo A.
  2. Install all the dependencies of repo A.
  3. Build the app and start the app.
  4. Check out the testing suite code from repo B.
  5. Install all the dependencies.
  6. Run the test against the app running from step 3)

So far, I have tried a bunch of different approaches to achieve the expected behavior. The following is my current YAML file for the workflow.

name: Automated Testing workflow
on:
  pull_request: 
    types: 
      - opened
    branches: 
      - 'github-actions/Test'
  workflow_dispatch:
  
jobs:
  build-and-test:
    name: Build and test app
    runs-on: ubuntu-latest
    env:
      APP_URL: ${{ secrets.APP_URL }}
      USERNAME: ${{ secrets.USERNAME }}
      PASSWORD: ${{ secrets.PASSWORD }}
      ORGANISATION_NAME: ${{ secrets.ORGANISATION_NAME }}
    steps:
      - name: Checkout Git repository A
        uses: actions/checkout@v4
        with:
          path: 'app'

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
        
      - name: Install Node.js dependencies
        working-directory: ${{ github.workspace }}/app
        run: npm ci

      - name: Run application
        working-directory: ${{ github.workspace }}/app
        run: npm run start &

      - name: Checkout Automated Testing suite repo
        uses: actions/checkout@v4
        with:
          repository: orgname/testing-repo-B
          token: ${{ secrets.TOKEN }}
          path: 'tests'
      
      - name: Install dependencies
        working-directory: ${{ github.workspace }}/tests
        run: npm ci

      - name: Install playwright browsers
        working-directory: ${{ github.workspace }}/tests
        run: npx playwright install --with-deps

      - name: Run Testing Suite
        run: export APP_URL=$APP_URL &&
          export USERNAME=$USERNAME &&
          export PASSWORD=$PASSWORD &&
          export ORGANISATION_NAME=$ORGANISATION_NAME &&
          npm test
        working-directory: ${{ github.workspace }}/tests

I can see the app from repo A getting build and running as expected. In the logs it does say that the application is running on http://localhost:3000.
However, in the step where I’m running the test, I’m getting the following error:

Error: a BeforeAll hook errored, process exiting: file:/home/runner/work/******/******/tests/hooks/hooks.js:36
    at Runtime.runTestRunHooks (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/run_test_run_hooks.js:22:23)
    at async Runtime.start (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/index.js:62:9)
    at async runCucumber (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/api/run_cucumber.js:110:21)
    at async Cli.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/index.js:56:29)
    at async Object.run [as default] (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/run.js:29:18) {
  [cause]: page.goto: net::ERR_CONNECTION_REFUSED at http://***
  Call log:
    - navigating to "***", waiting until "load"
  
      at Object.<anonymous> (/home/runner/work/******/******/tests/hooks/hooks.js:54:16)
      at async wrapPromiseWithTimeout (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/time.js:57:12)
      at async Object.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/user_code_runner.js:64:22)
      at async Runtime.runTestRunHooks (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/run_test_run_hooks.js:14:31)
      at async Runtime.start (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/index.js:62:9)
      at async runCucumber (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/api/run_cucumber.js:110:21)
      at async Cli.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/index.js:56:29)
      at async Object.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/run.js:29:18) {
    name: 'Error'
  }
}

If we take a look at the error message page.goto: net::ERR_CONNECTION_REFUSED at http://*** , to me it seems like there is some networking issue. I can see the app running in the GH UI and in the logs I can also see the URL of the app as stated earlier. But somehow in the last step, when trying to run the test and when the automated test tries to go to localhost, I’m getting the ERR_CONNECTION_REFUSED error. And since it’s printing the URL as at http://*** I’m assuming that the environment variables have been set correctly from the github secrets.

Can someone please help me fix this issue?

TLDR; can’t access the app running on localhost for testing in the Github actions.

I have tried running the app locally and running the test suite against it. The tests run smoothly in the local environment.

I have tried changing the APP_URL from http://localhost:3000 to 127.0.0.1 but no luck.

I have tried a bunch of different configurations of the workflow. I have also tried running the app in a service. The following is a different YAML file of the workflow that I’ve tried.

name: Automated Testing workflow
on:
  pull_request: 
    types: 
      - opened
    branches: 
      - 'github-actions/Test'
  workflow_dispatch:
  
jobs:
  build-and-test:
    name: Build and test app
    runs-on: ubuntu-latest
    env:
      APP_URL: ${{ secrets.APP_URL}}
      USERNAME: ${{ secrets.USERNAME}}
      PASSWORD: ${{ secrets.PASSWORD}}
      ORGANISATION_NAME: ${{ secrets.ORGANISATION_NAME}}
    container: ubuntu
    services:
      appA:
        image: node:20-alpine
        ports: 
          - 3000:3000
    steps:
      - name: Checkout Git repository
        uses: actions/checkout@v4
        with:
          path: 'app'

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
        
      - name: Install Node.js dependencies
        working-directory: ${{ github.workspace }}/app
        run: npm ci

      - name: Run application
        working-directory: ${{ github.workspace }}/app
        run: npm run start:prod &

      - name: Checkout Automated Testing suite repo
        uses: actions/checkout@v4
        with:
          repository: orgname/testing-repo-B
          token: ${{ secrets.TOKEN }}
          path: 'tests'
      
      - name: Install dependencies
        working-directory: ${{ github.workspace }}/tests
        run: npm ci

      - name: Install playwright browsers
        working-directory: ${{ github.workspace }}/tests
        run: export APP_URL=$APP_URL &&
          export USERNAME=$USERNAME &&
          export PASSWORD=$PASSWORD &&
          export ORGANISATION_NAME=$ORGANISATION_NAME &&
          npm test && npm test
        working-directory: ${{ github.workspace }}/tests

2

Answers


  1. First of all, I think starting the application in this way in Github action using & could not be able to keep it running

    So for tracing this workflow and validating that point, I can suggest some edits:

    1. Right after starting the application, you can run a command like curl -i localhost:3000 so you can make sure it’s still running
    - name: Run application
            working-directory: ${{ github.workspace }}/app
            run: |
              npm run start &
              curl -i localhost:3000
    
    1. Add another step which is just another bash step to do the same to make sure app is not exited
    - name: test app is still running
      run: curl -i localhost:3000
    

    This should help with tracing if application is getting exited for following steps or not


    Aside from that, I think it could be better to use other ways for starting the application like pm2 which I think is already included in the above workflow, otherwise, you can add a step to install it, but you can test first if it’s there.

    And usage of it shall be like pm2 start npm -- start which shall replace the command npm run start &

    - name: Run application
            working-directory: ${{ github.workspace }}/app
            run: |
              pm2 start npm -- start
              curl -i localhost:3000
    

    Mainly these edits are for the first workflow

    Login or Signup to reply.
  2. GitHub actions does process tracking and will automatically kill any executable that was spawned by a step when the step ends.

    There is a way to trick the runner to not kill the process, you need to add some "magic fairy dust" to the step that starts the process:

    RUNNER_TRACKING_ID="" && npm run start:prod &
    

    By clearing the RUNNER_TRACKING_ID temporarily, the runner won’t know this process is owned by the workflow.

    Be sure to add a cleanup step with if: always() to kill the process when the job finishes or is cancelled.

    I think you may also be able to set an environment variable

    env: 
      PROCESS_CLEAN: false
    

    To achieve the same result, but I’m not sure.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search