Home

Awesome

drkns is a simple build tool aimed at easing the continuous integration of monorepos through dependency aware caching.

Build Status

Le problem

Monorepositories contain many projects, it rarely makes sense to rebuild a every project when changes are committed.

But we can't limit ourselves to run builds and tests in directories where changes occurred because some projects depends on others.

Quick start

You wild kid!

    Confucius

Check a dummy project on which our tests are based.

Create your drkns.yml files

From your monorepo root, in drkns.yml:

dependencies:
  project1: projects/project1
  project2: projects/project2
  library1: library/library1

Sample projects/project1/drkns.yml:

checkSteps:
  installDependencies: pipenv install
  test: pipenv run pytest
buildSteps:
  build: pipenv run paver build
  deploy: pipenv run paver deploy_to_pypi
dependencies:
  - ../../library/library1

Test that everything is alright

drkns check  # Check the configuration file
drkns list   # Check list the identified steps
drkns run    # Run everything

.gitignore hygiene

echo '.drknspersistence/*' >> .gitignore

In your CI

With environment variables:

pip install drkns

drkns check             # We never know
drkns sync in --delete  # Get past execution statuses from S3
drkns debug             # If needed, you can check which steps are
                        #   going to run here
drkns run               # Run all steps
drkns clean             # Will remove four weeks old execution statuses to 
                        #   limit disk usage
drkns sync out --delete # Persist all execution statuses from S3,
                        # **use --delete** to also delete data removed by 
                        # `clean`, or not push old data that has been removed
                        # in the remote storage.

Troubleshooting

Trigger a new build without changing anything

We all like stable builds but sometimes life happens and things break where they should not. We would love to relaunch our CI without having to just randomly edit a file to ignore the caching.

If you have a DRKNS_S3_PATH environment variable you can remove it from the commands.

drkns sync in s3://my-drkns/project --delete
drkns sync forget dir1_project2/fedd32a-adbcc445555
drkns sync out s3://my-drkns/project --delete

The --delete flag is required, as S3 synchronization otherwise ignores files that have been removed locally.

Documentation

Unit

Each drkns.yml forms a unit, it should represent a specific unit of your code, a directory containing a lib or a project, that has specific build steps or can be depended on.

drkns.yml accepted fields:

Steps

Steps :

Three different step types are available, by order of execution:

  1. checkSteps: steps necessary to check the integrity of the unit. Will always be ran if no checkSteps has already failed in this unit. Typically used to build your application, your docker images and run your unit tests. If a steps fail, the following ones will not be executed.
  2. buildSteps: steps executed only if checkSteps, dependencies' checkSteps and previous buildSteps succeeded. You can use this to upload or deploy the build artifacts. Beware there is no guarantee that dependencies will be executed, there execution might have been started
  3. cleanupSteps: steps executed no matter what (except if the unit has not changed since last execution). You can suppress things that have taken too much memory or things in the like.

Warning: implicit cleanup of background tasks

If any of your steps used the background attributes they are killed after the cleanup steps at the end of the execution of your `unit.

Caching

The point of drkns is to not rerun everything for every change.

Upon execution a .drknspersistence folder in the directory of each unit will be created, this folder will contain the execution status of each step for a specific unit, step and a specific hash.

At each execution a hash for the unit is computed, it changes if files within the unit or its dependencies hashes have changed. If it is present in the persisted files, it will prevent the execution.

Ignoring files .drknsignore

Often, it happens that the execution of steps will alter some files in the directory changing the mentioned above hash.

It is not necessarily something that we wish.

You can add partial or full file or directory names (as long as they have a trailing /) to be ignored in a .drknsignore file. A unit will ignore specific patterns.

Warning: .drknsignore are also inherited from parents. Because of this path are not supported to avoid ambiguity.

The ignored elements are passed to dirhash's ignore argument. The relevant documentation is available at https://pypi.org/project/dirhash/ .

Sample .drknsignore:

*.tmp
build/

Persistence

Persistence is enabled through S3 buckets.

You need a DRKNS_S3_PATH environment variable, or provide it as a command line argument.

export DRKNS_S3_PATH=s3://some-drkns-bucket/someProjectDirectory

drkns expects AWS environment variables to be defined: AWS_ACCESS_KEY_ID, AWS_DEFAULT_REGION and AWS_SECRET_ACCESS_KEY for the AWS client to work properly.

Parallel CI generation

This is an advanced usage. You are invited to skip this if this is your first dive in drkns.

Once your CI is setup, maybe you want to parallelize job execution, drkns can generate your CI configuration, provided you write a template.

The template must be located at .drknsgeneration/*.template.*, only a single template file must be in this directory.

If you need a more concrete example, check the dummy project sample main.template.yml.

Fields to be defined in the template, always in the form %FIELD_NAME%:

drkns CLI

Commands

Options

Output

drkns output is composed of the failed steps output only and a summary.

Failed steps output

Output for unitName1@stepName1:
/bin/sh: line 1: stop: command not found

In case a step got canceled because of a previous failure:

Output for unitName2@stepName2:
Previous failure of dependency1 / dependency1FailingCheck

Summary

dependency1@dependency1FailingCheck: Error (restored)
dependency1@dependency1Build: Ignored
dependency1@dependency1Cleanup: OK (restored)
project1@project1Check: OK (restored)
project1@project1ShouldNotRunBuild: Ignored (restored)
project1@project1Cleanup: OK (restored)
project3@project3Build: OK
project3@project3failingCleanup: Error
project3@project3NeverExecutedCleanUp: OK
main@mainCheck1: OK
main@mainBuild1: Ignored

Step statuses:

(restored) indicates that the execution did not happen this round but was cache from a previous step.