Conversation
|
@Kononnable @pleerock @vlapo I couldn't get Travis to really work the way I wanted it. The main issue is an inability to share cache between the build stages. If I had access to a Docker registry, I'd build an image which would then cache the install, lint and build stages so we could basically focus on spending all our time in tests. As things are, the overhead of running those processes over and over kills any advantage we get from running everything in parallel. And Travis does not provide any sort of Docker cache so you have to pull each image on each run. We could spin our own and store everything in an S3 bucket, but that seems like too much of a hack. That's not to say we can't run things in parallel. If we don't care so much about build times, we can do this quite easily: Running like that builds take around 16-17 minutes (and can take more if there's a wait for jobs to start or especially if there are several commits at once). I also cleaned up some of the tests and externalized config so you can set I know I started out talking about jest, but I wanted to first see how things run in CI. To take full advantage of jest, I think we'd need to introduce some magic layer where each test creates and runs in its own db or schema. I also removed As I see it, the options at this point are:
|
It would be a problem on non-collaborator builds(majority of PRs) - Travis doesn't allow to use secrets in such builds(because someone might steal them). We might get it a little bit faster by separating compilation from running tests and compile in the background while downloading docker images(https://stackoverflow.com/questions/19543139/bash-script-processing-limited-number-of-commands-in-parallel). However db often accepts connections few seconds(even minutes in case of oracle) after container is up - so we would have to retry until it is ready. As for jest - I didn't have an opportunity to use it yet but I'm not sure if we will gain much from it if new layer needs to be added. Database creation for each test probably will be slow(often it creates new files in db container). New schema might be an option(few tests use multiple schemas, so schema with prefix would be necessary) but I think mysql, mariadb and oracle support only one schema per database. Another option would be to make tests separated from db driver they run on(single test runs single db driver, current test checks postgres, mysql -> 2 tests, one check only postgres, another one only mysql) and run them in parallel but make sure that two tests with same driver won't be running at the same time. Not sure if this is easily achievable. |
havenchyk
left a comment
There was a problem hiding this comment.
npm install sqlite3 --build-from-source was added recently, a comment from PR
This command has to be run because the pre-built versions of sqlite3 were not compiled with a recent enough sqlite lib, as in, >= 3.24.0. When you install sqlite3 from source, it builds using the bundled version that goes with it, 3.24.0. or with a custom version that can be specified with the --sqlite flag.
test/utils/test-utils.ts
Outdated
| if (process.env.CONNECTIONS) { | ||
| const connections = process.env.CONNECTIONS.split(","); | ||
| config = config.map((entry: TestingConnectionOptions) => { | ||
| entry.skip = connections.indexOf(entry.type) === -1; |
test/utils/test-utils.ts
Outdated
| config = require(__dirname + "/../../../../ormconfig.json"); | ||
| } catch (err) { | ||
| return require(__dirname + "/../../ormconfig.json"); | ||
| config = require(__dirname + "/../../ormconfig.json"); |
|
@Kononnable I tried separating compilation from execution. I wanted to run those things as separate stages in the job, but travis doesn't have good support for sharing things between stages. Running all in one process? I don't see how that would be better than what we have now. Creating a new and empty db should be fast, but yeah I don't know for sure that approach will work. It might get complicated supporting all these different db types. I don't think it's really possible to understand without having a working model. @havenchyk Thanks for the comments. If we split up the builds like this, I'd want to make sure sqlite is only installed when needed, otherwise it's pretty slow (and again Travis doesn't really help much). As for the style, I got TypeScript errors when trying to use |
|
@elthrasher I didn't get what's wrong with the idea to build docker image and then run it many times? Will it be too slow because of building step? |
|
@havenchyk The trouble there is Travis. There's no local Docker cache so I would have to either build the image in each process or build it, push it to some registry (now credentials are a problem), then pull it in each process. |
|
@elthrasher I was talking about the second approach (build, upload, use), but also have you tried using |
|
Yeah, a few of my attempts did something like that. The problem still is caching Docker. However, looks like there may be a way to hack around it: travis-ci/travis-ci#5358 (comment) |
|
I tried a bunch more things and TravisCI is just basically hostile to what I want to do. If I want to run a few parallel jobs, each of them will have its own cache that cannot be shared. There are a few github issues in which the Travis team says this is by design and won't be changed. Some of their reasoning makes sense, but it definitely doesn't in the context of a Docker build. What I want to do is build one version of the code in node 10 and then run several tests in parallel against that. It's not doable in TravisCI short of setting up an S3 integration or a Docker registry. The latter could be possible or we could look for another CI solution. In the mean time I'll leave this here and look at some of the jest ideas. |
@elthrasher |
|
Okay, lots of failures and a few successes here. There's been a long-standing issue that you can't just run tests against one kind of db. For example, disable all but postgres and run the tests and you'll get failures because it can't find mysql. I've fixed that so if mysql is disabled in ormconfig.json, no tests that require it will be run. I added an env variable I tried to do a sort of pipeline where the build happens once and then we run a bunch of parallel processes, one for each db connection. TravisCI just doesn't support this. There's no way to pass files from one stage to the next. Caches are not sharable. The only way we could do this on TravisCI is to publish a Docker image and then pull it for each parallel stage or to stage files on S3, both of which have their own complications. The real gain here would probably be fairly minimal as each stage would have to pull the Docker image, cutting into the time we saved. I experimented with running parallel mocha processes in the same job (sort of how it would work with jest, but explicitly by db connection). This works and gives us a slight improvement in time taken, however we get six times the logs so I had to switch to a more terse logging format. I tried running the setup stuff in parallel and saw some performance gains, but it gets complicated because travis doesn't do a great job of waiting for the setup to finish before the tests begin. If we were running 100 builds per day, I'd still optimize this, but I don't think the added complexity is worth it for typeorm. I removed node 9, which saw end-of-life last summer in favor of node 11. Fortunately all the tests still pass. I assume this is just a chore that nobody has gotten to yet rather than a commitment to support node 9. I tried altering the tests so that each test would create its own schema or database, which would let us convert to jest and full parallel execution (though it still remains to be seen how much improvement we'd get out of that). However, it's extremely complicated to do that for all the databases typeorm supports. I think it's doable, but should probably be its own PR if we decide we want to try it. Thoughts? If we want to go ahead with this, I'll add some more comments. |
|
Just reference to issue related to this changes #2807 |
mysql is required because very-very-old tests were using it (in the times when there was only mysql support in typeorm) and we still didn't refactor those old tests
if travis is a problem lets try some other CI. I have experience working only with travis and circleci. Are there better and popular/perspective alternatives? |
|
@pleerock This PR refactors those tests so that mysql won't always be required. It's not that Travis is ruining the project or anything. It's just that some of the suggestions made above won't work on Travis. It kills me a little that CI runs for 4-5 minutes before the tests even start, but is this really a big problem for typeorm? Probably not. I've added my comments so this is good to go from my perspective if we like these changes. If not, happy to discuss or revise. |
tsconfig.json
Outdated
| "build", | ||
| "node_modules" | ||
| "node_modules", | ||
| "test/utils/test-runner.ts" |
There was a problem hiding this comment.
Why this file is excluded and runned with ts-node?
There was a problem hiding this comment.
If that file is included in tranpilation, no tests are executed. I think it's some issue with the mocha global. I had started to run tests using ts-lint entirely but stopped after having some problems with Travis. Probably a good idea to take that up again and see if it will work. It should make local runs easier and allow us to exclude all tests from the build, which will make things faster.
|
Tests run via ts-node only now and are much faster! I'm surprised, but we've cut over two minutes off. This should also make development much nicer as compilation isn't necessary to run tests. I think we're now getting out of mocha what we could've hoped to get out of jest, so that conversion won't be necessary with the current feature set. Build times are still running 6-7 minutes but only 150 seconds are spent actually executing the tests. If we want to run faster, we could look at another CI, but I would merge this PR and start another for that. |
dfb13db to
a718475
Compare
|
This commit: 82ad52b#diff-165e041541ffbf626d08c6ac034a9c58R7 has removed almost all of the tests from execution via |
|
Ah well, running only one test explained the incredible test performance. Looks like we're back to normal levels, but I still think this is worth it. |
|
Ok, to sum up what are Pros and Cons of this PR? Pro: Con: I probably missed something here, so feel free to update the list. Is there any failing CI report so we can see how it looks like when CI fails? |
|
Here's how it looks when it fails: https://travis-ci.org/typeorm/typeorm/jobs/474388884 The performance gains for running parallel seem minor, so that could be removed for more verbose output, thus keeping most of the pros without the con. |
| ormconfig.json | ||
| ormlogs.log | ||
| npm-debug.log | ||
| test/functional/sqljs/*.sqlite |
There was a problem hiding this comment.
Why not use temp folder? It has it own gitignore file.
There was a problem hiding this comment.
That output had previously gone to build/compiled/test... which is gitignored already. I could redirect this output, but that would involve changing more tests. Think that would be better?
There was a problem hiding this comment.
If that how it always worked let's leave it for now.
| title: string; | ||
|
|
||
| @Column({ nullable: false }) | ||
| @Column("int", { nullable: false }) |
There was a problem hiding this comment.
Why was that needed? Shouldn't change much but don't see any obvious reason.
There was a problem hiding this comment.
This test was a little tricky. It implies it's testing an enum type, but it never creates an enum column in the db, just uses an enum in the orm code. When the code is transpiled, for whatever reason the column is created as an int, but running with ts-node it was sending object to mysql as the column type, which of course doesn't work. Adding int there made the test execute correctly - the same SQL statements are sent to the db for both the transpiled and ts-node versions.
There was a problem hiding this comment.
really useful to add according comment :)
|
Doesn't seem like the parallel execution is getting us anything other than confusing output so I removed it. I still think there are enough good things here to consider merging and maybe think about another CI which would support parallel better - or just solve some completely different problem. 10 minutes for CI isn't that bad. |
| "scripts": { | ||
| "test-ci": "gulp ci-tests", | ||
| "test": "rimraf ./build && tsc && mocha --file ./build/compiled/test/utils/test-setup.js --bail --recursive --timeout 60000 ./build/compiled/test", | ||
| "test": "ts-node test/utils/test-runner.ts", |
There was a problem hiding this comment.
I would like to keep previous setup. ts-node works very slow in windows (in my own tests) and I don't want to use it.
There was a problem hiding this comment.
it was few years ago last time I reproduced issue on windows however. Maybe we can keep ts-node
There was a problem hiding this comment.
Well, let me know. We could support both if desired.
|
Im okay to merge it |
|
I added circleci configuration. There are lot of useful options in circleci documentation. Sure we can improve ci process now |
|
I've measured times on my machine: Configurations where different(hardware, db engine config) so there is no point in comparing linux to windows etc. It looks like ts-node doesn't introduce performance problems on windows anymore(at least in our case). I think it's good or, we could support both ways if it is easy to implement. |
|
I'll give circleci a look when I can. As for running both ts-node and compiled, the main downside of that is that we don't need to ever compile the tests when we use ts-node - in fact they are excluded in the tsconfig.json in this PR. It does save a few seconds. |
|
@elthrasher I wasn't sure about this when I proposed this try, but I use ava as a test runner and there is an option there to run tests without pre-compilation, with requiring ts-node and it seemed to be faster :) |
|
So whats a status of this ? :-) |
|
I like the idea of using It seems there's a bunch of changes here that kinda all got conflated & made it harder to agree on merging them all in together We aren't using
I'll be closing this one, though - cause there's lots of conflicts and not too much movement for over a year. |

See if we can speed up tests by running in parallel on travis by db. I needed to rewrite a few tests as they would fail if mysql was not enabled. Some of this needs to be tweaked to be a bit more elegant. Can look at adding back mssql and oracle if this works out.