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:
- Check out the code from the head of the PR branch from repo A.
- Install all the dependencies of repo A.
- Build the app and start the app.
- Check out the testing suite code from repo B.
- Install all the dependencies.
- 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
First of all, I think starting the application in this way in Github action using
&
could not be able to keep it runningSo for tracing this workflow and validating that point, I can suggest some edits:
curl -i localhost:3000
so you can make sure it’s still runningbash
step to do the same to make sure app is not exitedThis 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 commandnpm run start &
Mainly these edits are for the first workflow
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:
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
To achieve the same result, but I’m not sure.