Praqma / pretested-integration-plugin

A generic pretest commit plugin for Jenkins CI
MIT License
7 stars 14 forks source link

maintainer:

In this readme file you find developer oriented documentation, about contributing, testing, the architecture and different design decisions.

User oriented documentation is on the Jenkins community wiki plugin page.

The roadmap is a public Trello board. While a simple bug, or very simple feature request just can be reported directly on the Jenkins community issue tracker you should use the roadmap for discussing new ideas, complicated features and the future of the plugin.

Current development efforts are also maintained Kanban-style on the Trello board.

The plugin is maintained in the scope of Joint Open Source Roadmap Alliance (JOSRA) by Praqma. We happily accept pull requests - see section about contributing below.

Introduction

The Jenkins Pretested Integration Plugin offers a branchy approach to pretested integration (also known as pretested commits), which upholds the invariant; that for a specific branch, known as the integration branch, all commits have been verified.

The plugin delivers an API that makes it possible to easily provide pretested integration functionality for arbitrary SCM tools which is capable of using branches or a similar technology.

The plugin is currently shipped with support for only Git.

The plugin is designed to automate the CoDE:U Git Flow, but is not bound to a specific SCM work flow.

References

Plugin repositories

Roadmap

Roadmap for future development maintained here:

Wiki and issue tracker

The user oriented documentation is found on the Jenkins community plugin wiki page:

Issues are tracked in the Jenkins JIRA issue tracker:

The Pretested Integration Plugin workflows

The Jenkins community have an article about designing pretested commits. The original work on this plugin was inspired from the personal branch version of the branchy approach.

The plugin is designed to automate the CoDe:U Git Flow, but is not bound to a specific SCM work flow as long as you uses branches.

The recommended workflow are described in our user documentation on the Pretested Integration Plugin wiki page

Concepts:

Merge strategies:

Accumulated and Squashed. These are explained, together with more background information, and a discussion on the different merge strategies in JOSRA as a blog post: " Pretested Integration Plugin".

Architecture

Plugin phases

The plugin footprint during the build executions have the following phases:

Before the build phase, a commit is checked out of the ready branch and merged into the integration branch in order to test compatibility. If the build is successfull the integrated changed are published.

Build results

This plugin can downgrade a build result to:

The following build results are not changed:

Publish changes on success:

Design decisions

We currently miss documentation on a lot of the design decisions - they should go into this document.

The accumulated commit message

The accumulated commit message can not be generated automatically by git, as the squashed message, so the plugin must collect, extract and format the needed information from the commits that goes into the integration commit. This means that locale settings and language in the environment affect the string formatting regarding dates. It is an early decision that the accumulated commit message should look the squash commit message.

To make the accumulated commit message look almost identical to the squash message, we use english formatting of the date strings as this seems to be the default behavior for git squash commit message, if autogenerated. Independent from environments.

See the GetAllCommitsFromBranchCallback for actual implementation.

Message formatting:

See the plugin wiki page for more information on example commits and demo jobs: Demo jobs and example on commit messages and output

Relates to JENKINS-29369.

Only one integration repository is supported

Integration tests

Things you want to know...

Static git repositories

We have been using JGit to create test repositories programatically for the functional tests, which means every test created their own repository and for each test run. This approach works fine, but verifying commits in details can be hard as SHAs, timestamps etc. changes pr. test run. Therefore we have taken an static git repository approach, where we create the reposiories (by script or hand) once, and persist them in the repository as a test resource.

In src/test/resources/ there is a static git repository collection that can be re-used in tests, or you can create new ones. For details see the file src/test/resources/howtoTestUsingStaticGitRepos.md

There is a roadmap decision, that every new test should be using static git repositories as preferred setup for working with git repositories during functional tests.

Logging

Our strategy for logging in the plugin is to log:

Every console or user message must be prefixed with [PREINT], by defining LOG_PREFIX = "[PREINT] "; and using it listener.getLogger().println( String.format(LOG_PREFIX + "Preparing to merge cha ....

Use [PREINT] only in user messages and console output, as the java loggers know which class that logs already so it will be redundant information.

Example - printing to job console:

    listener.getLogger().println(LOG_PREFIX + "Failed to commit merged changes.");
    listener.getLogger().println(String.format(LOG_PREFIX + "Git command failed with exit code '%d' and error message:", exitCodeCommit));
    listener.getLogger().println(LOG_PREFIX + out.toString());

Example - just logging to java logger:

    logger.fine(String.format("Found remote branch %s", b.getName()));

This is not yet achieved fully in the plugin - but on our roadmap

Extending the Pretested Integration Plugin

Contributing

We happily accept pull request on Praqma's Github repository
This is used to release from, and accepting pull request. Do not make pull request on Jenkins CI on Github - it is only used as final archive for released versions.

Creating an SCM interface

To define a new SCM interface, create a public class which extends "org.jenkinsci.plugins.pretestedintegration.AbstractSCMInterface" and overrides relevant methods. Currently we have no guide or howto on this, but the Git implementation should serve as inspiration.

Acknowledgement

Code contributions were initially made by Computer Science students at University of Copenhagen DIKU as part of a study project.

Sponsors

The plugin is primarily developed for our customer - see the Pretested Integration Plugin wiki page

CodeScene analysis data

Get more details at codescene.io.

Developer tips

IntelliJ works fine for this project, you just need to open the pom.xml file and chosen open as project.

Check the Jenkins community plugin page as well: https://wiki.jenkins.io/display/JENKINS/Plugin+tutorial#Plugintutorial-IntelliJIDEA

I also installed the Stapler plugin, but their guide is slight wrong, when you're on the plugin page in settings, you need to go to Browse repositories to find the plugin.

Build environment - the right one

Building with a container so you don't need neither Java or Maven on your computer, and you're sure that the environment is the one we use as well on our build systems.

Find a suitable tagged image on https://hub.docker.com/_/maven/ chosing maven + java combo. Then you could run this command and it will do Maven stuff inside the container:

docker run -it --rm --name pretested-integration-plugin-maven-build-env -v "$PWD":/usr/src/mymaven -w /usr/src/mymaven maven:3.5-jdk-8 mvn clean install

But every time you run that command, Maven will download the hole world again, so instead we would like to re-use the Maven cache using a docker volume:

Create a volume:

docker volume create --name dev-env-4-pretested-integration-plugin-volume

Re-use that volume mounting it into the Maven container (if you read the Dockerfile behind it you see the cache is in /root/.m2 and also where to mount in your source code):

docker run -it --rm --name dev-env-4-pretested-integration-plugin-container -v dev-env-4-pretested-integration-plugin-volume:/root/.m2 -v "$PWD":/usr/src/mymaven -w /usr/src/mymaven maven:3.5-jdk-8 mvn clean

(You should chose short names for container and volume, I just long names to describe the commands better).