The following stack is used when developing Codekvast (in alphabetical order):
- Angular 8+
- AspectJ (in Load-Time Weaving mode)
- Chrome headless
- Docker Engine - Community 19.03+ and Docker Compose 1.24+ (For running MariaDB and RabbitMQ in development environment)
- git-crypt
- Github
- Gradle (via Gradle wrapper)
- Inkscape (SVG graphics)
- Java 8, 9, 10, 11, 12, 13 and 14 (managed by SDKMAN).
- jq (for parsing JSON in scripts)
- Kotlin
- Lombok
- MariaDB 10+ (Codekvast Dashboard)
- Node Package Manager (npm)
- NodeJS
- Spring Boot
- TypeScript
- Webpack
- Yarn
- yq (for parsing YAML in scripts)
The product itself lives under product/
.
Server-side stuff lives under product/server
, while agent stuff lives under product/agent
.
Sample projects to use when testing Codekvast lives under sample/
.
Docker-related stuff live under docker/
.
Development tools live under tools/
.
Provisioning scripts live under deploy/
.
NOTE: Some files are encrypted with git-crypt since it stores sensible data like cloud provider credentials!
Authorized developers are enabled to unlock the repo by adding their public GPG keys.
See man git-crypt
, git-crypt help add-gpg-user
and git-crypt help unlock
.
Web pages (i.e., https://www.codekvast.io) lives in the Git repo https://github.com/crispab/codekvast-site
.
There are a couple of Bash scripts that prepares the development environment.
They work for Ubuntu, and are called tools/install-compilers.sh
and tools/prepare-workstation/run.sh
.
They use Bash and Ansible for setting up the workstation so that it works for Codekvast.
If you run some other OS or prefer to do it by hand, here are the requirements:
Some files in the deploy/
directory is encrypted with git-crypt
and GPG public keys.
Which files that are encrypted can be seen in deploy/.gitattributes
.
You must be added as trusted developer by git-crypt add-gpg-user
to access the secrets.
SDKMAN is required.
In SDKMAN, the Java versions that are required are defined by gradle.properties
.
Node.js 12+, NPM 3.10+ and Yarn 1.13+ are required. Chrome and Firefox are downloaded on demand for executing system tests.
git-crypt is required for deploying to the cloud.
Use the following command to install OpenJDK 11, git-crypt, Node.js, npm, Chrome and Yarn (Ubuntu, Debian):
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt install openjdk-11-jdk openjdk-11-doc openjdk-8-source git-crypt nodejs
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update && sudo apt-get install yarn google-chrome-stable
The Codekvast Dashboard web UI is developed with TypeScript and Angular 7. Twitter Bootstrap is used as CSS framework.
npm and yarn are used for managing the frontend development environment. Webpack is used as frontend bundler.
Docker Engine - Community 19.03 or later and Docker Compose 1.24 or later is required for Codekvast Dashboard development.
Install Docker Engine - Community v19.03+ using the official instructions.
Install Docker Compose 1.24+ using the official instructions.
Graphics including the Codekvast logo is crafted in SVG format, and exported to PNG in various variants and sizes. Inkscape is an excellent, free and cross-platform SVG editor.
Codekvast uses Gradle as build tool. It uses the Gradle Wrapper, gradlew
, which is checked in at the root of the workspace.
There is the convenience script tools/src/script/gradlew
which simplifies invocation of gradlew. Install that script in your PATH
(e.g., /usr/local/bin
), chmod +x /usr/local/bin/gradlew
and simply use gradlew
instead of path/to/gradlew
Codekvast is built by Jenkins at http://jenkins.crisp.se on every push, to all branches.
The pipeline is defined by Jenkinsfile
.
To access http://jenkins.crisp.se you need to be either a Member or an Outside collaborator of https://github.com/orgs/crispab/people.
Codekvast Agent is published to https://downloads.codekvast.io as well as to jcenter.
You execute the publishing by executing tools/ship-agent.sh
in the root of the project.
Preconditions:
-
curl
installed. -
Clean workspace (no work in progress).
-
On the master branch.
-
Synced with origin (pushed and pulled).
-
Bintray credentials either in environment variables
CODEKVAST_BINTRAY_USER
andCODEKVAST_BINTRAY_KEY
or as values in in~/.gradle/gradle.properties
:codekvast.bintray.user=my-bintray-user
codekvast.bintray.key=my-bintray-key
-
my-bintray-user
must be member of the Crisp organisation at Bintray.
Intellij Ultimate Edition 2019+ is the recommended IDE with the following plugins:
- Lombok Support (required)
- Google Java Format (required)
- Angular 2 TypeScript Live Templates (optional)
- JavaScript Support (optional)
- Karma (optional)
- Git (optional)
- Github (optional)
- Docker (optional)
Do like this to open Codekvast in Intellij the first time:
- File -> New -> Project from Existing Sources...
- Navigate to the project root
- Import project from external model...
- Select Gradle
- Click Next
- Accept the defaults (use the project's Gradle wrapper)
- Click Finish
After the import, some settings must be changed:
- File > Settings...
- Build, Execution, Deployment > Compiler > Annotation Processing
- Check Enable annotation processing
- Click OK
The general editor config for IDEA is stored in .editorconfig
.
For Java and IDEA, The google-java-format
plugin is required!
If you use some other IDE, please make sure to format the code in format as close to this as possible. The google-java-format is available for the major IDEs.
Most important rules:
- INDENT WITH SPACES!
- Indentation: 2 spaces
- Line length: 140
- Charset: UTF-8
The formatting of TypeScript is described and enforced by tslint.js files in the projects that use TypeScript. IDEA will automatically pick up and apply these settings when found.
All of the non-trivial code is covered with unit tests.
Some tricky integrations are covered by proper integration tests where the external part is executing in Docker containers managed by the tests.
There is also a smoke test that launches MariaDB and Codekvast Dashboard, and executes some Web Driver tests. This is just a smoke test though.
To assist manual e2e tests, there is a number of sample apps that are managed by Gradle. They are configured to start with the latest Codekvast collector attached.
The following procedure can be used for demo purposes and also when doing development with live data flowing.
- Launch 4 terminal windows
- In terminal #1 do
./gradlew :product:server:dashboard:bootRun
. This will start Codekvast Dashboard that will consume the data files uploaded by the instrumented apps. - In terminal #2 do
./gradlew :sample:jenkins1:run
. This will download and start one version of Jenkins with Codekvast attached. - In terminal #3 do
./gradlew :sample:jenkins2:run
. This will download and start another version of Jenkins with Codekvast attached. - In terminal #4 do
./gradlew :sample:sample-gradle-application:run
. This will launch the short-livedsample.app.SampleApp
with Codekvast attached. The SampleApp is handy when you want to correlate source code to the data that is collected by Codekvast. - Open a web browser at http://localhost:8081. It will show the dashboard web interface wher e you can inspect the collected data.
In addition to the above do this:
- Launch a terminal window
cd product/server/dashboard/src/webapp
npm start
. It will start an embedded web server on port 8088. It reloads changes to the webapp automatically. It will also refresh the browser automatically.- Open the web browser at http://localhost:8088
When running the dashboard webapp from npm start
there is a number of canned REST responses available.
This makes it possible to develop the webapp with nothing else than npm start
running.
The canned responses are really handy when doing frontend development, where live data is strictly not necessary.
In the Methods page, the canned response is delivered from disk by searching for the signature -----
(five dashes).
Canned responses has to be re-captured every time the dashboard REST API has been changed.
The canned response for /webapp/v1/methods
is captured by executing
curl -X GET --header 'Accept: application/json' 'http://localhost:8081/webapp/v1/methods?signature=%25&maxResults=100'|jq . > product/server/dashboard/src/webapp/src/app/test/canned/v1/MethodData.json
git add product/server/dashboard/src/webapp/src/app/test/canned/v1/MethodData.json
from the root directory while ./gradlew :product:server:dashboard:bootRun
is running.
When doing the capture, make sure that data from the three above mentioned sample apps is stored in the dashboard.
(The JSON response is piped through jq .
to make it more pretty for the human eye.)
On some Linux distros, both IntelliJ IDEA and the Node.js uses the system service inotify
to watch directories for changed files.
If the limit is to low, npm start
will fail.
If you happen to use Ubuntu, here is the remedy:
Create the file /etc/sysctl.d/60-jetbrains.conf
with the following content:
# Set inotify watch limit high enough for IntelliJ IDEA (PhpStorm, PyCharm, RubyMine, WebStorm).
# Create this file as /etc/sysctl.d/60-jetbrains.conf (Debian, Ubuntu), and
# run `sudo sysctl --system` or reboot.
# Source: https://confluence.jetbrains.com/display/IDEADEV/Inotify+Watches+Limit
#
# More information resources:
# man inotify # manpage
# man sysctl.conf # manpage
# cat /proc/sys/fs/inotify/max_user_watches # print current value in use
fs.inotify.max_user_watches = 524288
Then do sudo sysctl --system
to activate the changes.