Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Rewrote entire page to fit with version 1.0.0
Section
borderfalse
Column
Wiki Markup
{jenkins-plugin-info:pluginId=pretested-integration|jiraComponent=pretested-integration}
Column

Developed by

Alexander Winther Uldall
Ronni Elken Lindsgaard
Esben Skaarup
Andreas Frisch

NB! This is a temporary version of the plugin using a cloning approach. A new version using branching wil be released shortly

This plugin lets Jenkin manage a repository – keeping it in a clean state by only integrating changesets which build successfully. Builds – and thus repository updates – are triggered when developers push to another designated repository.

Description

Image Removed

This plugin aims to prevent accidentally breaking a repository through dirty commits. Instead of pushing directly to the repository in question, the clients will push to another repository made especially for this task. Jenkins will be triggered and start a build every time a changeset is pushed to this repository. Each build will merge the given changeset into the latest working copy of the project and run the job. If – and only if – the merged changeset builds successfully we will commit this to the original repository.

The system defined in this plugin depends on three parts: An 'upstream' repository where developers can pull the latest stable version; a 'downstream' staging repository to which developers push their changes and from where Jenkins extract changesets in order to build them and possibly commit them to the 'upstream' repository; and thirdly – in the case of distributed SCMs – the local repositories where developers work.

  • Upstream repository: This is the repository that you want Jenkins to manage in order to keep it in a working condition. This repository will usually be the original repository which clients pull from.
  • Staging repository: This repository is created by this plugin and is used by Jenkins to perform pretested integration. Clients will push their changesets to this repository to have them validated and - if they merge flawlessly with the current stable version and pass all tests - these changesets are integrated into the upstream repository.
  • Client repositories: These are the repositories on the client machines. The only changes required for these are to which repository they push changesets.

Limitations

The current version is a minimal working example and – as it is under development – there are some constraints to the plugin as it is:

  • Although the final plugin will support the most common SCMs – or at least allow for easy integration – only Mercurial is currently supported.
  • Only successful builds are fully supported. Problems during merge/build leaves the workspace in a non-working state, which must be fixed manually by clearing the workspace for the time being.

Setup

In order to get started using Pretested Integration, you need the three repositories described above. The upstream and local repositories probably already exist. Otherwise, you must set up a remote Mercurial repository and clone it onto the clients. For both existing and new repositories it is worth considering disallowing pushes directly to the upstream repository. If this plugin is applied to an existing project, the remote repository from the Jenkins job settings will be used as upstream repository. Please remember that only Mercurial is currently supported.

Image Removed

In Jenkins each job can be configured to use Pretested Integration from the job configuration page. Once selected, Jenkins will start building the job in question every time a developer pushes change to the repository defined in the plugin setup page (the staging repository). Whether or not this repository already exist, it is important to click 'Make/update repository': If the repository does not exist, it will be created at the given path and a repository hook will be added. If the repository already exists, the hook will simply be added. This repository hook is responsible for starting builds, why this step is important. Refer to the supplied screenshot for a visual example.

Image Removed

Wiki Markup
At this point client repositories should change their default configuration for push-requests to point to this staging repository. In Mercurial, this is done by adding a {{default-push}} parameter under the {{\[paths\]}} section in the repository's {{.hg/hgrc}} file, this this:

...


[paths]
default-push = ssh://server.com/upstream/repository/

Known Issues

Jira Issues
columnstype;key;summary
width85%
anonymoustrue
titleOpen issues
urlhttp://issues.jenkins-ci.org/sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml?jqlQuery=project+%3D+JENKINS+AND+status+in+%28Open%2C+%22In+Progress%22%2C+Reopened%29+AND+component+%3D+%27pretested-integration%27
height30%
  • Validation of the staging repository setup is not thorough enough.
  • Client SCM settings should be autogenerated for ease of deployment.
  • When two commits to the stage repository are made within a very short time interval, Jenkins will only trigger a single build instead of two.

Changes

No changes yet.

Introduction

