This document describes best practices of developing the Mendix Buildpack. Use in conjunction with CONTRIBUTING.md .
The buildpack features the following directories:
bin: Cloud Foundry buildpack lifecycle scripts, utility scripts and binaries live herebuildpack: All Python code lives here, this is the home of the main buildpack module. Entry points arestage.pyandstart.pydev: Code for local development and CI lives heredocs: Extra documentation in Markdown format lives hereetc: Configuration templates for e.g. nginx and M2EE live herelib: A forked version of M2EE Tools suited for the cloud lives here, used for working with the Mendix Runtimetests: All test code lives herevendor: All vendorized dependencies live here
The buildpack is a Python project, and you must have some experience in Python, bash and the make system to develop.
For developing the buildpack, you must set up the following:
- A shell / terminal of your choice
- Docker
- The Cloud Foundry CLI and the
cf-localplugin - A
pyenv virtualenvvirtual environment (or you can choose to develop in a Docker container)
pyenv in combination with pyenv-virtualenv can be used to create a local Python virtual environment to develop in. Note that you'll have to create an environment with the latest version of Python 3.6 - the default in the Cloud Foundry root filesystem ( cflinuxfs3 ) we use to deploy applications on.
As an alternative to running Python on your host you can run it in a Docker container. To do this:
- Set up required environment variables
- Go to the
dev/directory - Run
./run-locally.shThis will start the Docker container with preinstalled Python and provide you with an interactive shell. The project folder will be mapped to the current folder in the Docker container, so if you edit files on your host, the changes will be immediately available in the container.
The buildpack makes use of the make system. For dependency management, pip-compile is used under the hood.
A few make targets to use are:
vendor: downloads the Python runtime dependencies as wheels intobuild/vendor/wheels, and copies over vendorized dependencies to thebuild/vendor/install_requirements: installs all requirements and generatesrequirements.txt
Never change the requirements*.txt files directly! Use requirements*.in to that.
For integration tests, you need to have installed the prerequisites. Once you have those in place, you can set up the following environment variables:
export TEST_PREFIX="<prefix identifying your test run; default=test>"
export TEST_PROCESSES="<amount of simultaneous tests to run; default=2>"
export TEST_HOST="<custom host the tests will use to connect to dependencies; default=host.docker.internal>"
export TEST_MEMORY="<memory a test app container gets; default=1G>"
export TEST_DISK="<disk space a test app container gets; default=1G>"To ensure that your CF cluster has the buildpack you're developing available, use the following make targets:
clean: removes all the nasties, including leftover Mendix files, from your working directorylint: ensures that code adheres to our standardsbuild: builds the buildpack, i.e. updates / fetches all dependencies that need to be in source control, including all runtime Python dependencies as wheels, and compresses it todist/
You can include ("vendor in") any dependency you want in your build by adding it to vendor/ directory. This will ensure that the dependency is packaged in the buildpack artifact. This is especially useful for testing dependencies you have built yourself locally, but are not available online yet.
The dependency resolution will detect dependencies in vendor/ regardless of subdirectory. The only condition is that you use the same file name as the dependency you would like to vendor in instead of getting it online.
We have split up tests into unit tests, which do not need to fully start a Mendix application, and integration tests, which do.
To run all the tests locally you need to do is to go to the root folder and run the following command:
make testTo run the unit (offline) tests only, run the following command:
make test_unitTo run the integration (online) tests only, run the following command:
make test_integrationYou can keep watch on the tests with regular Docker commands such as docker ps .
To run one or more separate tests do:
make test_integration TEST_FILES='file1, file2'As extension of the integration tests, a Command Line Interface (CLI) is available. This CLI enables you to run an arbitrary MDA with cf-local without having to do the heavy lifting yourself.
The CLI loosely follows the Docker CLI commands for run , rm and logs .
The CLI can be accessed by running the following command from the project root:
python3 tests/integration/runner.pyThe CLI features a help prompt to get you started:
python3 tests/integration/runner.py --helpAn example that runs the myapp application with a PostgreSQL database container and two environment variables:
python3 tests/integration/runner.py run --name myapp --with-db -e ENV1=VALUE1 -e ENV2=VALUE2 myapp.mdaAfter running the application, standard Docker commands and Docker tooling can be used to manipulate the application container(s).