First off, thank you for considering contributing to hesperides-jenkins-lib
!
There are many ways you can help us in this project:
- first, test it and tell us what you think about it !
- help us by communicating around the project: present it to your coworkers, and maybe use it in your organization !
- suggest new features and/or improvements to existing ones: get a look at the "suggesting new features" section below detailing how to proceed
- tell us when you face bugs by creating a bug report issue
- contribute some code to the project, by making a pull request
Overall, don't hesitate to get in touch with us throught this project issues for any request, even for simple questions.
First off, make sure it hasn't been suggested before by making a quick issues search.
If not, simply open an issue including the following information:
- a short description of what you have in mind
- why you need this feature : this will help us to understand your need and maybe suggest an existing solution or an alternative approach
- as much explanatory documentation as you are willing to add:
- a simple diagram is often very helpful
- a user story or a user-centered usage scenario
- in case of REST API changes, a Swagger spec
- finally, whether you are willing to work on a PR to implement it
First off, make sure it hasn't been reported yet by making a quick issues search.
If not, please open an issue including the following information:
- the current version of
hesperides-jenkins-lib
you are using - some detailed steps to reproduce it (e.g. a
Jekinsfile
) - please include the Jenkins logs and stack trace whenever possible
The overall process is:
- Make sure there is an issue detailing the feature you want to implement or bug you want to fix. Ideally, indicate in this issue that you intend to work on it to begin with.
- Fork this repository under your GitHub username, and install your development environment.
- Write some code !
- Commit and push your changes on your forked repo, ideally on a specific branch and not on
master
(to allow you to work on different issues in parallel). During this step, the continuous integration checks will be executed to detect issues before your code is merged. - Create a pull request, and make sure the Travis CI & Circle CI builds pass. Then mention in the related issue that you created this PR, and ask for a code review.
- It is very likely you will be asked to make some minor changes: simply add commits in your branch on your forked repo, they will be automatically taken into account in the pull request, and then squashed by GitHub when merged.
Once you've fixed all the potential issues, a maintainer of this project will merge your contribution.
That's it !
There is the list of things to include in your PRs, and that reviewers will check:
- the code uses the idioms already present in the code:
required
arguments,httpRequest
method used for HTTP calls, public API up-to-date invars/hesperides.groovy
, etc. - you ran the linter (cf. Coding style)
- the existing non-regression tests pass (cf. Continuous integration)
- you added new tests
- the documentation has been updated: code snippet
Jenkinsfile
, detailed doc invars/hesperides.txt
,CHANGELOG.md
&CONTRIBUTORS.md
updated
You will need Docker & docker-compose
. A local Groovy & Gradle installation may also help you to run things (linter, tests) more easily.
The tests require the $HESPERIDES_HOST
environment variable to be set, including the protocol.
An optional $HESPERIDES_PORT
can also be specified,
along with $HESPERIDES_AUTH
as <USERNAME>:<PASSWORD>
.
gradle test
To run a single test:
gradle -Dtest.single=HesperidesIntegrationSpec test
The test report is generated in build/reports/tests/test/index.html
.
Integration tests use a dockerized Hesperides instance.
docker-compose build
docker-compose run gradle-check
To skip the CodeNarc linter and only execute tests:
docker-compose run gradle-check gradle test --debug --stacktrace
To expose the build/
directory generated, containing the tests reports:
docker-compose run --volume ./build:/home/gradle/build gradle-check
If you want to only use Docker to launch an Hesperides instance:
docker-compose up -d hesperides
HESPERIDES_HOST=http://localhost
HESPERIDES_PORT=8080
gradle test
Currently, we do not enforce any code style, but we strongly encourage you to execute the CodeNarc Groovy linter:
gradle check
In general:
- follow Robert C. Martin "Clean Code" recommendations.
- we avoid methods with too many parameters, we use named-parameter with
Map args
, and validate necesseray parameters withrequired
. - do NOT
@Grab
in source files undersrc/
, it makes the code non-testable
Two online services are configured on this project to automatically execute tests on every commit on each each commit or pull request:
- Circle CI will run Gradle integration tests with a running Docker instance of Hesperides, cf. .circleci\config.yml
- Travis CI will run some static analysis checks, cf. .travis.yml and the next section
In order to execute a number of checks before each commit, this project uses git
pre-commit hooks.
They are listed in the .pre-commit-config.yaml configuration file.
As much as possible, please try to install them on your development machine. If you can't or don't want to, you'll have to use the Travis CI build logs to debug issues that may arise with them.
To install them on your development machine, you will need Python, and the pre-commit
package that can be installed with pip
.
To configure git
to run them before each commit, execute the following command:
pre-commit install
You can also run those hooks manually:
pre-commit run $hook_name # execute a single hook on all modified files
pre-commit run --files $file1 $file2 # execute all hooks on some selected files
pre-commit run --all-files # execute all hooks on all files
Every pull request must be reviewed by a current maintainer of the project, and get their approval.
Code reviewers should follow the PR Checklist and those guidelines:
- complete the
CHANGELOG.md
file - for any method addition / arguments change, ensure a piece of doc exists for them in
vars.hesperides.txt
- bumb the
pom.version
inbuild.gradle
git commit
&git tag
&git push --tags
- set the
ARTIFACT_REPO_URL
/ARTIFACT_REPO_USERNAME
/ARTIFACT_REPO_PASSWORD
environment variables &gradle upload
Because we want this library to be usable both with the standard Groovy interpreter and the jenkins groovy-cps plugin, we faced the challenge of making HTTP requests in both contexts:
-
in Jenkins pipelines, the recommended solution is to use the non-builtin http_request plugin. Another, more hacky approach, would be to use the sh step +
curl
. -
with the Groovy standard interpreter, groovyx.net.http.HTTPBuilder is a very common library to make HTTP calls
Both are based on org.apache.httpcomponents.httpclient.
In order to use either one dependeing on the execution context, we created the com.vsct.dt.hesperides.jenkins.pipelines.http
package to abstract this into an HTTPRequester
interface:
abstract
classes &traits
do not work : cf. https://issues.jenkins-ci.org/browse/JENKINS-39329 & https://issues.jenkins-ci.org/browse/JENKINS-46145- static nested classes limitations : https://issues.jenkins-ci.org/browse/JENKINS-41896
- use
JsonSlurperClassic
instead ofJsonSlurper
: http://stackoverflow.com/a/38439681/636849 - assignment in
if
statements : https://issues.jenkins-ci.org/browse/JENKINS-41422 .empty
is buggy, always uses.isEmpty
: https://issues.jenkins-ci.org/browse/JENKINS-50863List.sort()
does not work properly with aClosure
parameter : it does not return a list and will not sort it. _cf._https://issues.jenkins-ci.org/browse/JENKINS-44924 & https://wiki.jenkins.io/display/JENKINS/Pipeline+CPS+method+mismatches
Some of those "code smells" are detected by git
pre-commit hooks defined in .pre-commit-config.yaml.
javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
exception when using http_request plugin : you need to run Jenkins with Java 8, a bug with Java 7 will prevent you from making HTTPS requests.
Deleting an artifact in both Groovy & Maven caches, to test re-downloading (yes, Groovy will use Maven cache by default !) :
rm -r %HOME%\.groovy\grapes\com.cloudbees\groovy-cps %HOME%\.m2\repository\com\cloudbees\groovy-cps
Rerunning a script with increased logging:
set CLASSPATH=src
groovy -Dgroovy.grape.report.downloads=true -Divy.message.logger.level=3 vars/getHesperidesPlatformInfo.groovy --app CSC --platform USN1
Look for strings like "downloading https://jcenter.bintray.com/com/cloudbees/groovy-cps/1.12/groovy-cps-1.12.jar".
To disable default groovy resolvers (like jcenter), you need to create a ~/.groovy/grapeConfig.xml
file based on the default one, then remove the resolver entries you don't want.
- First off, thanks to all the past contributors !
- Thanks to Github opensource.guide for their guidance on how to write this file, and also for the top image, used under the CC-BY-4.0 license.