The Pretested Integration Plugin offers a branchy approach to pretested integration (also known as pre-tested 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 Mercurial as a proof-of-concept implementation and Git implementation is planned as well.

Under the hood

Plugin footprint

The plugin manipulates the workspace after changes have been pulled by the SCM and before any build steps are run and after all build steps are run.

Before the build phase, a commit is checked out of the staging branch and merged into the integration branch in order to test compatibility. If the build is marked as stable, the workspace is scanned for further changes. If any changes are found, a new build will be triggered.

Finally, the workspace is cleaned up in order to prepare for the next build.

Mechanics

An extension point called an SCM interface is used to perform action on the workspace. The internal workflow is as following

1. A build is triggered (e.g. by polling)

2. The Pretested Integration plugin asks the SCM interface for the next commit to be tested, based on the commit tested in the previous build.

3. The Pretested Integration plugin asks the SCM interface to check out the integration branch and merge the found commit leaving the workspace in a state that makes it possible to build and test the changes invoked by the commit.

4. The build phase builds the software

5. The Pretested Integration plugin asks the SCM interface to act on the build result

6. If the build is verified, the commit should be integrated on the integration branch and pushed back to the repository by the SCM interface

7. If the build is not verified, the workspace should be rolled back so that another commit can be tested

8. The Pretested Integration plugin asks the SCM interface for the next commit to be tested

9. If any commits are found, a new build is triggered.

Handling false negatives

It is possible to obtain false negatives in the build phase, causing verifiable commits to be rejected. Resetting the job to rerun tests is an SCM interface implementation and is not handled by the Pretested Integration plugin natively.

Build with no changes

If a build is triggered and no commits for integration are found, then the build will be marked as NOT_BUILT

Setting up pretested integration with Mercurial

Development workflow

The workflow is adapted from the personal branch version of the branchy approach described in https://wiki.jenkins-ci.org/display/JENKINS/Designing+pre-tested+commit.\\

1. A named branch is used as the team integration branch (defaults to 'default'). 

2. The developer checks out a feature branch based on the integration branch and commits her changes. (hg update -C default && hg branch feature-branch)

3. Every team member has a designated staging branch (also a named branch) unto where she merges the changes and pushes this branch. (hg update stage-branch && merge feature-branch && hg commit -m "Finished development of feature")

4. Jenkins looks for changes on the stage branch, and integrates verified changes in the integration branch and pushes the updated branch.

Jenkins setup

For each staging branch, a Jenkins job is configured to poll for changes and trigger a build. A build is created for every found commit, and is sequentially merged into the integration branch if the commit is verified. 

Subsequent jobs should be configured by listening on the integration branch and commense further tests, deployment etc.

Job configuration

1. Under "Source Code Management" select Mercurial. For "Repository URL" use the repository url. Type in the name of the staging branch into "Branch".

2. Under Build Environment, check "Use pretested integration"

3. Select Mercurial and type in the name of the integration branch into "Integration branch".

_Note: A post-build action can also be configured, however it will automatically be activated by the plugin the first time a build is triggered._

Reset to latest integrated commit

The Mercurial SCM interface makes it possible to handle false negatives by resetting the internal state to check all subsequent changes not integrated from the last integrated commit in the stage branch history.

This is done by checking the checkbox named "Reset to latest integrated commit" under the Mercurial SCM interface in the job configuration.

False negatives which occur before a successful integration will need to be recommitted to be re-tested and integrated. 

Currently known issues

* Only builds with Result.STABLE is committed.

* It is not possible to customise the integration message

* If the integration branch does not exist, the plugin will fail.

Setting up pretested integration with Git

Not implemented yet

Extending the Pretested Integration Plugin

An example module is available at https://github.com/rlindsgaard/interface-example

Creating an SCM interface

To define a new SCM interface, create a public class which extends "org.jenkinsci.plugins.pretestedintegration.AbstractSCMInterface" and overrides the following methods. 

Interface methods

nextCommit

The method should return an extension of the AbstractCommit<?> class specifying the next commit to be merged and verified calculated from the last commit residing on both integration and staging branch.

prepareWorkspace

The method is invoked before the build starts, and after the SCM plugin has downloaded repository changes. 

A branch with the merge of the integration branch and the passed commit should be checked out.

handlePostBuild

After the build completes, depending on the build result, the method either integrates the commit being verified or rolls the workspace back preparing for the next build.

_Note: A default implementation exists that invokes commit() or rollback(), so it should it is not necessary to implement this method._

commit

Actually merge the commit into the integration branch in the workspace. This method is also responsible for 

rollback

If anything needs to be undone, do it here.

Identifying a commit

For Git and Mercurial, it is possible to uniquely identify a commit by a hash value. It is possible to parameterise "org.jenkinsci.plugins.pretestedintegration.Commit" in order to use a custom class or type which uniquely identifies the commit.

NB! This is a temporary version of the plugin using a cloning approach. A new version using branching wil be released shortly

This plugin lets Jenkin manage a repository – keeping it in a clean state by only integrating changesets which build successfully. Builds – and thus repository updates – are triggered when developers push to another designated repository.

Changes