For the last few years, I tried to integrate BaseX into a CI/CD workflow (the one used by gitlab [1]).

My understanding of CI/CD explicitly includes automated tests so I can be as sure as possible I don’t break anything when doing further development. I pondered with using BaseX’ built in unit test framework [2], which I think is very good in many situations, but I was not really satisfied when it comes to checking RestXQ endpoints. The way it needs to be launched [3] is a bit awkward to me as a test for RestXQ and I could not come up with an easy way to automate this. When serving HTML based apps that interact with BaseX as a data store there is also no well-established way to do end-to-end testing, that is to for example programmatically click a button and capture the result, but they do exist for Node.js [4].

Unfortunately my projects almost never allow for more than a few tests due to budget and time constraints. So, I want to make them count. My experience is that such end-to-end tests are what can test the most code in JS and RestXQ with the least amount of test code. Admittedly, if you get an error, you go hunting for the real problem. Similarly, I use Node.js to do kind of an outside integration test for RESTful APIs. I have to admit I have a personal aversion against using many programming languages throughout my day. I try to use two or maximum three on any given day. But there are also other reasons: * For one JS and TypeScript are very likely consumers of a RESTful API. It is hard to escape JS or TypeScript today. * Other people are probably much better at their preferred programming languages but I hope almost anyone has a passive knowledge of JS. If this is true, then tests written in JS are good examples and candidates for translation into another languages test framework if necessary.

The (now old) gitlab CI/CD workflow uses herokuish [5] and Heroku buildpacks [6] (but not the actual commercial Heroku service) to achieve two things: * Bundle an application written in some programming language in a container without the author of the program needing to have any knowledge of containers, Dockerfiles etc. The author just needs to know the dependency tools of their programming language well * Having a well-defined way to start up tests and proceed with deployment if the tests succeed or stopping right there. The second point is something that the currently used process for building containers in gitlab, Cloud Native Buildpacks [7], still cannot do because they are only in the planning phase of a container interface for launching tests.

As I wanted to bundle everything needed to run and test an application running in the RestXQ environment provided by BaseX for the GitLab CI/CD process, I created a Heroku buildpack for BaseX based on the one for Node.js [8]. As I extended the Node.js buildpack everything is still controlled from package.json in principle. The “engines” definitions are amended to also include a version of BaseX and a version of Saxon to use [9]. Due to inheriting from the Node.js buildpack, JS dependencies for a HTML page that acts as the user interface for some RestXQ endpoints can be easily specified, a “build” script can build some sources written to use the Vue.js, React or angular frameworks. Or maybe only the dependencies of a more elaborate test suite need to be fetched like mocha, chai etc. [10] Also, there is a shell script “deployment/initial.sh” [11] is run so XML data can be fetched and loaded into BaseX at the time the container is built. For example, I use it to pull data from another git repository and execute a BaseX bxs script [12] to load the data, generate indices etc. A “test” script then needs to be defined to run the RESTful API endpoint tests [13] or the end-to-end test [14] automatically. Using this approach, it is possible to also launch any external process for testing so for example BaseX Unit module based tests could be launched additionally or instead of something truly Node.js based.

We have decided a while ago that we want to have private git repositories with all their CI/CD at gitlab.com. We provide the compute resources to run all builds and checks using a Kubernetes cluster we own. Back then github just didn’t provide any private repositories for free but we wanted to be present there and so we have all the public projects at github.com. The good thing about public repositories on github.com is the Actions workflows there which run in a VM that provides just about any conceivable programming languages build environment plus container building tools and more. The bad thing is: there is no immediately obvious recipe of how to make good use of that VM on github.com. But if there are container building tools we can run pretty much a copy of the gitlab CI/CD workflow that people over there came up with and that is documented in their AutoDevOps workflow definitions. So I cannot really show you the gitlab CI/CD workflow I made the buildpack for in action, you have to take my word for it or try it yourself on some gitlab instance. Reenabling the old herokuish workflow for build (AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED=false) and referencing my BaseX buildpack (BUILDPACK_URL=https://github.com/simar0at/heroku-buildpack-basex) will integrate BaseX into the AutoDevOps workflow. But you can also see it running in some of our public projects on github.com. There just a pretty stereotypical .github/workflows YAML file is needed and you can use the github.com Actions just fine [15]. That also has the advantage that one can utilize the infrastructure on github.com instead of providing some compute resources.

The package might be still a little rough around the edges but I use it now for a few projects of mine (and my institution).

I hope someone finds this useful. There are probably a lot of things that need to be fine tuned and I would be happy to work together to get this package better with time.

[1] https://docs.gitlab.com/ee/topics/autodevops/
[2] https://docs.basex.org/wiki/Unit_Module
[3] https://docs.basex.org/wiki/Unit_Module#Example
[4] for one of the solutions existing for Node.js check out https://www.cypress.io/ . That is what I used recently.
[5] https://github.com/gliderlabs/herokuish
[6] https://devcenter.heroku.com/articles/buildpacks
[7] https://buildpacks.io/
[8] https://github.com/simar0at/heroku-buildpack-basex
[9] https://github.com/acdh-oeaw/zuludict-app/blob/master/package.json#L6-L12 [10] https://github.com/acdh-oeaw/vleserver_basex/blob/main/package.json#L19-L25
[11] https://github.com/acdh-oeaw/zuludict-app/tree/master/deployment
[12] https://github.com/acdh-oeaw/zuludict-app/blob/master/deployment/deploy-zuludict-data.bxs [13] https://github.com/acdh-oeaw/api-problem4restxq/blob/master/package.json#L6-L8
[14] https://github.com/acdh-oeaw/vicav-app/tree/master/cypress/integration
[15] https://github.com/acdh-oeaw/vleserver_basex/blob/main/.github/workflows/build-vleserver_basex.yml

Best regards

--
Mag. Ing. Omar Siam
Austrian Center for Digital Humanities and Cultural Heritage
Österreichische Akademie der Wissenschaften | Austrian Academy of Sciences
Stellvertretende Behindertenvertrauensperson | Deputy representative for 
disabled persons
Wohllebengasse 12-14, 1040 Wien, Österreich | Vienna, Austria
T: +43 1 51581-7295
omar.s...@oeaw.ac.at | www.oeaw.ac.at/acdh

Reply via email to