Skip to content

Commit

Permalink
JENKINS-25888: Documentation - updated readme in repository, mostly d…
Browse files Browse the repository at this point in the history
…eveloper oriented info
  • Loading branch information
Bue Petersen committed Dec 3, 2014
1 parent 9c068c8 commit 5fa964b
Showing 1 changed file with 134 additions and 74 deletions.
208 changes: 134 additions & 74 deletions README.md
@@ -1,104 +1,164 @@
# Pretested Integration
# Jenkins Pretested Integration Plugin

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](https://wiki.jenkins-ci.org/display/JENKINS/Pretested+Integration+Plugin).

The [_roadmap_](https://trello.com/b/tOQL6crl/pretested-integration-plugin) is a public Trello board.

The plugin is maintained in the scope of [Joint Open Source Roadmap Alliance (JOSRA)](http://www.josra.org/) by [Praqma](http://www.praqma.net). We happily accept pull request - see section about contributing below.

## 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 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 Mercurial as a proof-of-concept implementation and Git implementation is planned as well.
The plugin is currently shipped with support for only Git.

The plugin is designed to automate the **[CoDE:U Git Flow](http://www.praqma.com/resources/papers/git-flow)**, but is not bound to a specific SCM work flow.


## References

### Plugin repositories

* [Jenkins CI on Github](https://github.com/jenkinsci/pretested-integration-plugin) (used as final archive for released version)
* [Praqma's on github](https://github.com/Praqma/pretested-integration-plugin) (used to release from and accept pull requests)


### Automated builds

* **Praqma's build server** (used for daily development builds)
* [Pretested integration plugin build view](http://code.praqma.net/ci/view/Open%20Source/view/Pretested%20Integration%20Plugin/)
* [Pretested integration delivery pipeline](http://code.praqma.net/ci/view/Open%20Source%20Pipelines/view/Pretested%20Integration%20Plugin%20-%20build%20pipeline/)
* **Jenkins CI community build** (automated setup for all plugins, not used in our daily workflows)
* [Maven project pretested-integration-plugin]((https://jenkins.ci.cloudbees.com/job/plugins/job/pretested-integration-plugin/)



### Roadmap
Roadmap for future development maintained here:

* [Pretested integration plugin public Trello board](https://trello.com/b/tOQL6crl/pretested-integration-plugin)


### Wiki and issue tracker
The user oriented documentation is found on the Jenkins community plugin wiki page:

* [Pretested Integration Plugin wiki page](https://wiki.jenkins-ci.org/display/JENKINS/Pretested+Integration+Plugin)

Issues are tracked in the Jenkins JIRA issue tracker:

* [Pretested Integration Plugin - open issues filter]( https://issues.jenkins-ci.org/secure/IssueNavigator.jspa?mode=hide&reset=true&jqlQuery=project+%3D+JENKINS+AND+status+in+%28Open%2C+%22In+Progress%22%2C+Reopened%29+AND+component+%3D+%27pretested-integration-plugin%27)


## The Pretested Integration Plugin workflows

The Jenkins community have an [article about designing pretested commits](https://wiki.jenkins-ci.org/display/JENKINS/Designing+pre-tested+commit). The original work on this plugin was inspired from the [personal branch version of the branchy approach](https://wiki.jenkins-ci.org/display/JENKINS/Designing+pre-tested+commit#Designingpre-testedcommit-%22BranchySCM%22approach).

## 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.
The plugin is designed to automate the **[CoDe:U Git Flow](http://www.praqma.com/resources/papers/git-flow)**, but is not bound to a specific SCM work flow as long as you uses branches.

### Mechanics
An extension point called an SCM interface is used to perform action on the workspace. The internal workflow is as following
The recommended workflow are described in our user documentation on the [Pretested Integration Plugin wiki page](https://wiki.jenkins-ci.org/display/JENKINS/Pretested+Integration+Plugin)

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.
Concepts:

### 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.
* The **ready branch** the developer branch with changes, that should be integrated. It is called ready, because of our recommended naming conventions in the [CoDe:U Git Flow](http://www.praqma.com/resources/papers/git-flow).
* **Ready** branches are specified by configuring the SCM plugin (not the prestested integration plugin) to pic up changes on those specific branches. For the Git plugin, it is the `Branch Specifier`.
* The **integration branch** is the target branch for integration. This is where changes from the ready-branches comes in.

### 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.
## Architecture

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.
### Plugin phases

### 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.
The plugin footprint during the build executions have the following phases:

#### 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".
* **Integrate**: Integrates SCM changes _locally_ by manipulating the workspace. Executed after changes have been pulled by the SCM plugin, and before any build steps are run.
* **Publish changes**: As a post-build step, a decision is made based on build result, after all build steps are run, whether to publish the integration.

_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._
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:

* `NOT_BUILD`: If a build is triggered and there is not changes for on the _ready_ branch, then the build will be marked as NOT_BUILT
* `FAILED`: If any of the pretested integration plugin phases find a configuration error, or a problem is detected during integration or publish.

The following build results are not changed:

* `FAILED` and `UNSTABLE`: If any build step prior to the integration phase fails, the pretested integration plugin never get control. If build result becomes failed after the integration phase, the plugin never executes the publish phase thus integration is not published.

Publish changes on success:

* `SUCCESS`: If build result successful until the publish changes phase, the integration changes will be published.

## Design decisions

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

## Logging

Our strategy for logging in the plugin is to:

* **Exceptions**: The automated added logging lines logs for almost all exceptions entering and existing exception handling. That is okay, but I need more information than that - human well described situation report pr. exception. Why did we end there? How ? What do we suspect is wrong. Log those informations, as well as stacktrace message and so fort. Also log if we re-throw the exception.
* **State transitions or decisions**: please log situation where we change state or make decisions. Examples can be that we can't find the branch, it does not fulfil requirements, there is no new commit and so forth. Typically this is placed where we might print something to console for the user, I want that in the log as well.
* **Every user message or output to Jenkins console**: User messages and console output should be logged as well - it will be way easier to follow those large logs, if the same messages we see in Jenkins job console is there as well.

_This is not yet achieved fully in the plugin_

#### Automated inserted logging statements
Praqma have a little java tools called Code-injector that can be used to automatically insert logging statements in java code.

The project is available internally in Praqma.

We have used to add logging to this plugin at a point where there were missing lots of logging.

Automated logging looks like this:

public String getRevId() {
logger.entering("GitBridge", "getRevId");// Generated code DONT TOUCH! Bookmark: 7daeaf95ed1ab33f362632d94f8d0775
logger.exiting("GitBridge", "getRevId");// Generated code DONT TOUCH! Bookmark: 05723ee14ce48ed93ffbd8d5d9af889a
return this.revId;
}

_Notes to use the project internally in Praqma (add/remove automated logging)_:
To run the operation clone the `code-injector` project from Praqma's internall Gitlab, and run `mvn clean install` to add it to the local maven cache.
Next clone both `pretested-integration-plugin` and `usecase-pretested-integration-plugin` from the code-injector namespace.

The java class called `InsertLoggingStatements` contains a path pointing to the `pretested-integration-plugin`, change that as appropriate.
Run the `Main` class and check the results.

#### 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
### Contributing
The official repository is at https://bitbucket.org/rlindsgaard/pretested-integration-plugin please use this repository for the current development branch and pull requests.

### 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.
### Contributing

#### 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.
We happily accept pull request on [Praqma's Github repository](https://github.com/Praqma/pretested-integration-plugin)
This is used to release from, and accepting pull request.

##### 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.
* We don't accept changes, that doesn't reference a Jira issue.
* Every code change must be tested, so there should be either new tests contributed or tests that are changed to new workflows.
* We currently favor functional testing, going through user scenarios in favor of unit tests. Best of course to contribute to both.
* Unless it is a simple bugfix, or feature implementation, please consult the [Pretested Integration Plugin **roadmap** Trello board](https://trello.com/b/tOQL6crl/pretested-integration-plugin) to discuss implementation ideas.

##### 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._
### 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.

##### 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.
## Acknowledgement

### 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.
Code contributions were initially made by Computer Science students at University of Copenhagen [DIKU](http://www.diku.dk) as part of a study project.

## Inserting logging statements
Code-injector is used to achieve automatic insertion of logging satements. The project is available internally in Praqma.
* Ronni Elken Lindsgaard
* Alexander Winther Uldall
* Esben Skaarup
* Andreas Frisch

To run the operation clone the code-injector project from gitlab and run mvn clean install to add it to the local maven cache.
Next clone both pretested-integration-plugin and usecase-pretested-integration plugin from the code-injector namespace.
### Sponsors

The java class called InsertLoggingStatements contains a path pointing to the pretested-integration-plugin, change that as appropriate.
Run the Main class and check the results.
The plugin is primarily developed for our customer - see the [Pretested Integration Plugin wiki page](https://wiki.jenkins-ci.org/display/JENKINS/Pretested+Integration+Plugin)

0 comments on commit 5fa964b

Please sign in to comment.