I’m trying to write an integration test which for now simply launches a Node server, then queries it to check if it’s running properly. The test works locally, and on CircleCI I was also apparently able to launch the Node server on port 9000. However, my tests fail with net::ERR_CONNECTION_REFUSED. Would you have any idea?
I’m guessing that your tests are starting too quickly, before your HTTP server has started up. The solution may be as simple as sleep 5 && yarn test, or you can do something a bit fancier that checks if the socket has started up.
To start with, you could just let the build fail with the SSH option, then get a remote console and run the tests (I guess cd ~/repo && yarn test?). By the time you get a connection, your HTTP server should definitely be started.
@halfer there is already a sleep of 30 seconds (see config and screenshot above). When following the build through the CircleCI console I see that the HTTP server is fully started after less than one second, then it idly waits for 30 seconds. But then when yarn test kicks in, it fails nevertheless. It also fails if I replace yarn test with curl http://localhost:9000.
However, yarn test and curl both work fine when I SSH into the machine then run manually.
So it’s just when CircleCI itself is running the tests, it can’t resolve localhost for some reason. Is it somehow related to docker (which I know nothing about)?
Hmm, OK. I am not familiar with Yarn, but it looks to me that your server is called Gatsby, and that seems to be starting up after the sleep, thus defeating its purpose. Moreover, I cannot see where gatsby is started up in your config.
I don’t think so. The run line is run inside your container, and if you can run the tests in a subsequent SSH session, then you’ve not changed anything.
I wonder, try using 127.0.0.1 instead of localhost? I have seen some rare envs where the name was not defined.
So first the build is run, which produces static HTML/CSS/JS, then gatsby serve just spins an HTTP server serving those assets from localhost:9000. As the screenshot above shows, that command starts fine: “Running on port 9000”.
OK, 127.0.0.1 didn’t seem to work either, but I could detect the IP with node -p "require('ip').address()". So problem is fixed with the config below. It’s still really puzzling that localhost doesn’t work, that looks like a big limitation.
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:9.5-browsers
# Specify other service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
working_directory: ~/repo
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: yarn install
# workaround for failing node-gyp build of native dep gatsby>sharp>libvips.
# Remove when https://github.com/yarnpkg/yarn/issues/5152 is fixed.
- run:
name: Rebuild native dependencies
command: npm rebuild
when: on_fail
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run: yarn build
- run:
name: starting node server
command: mkdir logs && yarn start 2>&1 | tee logs/node_server.log
background: true
- run:
name: storing local IP address
command: node -p "require('ip').address()" > logs/ip.log
- run:
name: waiting for node server to start
command: wget --retry-connrefused --waitretry=2 -t 5 "http://$(cat logs/ip.log):9000" > /dev/null
- run:
name: running tests
command: yarn test
- store_artifacts:
path: logs
And changed the test with const siteUrl =http://${require(‘ip’).address()}:9000``.
(NB: the documentation mentions a config run: echo 127.0.0.1 devhost | sudo tee -a /etc/hosts, but with no explanation on what that would be for (and I didn’t try adding that).)
How big is the limitation if you solved the problem?
I’m not sure what issue you’re running into here, but hey, it’s fixed now. For anything requiring more than a single repo, I tend to install Docker Compose, and so my HTTP/WS operations are local names on a private Docker LAN anyway. If you ever get stuck again, it may be worth a go, since DC can be run/debugged locally too.
I just mean that localhost is a standard Unix feature, it should « just work » for any newcomer figuring out their first circleCI setup. If not, it should be documented properly. But anyway, thanks a lot for your help.
Thinking about this, I wonder if there is a way to tell Node what address to start the server on? I wonder if it does the equivalent of ifconfig and binds to the first one it finds, and if so, if the LAN IP is first in the list, it binds to that rather than localhost?
Gatsby relies on the serve NPM package which has no such argument. But anyway, I am able to run gatsby serve locally and access the server at http://localhost:9000, so it should also work on CircleCI.
Maybe, but I am not convinced this is necessarily a CircleCI issue, for the reasons I stated earlier. No matter though, it’s fixed! I thought I would just kick around some ideas to see if it can be made to attach to localhost.
Indeed, perhaps it’s a bug in npm serve - it would be interesting to see some internal logic to see why it binds to the address it does.
After glancing into the zeit/serve code, I honestly don’t know. After the server has started, it just displays that it’s listening on require('ip').address(), but don’t see where the server is configured.