Merge branch 'master' into fix-workflow-steps
This commit is contained in:
commit
0f77523137
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
|
|
@ -0,0 +1,52 @@
|
|||
language: java
|
||||
|
||||
env:
|
||||
global:
|
||||
- DOCKER_CACHE_DIR=$HOME/.docker-images
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
- chmod +x travis/*.sh
|
||||
|
||||
install: true
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: test
|
||||
script: ./travis/test.sh
|
||||
|
||||
|
||||
- stage: integration-test
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- GITLAB_VERSION=8.17.4
|
||||
script: ./travis/integration-test.sh
|
||||
|
||||
- stage: integration-test
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- GITLAB_VERSION=9.5.5
|
||||
script: ./travis/integration-test.sh
|
||||
|
||||
- stage: integration-test
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- GITLAB_VERSION=latest
|
||||
script: ./travis/integration-test.sh
|
||||
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $DOCKER_CACHE_DIR
|
||||
- $HOME/.m2/repository
|
||||
- $HOME/.m2/wrapper
|
||||
before_cache:
|
||||
- travis/before_cache.sh
|
44
CHANGELOG.md
44
CHANGELOG.md
|
@ -1,5 +1,49 @@
|
|||
ChangeLog
|
||||
|
||||
1.5.2
|
||||
=====================
|
||||
* #524: If Blue Ocean is installed, build URL in GitLab will point to Blue Ocean
|
||||
* #564: Build status can now be sent to GitLab from builds downstream of the one that GitLab triggered
|
||||
* #589: Make it easier to distinguish a commit push from a tag push
|
||||
* #616: Make it easier to configure gitlab-plugin from Job DSL plugin.
|
||||
* #639: Don't NPE if one of the filter specs is not specified in a Jenkinsfile
|
||||
* #658: Send current state of build to GitLab when making commit API calls so it can be seen in the GitLab UI
|
||||
* #659: Trigger builds when MR is approved in GitLab
|
||||
|
||||
1.5.1
|
||||
=====================
|
||||
* #648: Fix NPE when an MR build is triggered
|
||||
* #650: Improve GitLab API version autodetection
|
||||
* #653: Fix unsupported date format in MR trigger
|
||||
* #656: Fix 404 error when making v4 API calls for MRs
|
||||
|
||||
1.5.0
|
||||
=====================
|
||||
* #614: Add optional support for GitLab API v4
|
||||
|
||||
1.4.8
|
||||
=====================
|
||||
* #483: If 'Add message for failed builds' feature is used, send the message for both failed and 'unstable' builds
|
||||
* #514: Fix branch name comparison to avoid spurious builds, fixes issue #512
|
||||
* #540: Allow jobs to be triggered by GitLab 'Pipeline' event
|
||||
* #552: Use GitLab's host url to calculate project's ID - allows Jenkins to work with GitLab projects that are in subgroups (issue #538)
|
||||
* #567: Plugin should have secure defaults - first-time installs will now have plugin endpoint require auth by default
|
||||
* #604: Recursively retrieve all BuildData - prevents Jenkins from rebuilding when MR assignee changes (issue #603)
|
||||
|
||||
1.4.7
|
||||
=====================
|
||||
* #584: Fixes commit status exception found in issue #583
|
||||
|
||||
1.4.6
|
||||
=====================
|
||||
* #508 and #542: Trigger build when merge request has been merged or closed
|
||||
* #510: Add gitlabMergeRequestTargetProjectId to available variables in builds
|
||||
* #516: Fix: Trigger for pushes to the destination branch of open merge requests does not work in pipeline scripts
|
||||
* #532: Allow publishing a comment to the GitLab MR if the build result is 'unstable'
|
||||
* #543: Matrix/multi-configuration project support
|
||||
* #544: Add a button to clear the security token in build configuration
|
||||
* #559: Add a function to (re)set the Gitlab connections for bootstrapping new Jenkins installs
|
||||
* #562: Fix issue #523 - Build result sent to Pipeline library repo instead of project repo
|
||||
|
||||
1.4.5
|
||||
=====================
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
buildPlugin()
|
195
README.md
195
README.md
|
@ -3,25 +3,19 @@
|
|||
- [User support](#user-support)
|
||||
- [Known bugs/issues](#known-bugsissues)
|
||||
- [Supported GitLab versions](#supported-gitlab-versions)
|
||||
- [Configuring access to GitLab](#configuring-access-to-gitlab)
|
||||
- [Configuring the plugin](#configuring-the-plugin)
|
||||
- [Global configuration and authentication](#global-configuration)
|
||||
- [Jenkins Job Configuration](#jenkins-job-configuration)
|
||||
- [Gitlab Configuration (>= 8.1)](#gitlab-configuration)
|
||||
- [Branch filtering](#branch-filtering)
|
||||
- [Build Tags](#build-tags)
|
||||
- [Parameterized builds](#parameterized-builds)
|
||||
- [Contributing to the Plugin](#contributing-to-the-plugin)
|
||||
- [Quick test environment setup using Docker](#quick-test-environment-setup-using-docker)
|
||||
- [Access GitLab](#access-gitlab)
|
||||
- [Access Jenkins](#access-jenkins)
|
||||
- [Testing With Docker](#testing-with-docker)
|
||||
- [Release Workflow](#release-workflow)
|
||||
|
||||
# Introduction
|
||||
|
||||
This plugin allows GitLab to trigger builds in Jenkins after code is pushed and/or after a merge request is created and report build status back to GitLab.
|
||||
|
||||
# Seeking maintainers
|
||||
|
||||
We are seeking new maintainers for the plugin! The existing codebase is clean and well-tested thanks to a lot of hard work done by former lead maintainer [coder-hugo,](https://github.com/coder-hugo) but he is no longer using GitLab and does not have spare time to keep working on the plugin. We're looking for an active GitLab user and experienced Java programmer to take over as lead maintainer. The main work necessary at this point is resolving minor bugs and maintaining support for new versions of GitLab. If you're interested, reach out to [Owen](https://github.com/omehegan) - email address in the project's commit log.
|
||||
This plugin allows GitLab to trigger builds in Jenkins after code is pushed and/or after a merge request is created and/or after an existing merge request was merged/closed, and report build status back to GitLab.
|
||||
|
||||
# User support
|
||||
|
||||
|
@ -45,35 +39,72 @@ You can also try chatting with us in the #gitlab-plugin channel on the Freenode
|
|||
# Known bugs/issues
|
||||
|
||||
This is not an exhaustive list of issues, but rather a place for us to note significant bugs that may impact your use of the plugin in certain circumstances. For most things, please search the [Issues](https://github.com/jenkinsci/gitlab-plugin/issues) section and open a new one if you don't find anything.
|
||||
* [#272](https://github.com/jenkinsci/gitlab-plugin/issues/272) - Plugin version 1.2.0+ does not work with GitLab Enterprise Edition < 8.8.3, due to a bug on their side.
|
||||
* [#272](https://github.com/jenkinsci/gitlab-plugin/issues/272) - Plugin version 1.2.0+ does not work with GitLab Enterprise Edition < 8.8.3. Subsequent versions work fine.
|
||||
* Jenkins versions 1.651.2 and 2.3 removed the ability of plugins to set arbitrary job parameters that are not specifically defined in each job's configuration. This was an important security update, but it has broken compatibility with some plugins, including ours. See [here](https://jenkins.io/blog/2016/05/11/security-update/) for more information and workarounds if you are finding parameters unset or empty that you expect to have values.
|
||||
* [#473](https://github.com/jenkinsci/gitlab-plugin/issues/473) - When upgrading from plugin versions older than 1.2.0, you must upgrade to that version first, and then to the latest version. Otherwise, you will get a NullPointerException in com.cloudbees.plugins.credentials.matchers.IdMatcher after you upgrade. See the linked issue for specific instructions.
|
||||
* [#608](https://github.com/jenkinsci/gitlab-plugin/issues/608) - GitLab 9.5.0 - 9.5.4 has a bug that causes the "Test Webhook" function to fail when it sends a test to Jenkins. This was fixed in 9.5.5.
|
||||
|
||||
# Supported GitLab versions
|
||||
|
||||
* GitLab versions 8.1.x and newer (both CE and EE editions) are supported via the GitLab commit status API which supports with external CI services like Jenkins
|
||||
* GitLab versions 8.1.x and newer (both CE and EE editions) are supported via the GitLab [commit status API](https://docs.gitlab.com/ce/api/commits.html#commit-status) which supports with external CI services like Jenkins
|
||||
* Versions older than 8.1.x may work but are no longer officially supported
|
||||
|
||||
# Configuring access to GitLab
|
||||
# Configuring the plugin
|
||||
## Global configuration
|
||||
### GitLab-to-Jenkins authentication (required by default)
|
||||
**Disabling authentication**
|
||||
|
||||
Optionally, the plugin communicates with the GitLab server in order to fetch additional information. At this moment, this information is limited to fetching the source project of a Merge Request, in order to support merging from forked repositories.
|
||||
By default the plugin will require authentication to be set up for the connection from GitLab to Jenkins, in order to prevent unauthorized persons from being able to trigger jobs. If you want to disable this (not recommended):
|
||||
1. In Jenkins, go to Manage Jenkins -> Configure System
|
||||
2. Scroll down to the section labeled 'GitLab'
|
||||
3. Uncheck "Enable authentication for '/project' end-point" - you will now be able to trigger Jenkins jobs from GitLab without needing authentication
|
||||
|
||||
To enable this functionality, a user should be set up on GitLab, with GitLab 'Developer' permissions, to access the repository. You will need to give this user access to each repo you want Jenkins to be able to clone. Log in to GitLab as that user, go to its profile, and copy its secret API key. On the Global Configuration page in Jenkins, supply the GitLab host URL, e.g. ``http://your.gitlab.server.`` Click the 'Add' button to add a credential, choose 'GitLab API token' as the kind of credential, and paste your GitLab user's API key into the 'API token' field. Testing the connection should succeed.
|
||||
**Configuring global authentication**
|
||||
|
||||
Otherwise, to set up authentication for GitLab to trigger builds:
|
||||
1. Create a user in Jenkins which has, at a minimum, Job/Build permissions
|
||||
2. Log in as that user (this is required even if you are a Jenkins admin user), then click on the user's name in the top right corner of the page
|
||||
3. Click 'Configure,' then 'Show API Token...', and note/copy the User ID and API Token
|
||||
4. In GitLab, when you create webhooks to trigger Jenkins jobs, use this format for the URL and do not enter anything for 'Secret Token': `http://USERID:APITOKEN@JENKINS_URL/project/YOUR_JOB`
|
||||
5. After you add the webhook, click the 'Test' button, and it should succeed
|
||||
|
||||
**Configuring per-project authentication**
|
||||
|
||||
If you want to create separate authentication credentials for each Jenkins job:
|
||||
1. In the configuration of your Jenkins job, in the GitLab configuration section, click 'Advanced'
|
||||
2. Click the 'Generate' button under the 'Secret Token' field
|
||||
3. Copy the resulting token, and save the job configuration
|
||||
4. In GitLab, create a webhook for your project, enter the trigger URL (e.g. `http://JENKINS_URL/project/YOUR_JOB`) and paste the token in the Secret Token field
|
||||
5. After you add the webhook, click the 'Test' button, and it should succeed
|
||||
|
||||
### Jenkins-to-GitLab authentication (optional)
|
||||
**PLEASE NOTE:** This auth configuration is only used for accessing the GitLab API for sending build status to GitLab. It is **not** used for cloning git repos. The credentials for cloning (usually SSH credentials) should be configuring separately, in the git plugin.
|
||||
|
||||
This plugin can be configured to send build status messages to GitLab, which show up in the GitLab Merge Request UI. To enable this functionality:
|
||||
1. Create a new user in GitLab
|
||||
2. Give this user 'Developer' permissions on each repo you want Jenkins to send build status to
|
||||
3. Log in or 'Impersonate' that user in GitLab, click the user's icon/avatar and choose Settings
|
||||
4. Click on 'Access Tokens'
|
||||
5. Create a token named e.g. 'jenkins' with 'api' scope; expiration is optional
|
||||
6. Copy the token immediately, it cannot be accessed after you leave this page
|
||||
7. On the Global Configuration page in Jenkins, in the GitLab configuration section, supply the GitLab host URL, e.g. `http://your.gitlab.server`
|
||||
8. Click the 'Add' button to add a credential, choose 'GitLab API token' as the kind of credential, and paste your GitLab user's API key into the 'API token' field
|
||||
9. Click the 'Test Connection' button; it should succeed
|
||||
|
||||
## Jenkins Job Configuration
|
||||
### Git configuration for Freestyle jobs
|
||||
1. In the *Source Code Management* section:
|
||||
1. Click *Git*
|
||||
2. Enter your *Repository URL*, such as ``git@your.gitlab.server:gitlab_group/gitlab_project.git``
|
||||
* In the *Advanced* settings, set *Name* to ``origin`` and *Refspec* to
|
||||
* In the *Advanced* settings, set *Name* to ``origin`` and *Refspec* to
|
||||
``+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*``
|
||||
3. In order to merge from forked repositories: <br/>**Note:** this requires [configuring communication to the GitLab server](#configuring-access-to-gitlab)
|
||||
* Click *Add Repository* to specify the merge request source repository. Then specify:
|
||||
* *URL*: ``${gitlabSourceRepoURL}``
|
||||
* In the *Advanced* settings, set *Name* to ``${gitlabSourceRepoName}``. Leave *Refspec* blank.
|
||||
* Click *Add Repository* to specify the merge request source repository. Then specify:
|
||||
* *URL*: ``${gitlabSourceRepoURL}``
|
||||
* In the *Advanced* settings, set *Name* to ``${gitlabSourceRepoName}``. Leave *Refspec* blank.
|
||||
4. In *Branch Specifier* enter:
|
||||
* For single-repository workflows: ``origin/${gitlabSourceBranch}``
|
||||
* For forked repository workflows: ``merge-requests/${gitlabMergeRequestIid}``
|
||||
* For single-repository workflows: ``origin/${gitlabSourceBranch}``
|
||||
* For forked repository workflows: ``merge-requests/${gitlabMergeRequestIid}``
|
||||
5. In *Additional Behaviours*:
|
||||
* Click the *Add* drop-down button
|
||||
* Select *Merge before build* from the drop-down
|
||||
|
@ -88,21 +119,31 @@ To enable this functionality, a user should be set up on GitLab, with GitLab 'De
|
|||
* A Jenkins Pipeline bug will prevent the Git clone from working when you use a Pipeline script from SCM. It works if you use the Jenkins job config UI to edit the script. There is a workaround mentioned here: https://issues.jenkins-ci.org/browse/JENKINS-33719
|
||||
|
||||
* Use the Snippet generator, General SCM step, to generate sample Groovy code for the git checkout/merge etc.
|
||||
* Example that performs merge before build: `checkout changelog: true, poll: true, scm: [$class: 'GitSCM', branches: [[name: "origin/${env.gitlabSourceBranch}"]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'PreBuildMerge', options: [fastForwardMode: 'FF', mergeRemote: 'origin', mergeStrategy: 'default', mergeTarget: "${env.gitlabTargetBranch}"]]], submoduleCfg: [], userRemoteConfigs: [[name: 'origin', url: 'git@mygitlab:foo/testrepo.git']]]`
|
||||
* Example that performs merge before build:
|
||||
```
|
||||
checkout changelog: true, poll: true, scm: [
|
||||
$class: 'GitSCM',
|
||||
branches: [[name: "origin/${env.gitlabSourceBranch}"]],
|
||||
doGenerateSubmoduleConfigurations: false,
|
||||
extensions: [[$class: 'PreBuildMerge', options: [fastForwardMode: 'FF', mergeRemote: 'origin', mergeStrategy: 'default', mergeTarget: "${env.gitlabTargetBranch}"]]],
|
||||
submoduleCfg: [],
|
||||
userRemoteConfigs: [[name: 'origin', url: 'git@gitlab.example.com:foo/testrepo.git']]
|
||||
]
|
||||
```
|
||||
|
||||
### Git configuration for Multibranch Pipeline/Workflow jobs
|
||||
**Note:** none of the GitLab environment variables are available for mulitbranch pipeline jobs as there is no way to pass some additional data to a multibranch pipeline build while notifying a multibranch pipeline job about SCM changes.
|
||||
**Note:** none of the GitLab environment variables are available for multibranch pipeline jobs as there is no way to pass some additional data to a multibranch pipeline build while notifying a multibranch pipeline job about SCM changes.
|
||||
Due to this the plugin just listens for GitLab Push Hooks for multibranch pipeline jobs; Merge Request hooks are ignored.
|
||||
|
||||
1. Click **Add source**
|
||||
2. Select **Git**
|
||||
3. Enter your *Repository URL* (e.g.: ``git@your.gitlab.server:group/repo_name.git``)
|
||||
4. Unlike other job types, there is no 'Trigger' setting required for a Multibranch job configuration; just create a webhook in GitLab for push requests which points to ``http://JENKINS_URL/project/PROJECT_NAME``
|
||||
4. Unlike other job types, there is no 'Trigger' setting required for a Multibranch job configuration; just create a webhook in GitLab for push requests which points to ``http://JENKINS_URL/project/PROJECT_NAME`` or ``http://JENKINS_URL/project/FOLDER/PROJECT_NAME`` if the project in inside a folder in Jenkins.
|
||||
|
||||
Example `Jenkinsfile` for multibranch pipeline jobs
|
||||
```
|
||||
// Reference the GitLab connection name from your Jenkins Global configuration (http://JENKINS_URL/configure, GitLab section)
|
||||
properties([gitLabConnection('<your-gitlab-connection-name')])
|
||||
properties([gitLabConnection('your-gitlab-connection-name')])
|
||||
|
||||
node {
|
||||
stage "checkout"
|
||||
|
@ -125,12 +166,15 @@ node {
|
|||
* Select *Build when a change is pushed to GitLab*
|
||||
* Make a note of the *GitLab CI Service URL* appearing on the same line with *Build when a change is
|
||||
pushed to GitLab*. You will later use this URL to define a GitLab web hook.
|
||||
* Use the check boxes to trigger builds on *Push Events* and/or *Merge Request Events*
|
||||
* Use the check boxes to trigger builds on *Push Events* and/or *Created Merge Request Events* and/or *Accepted Merge Request Events* and/or *Closed Merge Request Events*
|
||||
* Optionally use *Rebuild open Merge Requests* to enable re-building open merge requests after a
|
||||
push to the source branch
|
||||
* If you selected *Rebuild open Merge Requests* other than *None*, check *Comments*, and specify the
|
||||
*Comment for triggering a build*. A new build will be triggered when this phrase appears in a
|
||||
commit comment. In addition to a literal phrase, you can also specify a Java regular expression.
|
||||
* You can use *Build on successful pipeline events* to trigger on a successful pipeline run in Gitlab. Note that
|
||||
this build trigger will only trigger a build if the commit is not already built and does not set the Gitlab status.
|
||||
Otherwise you might end up in a loop.
|
||||
2. Configure any other pre build, build or post build actions as necessary
|
||||
3. Click *Save* to preserve your changes in Jenkins.
|
||||
|
||||
|
@ -141,9 +185,16 @@ The plugin supports the new [declarative pipeline syntax](https://github.com/jen
|
|||
```
|
||||
pipeline {
|
||||
agent any
|
||||
post {
|
||||
failure {
|
||||
updateGitlabCommitStatus name: 'build', state: 'failed'
|
||||
}
|
||||
success {
|
||||
updateGitlabCommitStatus name: 'build', state: 'success'
|
||||
}
|
||||
}
|
||||
options {
|
||||
gitLabConnection('<your-gitlab-connection-name')
|
||||
gitlabCommitStatus(name: 'jenkins')
|
||||
}
|
||||
triggers {
|
||||
gitlab(triggerOnPush: true, triggerOnMergeRequest: true, branchFilterType: 'All')
|
||||
|
@ -159,12 +210,56 @@ pipeline {
|
|||
}
|
||||
```
|
||||
|
||||
If you make use of the "Merge When Pipeline Succeeds" option for Merge Requests in GitLab, and your Declarative Pipeline jobs have more than one stage, you will need to define those stages in an `options` block. Otherwise, when and if the first stage passes, GitLab will merge the change. For example, if you have three stages named build, test, and deploy:
|
||||
|
||||
```
|
||||
options {
|
||||
gitLabConnection('<your-gitlab-connection-name')
|
||||
gitlabBuilds(builds: ['build', 'test', 'deploy'])
|
||||
}
|
||||
```
|
||||
|
||||
If you want to configure any of the optional job triggers that the plugin supports in a Declarative build, use a `triggers` block. The full list of configurable trigger options is as follows:
|
||||
|
||||
```
|
||||
triggers {
|
||||
gitlab(
|
||||
triggerOnPush: false,
|
||||
triggerOnMergeRequest: true, triggerOpenMergeRequestOnPush: "never",
|
||||
triggerOnNoteRequest: true,
|
||||
noteRegex: "Jenkins please retry a build",
|
||||
skipWorkInProgressMergeRequest: true,
|
||||
ciSkip: false,
|
||||
setBuildDescription: true,
|
||||
addNoteOnMergeRequest: true,
|
||||
addCiMessage: true,
|
||||
addVoteOnMergeRequest: true,
|
||||
acceptMergeRequestOnSuccess: false,
|
||||
branchFilterType: "NameBasedFilter",
|
||||
includeBranchesSpec: "release/qat",
|
||||
excludeBranchesSpec: "",
|
||||
secretToken: "abcdefghijklmnopqrstuvwxyz0123456789ABCDEF")
|
||||
}
|
||||
```
|
||||
|
||||
### Matrix/Multi-configuration jobs
|
||||
**The Jenkins Matrix/Multi-configuration job type is not supported.**
|
||||
|
||||
This plugin can be used on Matrix/Multi-configuration jobs together with the [Flexible Publish](https://plugins.jenkins.io/flexible-publish) plugin which allows to run publishers after all axis jobs are done.
|
||||
|
||||
To use GitLab with Flexible Publish, configure the *Post-build Actions* as follows:
|
||||
|
||||
1. Add a *Flexible publish* action
|
||||
2. In the *Flexible publish* section:
|
||||
1. *Add conditional action*
|
||||
2. In the *Conditional action* section:
|
||||
1. Set *Run?* to *Never*
|
||||
2. Select *Condition for Matrix Aggregation*
|
||||
3. Set *Run on Parent?* to *Always*
|
||||
4. Add GitLab actions as required
|
||||
|
||||
## Gitlab Configuration
|
||||
|
||||
GitLab 8.1 has implemented a commit status api, you need an extra post-build step to support commit status.
|
||||
GitLab 8.1 has implemented a commit status API, you need an extra post-build step to support commit status.
|
||||
|
||||
* In GitLab go to your repository's project *Settings*
|
||||
* Click on *Web Hooks*
|
||||
|
@ -235,13 +330,13 @@ In order to build when a new tag is pushed:
|
|||
* In the ``GitLab server`` add ``Tag push events`` to the ``Web Hook``
|
||||
* In the ``Jenkins`` under the ``Source Code Management`` section:
|
||||
* select ``Advance...`` and add ``+refs/tags/*:refs/remotes/origin/tags/*`` as ``Refspec``
|
||||
* you can also use ``Branch Specifier`` to specify which tag need to be built (exampple ``refs/tags/${TAGNAME}``)
|
||||
* you can also use ``Branch Specifier`` to specify which tag need to be built (example ``refs/tags/${TAGNAME}``)
|
||||
|
||||
# Send message on complete of a build
|
||||
|
||||
1. In the *Post build steps* section:
|
||||
1. Click *Add post build step*
|
||||
2. Click *Add note with build status on GitLab merge requests* and save build settings (You enabled autoumatically sending default message on result of a build)
|
||||
2. Click *Add note with build status on GitLab merge requests* and save build settings (You enabled automatically sending default message on result of a build)
|
||||
|
||||
2. If you want make custom message on result of a build:
|
||||
1. In *Add note with build status on GitLab merge requests* section click to *Custom message on success/failure/abort*
|
||||
|
@ -267,7 +362,11 @@ These include:
|
|||
* gitlabMergeRequestDescription
|
||||
* gitlabMergeRequestId
|
||||
* gitlabMergeRequestIid
|
||||
* gitlabMergeRequestState
|
||||
* gitlabMergedByUser
|
||||
* gitlabMergeRequestAssignee
|
||||
* gitlabMergeRequestLastCommit
|
||||
* gitlabMergeRequestTargetProjectId
|
||||
* gitlabTargetBranch
|
||||
* gitlabTargetRepoName
|
||||
* gitlabTargetNamespace
|
||||
|
@ -298,38 +397,10 @@ Before submitting your change make sure that:
|
|||
* you updated the README
|
||||
* you have used findbugs to see if you haven't introduced any new warnings.
|
||||
|
||||
# Quick test environment setup using Docker
|
||||
# Testing With Docker
|
||||
|
||||
In order to test the plugin on different versions of `GitLab` and `Jenkins` you may want to use `Docker` containers.
|
||||
|
||||
A example docker-compose file is available at `gitlab-plugin/src/docker` which allows to set up instances of the latest `GitLab` and `Jenkins` versions.
|
||||
|
||||
To start the containers, run below command from the `docker` folder:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Access GitLab
|
||||
|
||||
To access `GitLab`, point your browser to `http://172.17.0.1:10080` and set a password for the `root` user account.
|
||||
|
||||
For more information on the supported `GitLab` versions and how to configure the containers, visit Sameer Naik's github page at https://github.com/sameersbn/docker-gitlab.
|
||||
|
||||
## Access Jenkins
|
||||
|
||||
To see `Jenkins`, point your browser to `http://localhost:8080`.
|
||||
|
||||
For more information on the supported `Jenkins` tags and how to configure the containers, visit https://hub.docker.com/r/library/jenkins.
|
||||
See https://github.com/jenkinsci/gitlab-plugin/tree/master/src/docker/README.md
|
||||
|
||||
# Release Workflow
|
||||
|
||||
GitLab-Plugin admins should adhere to the following rules when releasing a new plugin version:
|
||||
|
||||
* Ensure codestyle conformity
|
||||
* Run unit tests
|
||||
* Run manual tests on both, oldest and latest GitLab versions
|
||||
* Update documentation
|
||||
* Create change log
|
||||
* Create release tag
|
||||
* Create release notes (on github)
|
||||
To perform a full plugin release, maintainers can run ``mvn release:prepare release:perform`` To release a snapshot, e.g. with a bug fix for users to test, just run ``mvn deploy``
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
#
|
||||
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
|
||||
# for the new JDKs provided by Oracle.
|
||||
#
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
|
||||
#
|
||||
# Oracle JDKs
|
||||
#
|
||||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=`/usr/libexec/java_home`
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Migwn, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
local basedir=$(pwd)
|
||||
local wdir=$(pwd)
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
wdir=$(cd "$wdir/.."; pwd)
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
# avoid using MAVEN_CMD_LINE_ARGS below since that would loose parameter escaping in $@
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
@ -0,0 +1,146 @@
|
|||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%MAVEN_CONFIG% %*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR=""%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar""
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
@REM avoid using MAVEN_CMD_LINE_ARGS below since that would loose parameter escaping in %*
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
55
pom.xml
55
pom.xml
|
@ -14,7 +14,7 @@
|
|||
</properties>
|
||||
|
||||
<artifactId>gitlab-plugin</artifactId>
|
||||
<version>1.4.5</version>
|
||||
<version>1.5.3-SNAPSHOT</version>
|
||||
<name>GitLab Plugin</name>
|
||||
<url>https://wiki.jenkins-ci.org/display/JENKINS/GitLab+Plugin</url>
|
||||
<packaging>hpi</packaging>
|
||||
|
@ -27,20 +27,15 @@
|
|||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>coderhugo</id>
|
||||
<name>Robin Müller</name>
|
||||
<email>coderhugo@googlemail.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>owenmehegan</id>
|
||||
<name>Owen Mehegan</name>
|
||||
<email>owen@nerdnetworks.org</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>omorillo</id>
|
||||
<name>Oscar Salvador Morillo Victoria</name>
|
||||
<email>omorillovictoria@googlemail.com</email>
|
||||
<id>milena</id>
|
||||
<name>Milena Reichel</name>
|
||||
<email>milena.reichel@gmail.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
|
@ -61,7 +56,7 @@
|
|||
<connection>scm:git:ssh://github.com:jenkinsci/gitlab-plugin.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:jenkinsci/gitlab-plugin.git</developerConnection>
|
||||
<url>https://github.com/jenkinsci/gitlab-plugin</url>
|
||||
<tag>gitlab-plugin-1.4.5</tag>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
<!-- get every artifact through repo.jenkins-ci.org, which proxies all the artifacts that we need -->
|
||||
<repositories>
|
||||
|
@ -84,6 +79,7 @@
|
|||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean install</defaultGoal>
|
||||
<directory>${project.basedir}/target</directory>
|
||||
<outputDirectory>${project.build.directory}/classes</outputDirectory>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
|
@ -192,6 +188,17 @@
|
|||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>3.5.2.201411120430-r</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jenkins-ci.plugins</groupId>
|
||||
<artifactId>matrix-project</artifactId>
|
||||
<version>1.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jenkins-ci.plugins</groupId>
|
||||
<artifactId>display-url-api</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- REST client dependencies -->
|
||||
<dependency>
|
||||
|
@ -252,6 +259,18 @@
|
|||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-netty</artifactId>
|
||||
|
@ -288,7 +307,8 @@
|
|||
<profile>
|
||||
<id>integration-test</id>
|
||||
<properties>
|
||||
<gitlab.version>8.5.8</gitlab.version>
|
||||
<gitlab.version>8.17.4</gitlab.version>
|
||||
<postgres.version>9.5-1</postgres.version>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -359,7 +379,7 @@
|
|||
<verbose>true</verbose>
|
||||
<images>
|
||||
<image>
|
||||
<name>sameersbn/postgresql:9.4-15</name>
|
||||
<name>sameersbn/postgresql:${postgres.version}</name>
|
||||
<alias>it-gitlab-postgres</alias>
|
||||
<run>
|
||||
<namingStrategy>alias</namingStrategy>
|
||||
|
@ -367,6 +387,7 @@
|
|||
<DB_NAME>gitlabhq_production</DB_NAME>
|
||||
<DB_USER>gitlab</DB_USER>
|
||||
<DB_PASS>password</DB_PASS>
|
||||
<DB_EXTENSION>pg_trgm</DB_EXTENSION>
|
||||
</env>
|
||||
<ports>
|
||||
<port>${postgres.port}:5432</port>
|
||||
|
@ -382,7 +403,9 @@
|
|||
</image>
|
||||
<image>
|
||||
<name>sameersbn/gitlab:${gitlab.version}</name>
|
||||
<alias>it-gitlab-gitlab</alias>
|
||||
<run>
|
||||
<namingStrategy>alias</namingStrategy>
|
||||
<links>
|
||||
<link>it-gitlab-postgres:postgresql</link>
|
||||
<link>it-gitlab-redis:redisio</link>
|
||||
|
@ -392,9 +415,15 @@
|
|||
<port>${gitlab.ssh.port}:22</port>
|
||||
</ports>
|
||||
<env>
|
||||
<DEBUG>false</DEBUG>
|
||||
<TZ>Asia/Kolkata</TZ>
|
||||
<GITLAB_TIMEZONE>Kolkata</GITLAB_TIMEZONE>
|
||||
<GITLAB_PORT>${gitlab.http.port}</GITLAB_PORT>
|
||||
<GITLAB_SSH_PORT>${gitlab.ssh.port}</GITLAB_SSH_PORT>
|
||||
<GITLAB_SECRETS_DB_KEY_BASE>abc123</GITLAB_SECRETS_DB_KEY_BASE>
|
||||
<GITLAB_SECRETS_DB_KEY_BASE>long-and-random-alpha-numeric-string</GITLAB_SECRETS_DB_KEY_BASE>
|
||||
<GITLAB_SECRETS_SECRET_KEY_BASE>long-and-random-alphanumeric-string</GITLAB_SECRETS_SECRET_KEY_BASE>
|
||||
<GITLAB_SECRETS_OTP_KEY_BASE>long-and-random-alpha-numeric-string</GITLAB_SECRETS_OTP_KEY_BASE>
|
||||
<GITLAB_HOST>172.17.0.1</GITLAB_HOST>
|
||||
</env>
|
||||
<wait>
|
||||
<http>
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Quick test environment setup using Docker
|
||||
|
||||
In order to test the plugin on different versions of `GitLab` and `Jenkins` you may want to use `Docker` containers.
|
||||
|
||||
A example docker-compose file is available at `gitlab-plugin/src/docker` which allows to set up instances of the latest `GitLab` and `Jenkins` versions.
|
||||
|
||||
If they don't already exist, create the following directories and make sure the user that Docker is running as owns them:
|
||||
* /srv/docker/gitlab/postgresql
|
||||
* /srv/docker/gitlab/gitlab
|
||||
* /srv/docker/gitlab/redis
|
||||
* /srv/docker/jenkins
|
||||
|
||||
To start the containers, run `docker-compose up -d` from the `docker` folder. If you have problems accessing the services in the containers, run `docker-compose up` by itself to see output from the services as they start.
|
||||
|
||||
## Access GitLab
|
||||
|
||||
To access `GitLab`, point your browser to `http://localhost:10080` and set a password for the `root` user account. Then create a user for Jenkins, impersonate that user, get its API key, set up test repos, etc. When creating webhooks to trigger Jenkins jobs, use `http://jenkins:8080` as the base URL.
|
||||
|
||||
For more information on the supported `GitLab` versions and how to configure the containers, visit Sameer Naik's github page at https://github.com/sameersbn/docker-gitlab.
|
||||
|
||||
## Access Jenkins
|
||||
|
||||
To see `Jenkins`, point your browser to `http://localhost:8080`. Jenkins will be able to access GitLab at `http://gitlab`
|
||||
|
||||
For more information on the supported `Jenkins` tags and how to configure the containers, visit https://hub.docker.com/r/jenkins/jenkins/.
|
||||
|
|
@ -1,78 +1,98 @@
|
|||
postgresql:
|
||||
container_name: docker-postgresql
|
||||
restart: always
|
||||
image: sameersbn/postgresql:9.5-1
|
||||
environment:
|
||||
- DB_USER=gitlab
|
||||
- DB_PASS=password
|
||||
- DB_NAME=gitlabhq_production
|
||||
- DB_EXTENSION=pg_trgm
|
||||
volumes:
|
||||
- /srv/docker/gitlab/postgresql:/var/lib/postgresql
|
||||
gitlab:
|
||||
container_name: docker-gitlab
|
||||
restart: always
|
||||
image: sameersbn/gitlab:8.11.5
|
||||
links:
|
||||
- redis:redisio
|
||||
- postgresql:postgresql
|
||||
ports:
|
||||
- "10080:80"
|
||||
- "10022:22"
|
||||
environment:
|
||||
- DEBUG=false
|
||||
- TZ=Asia/Kolkata
|
||||
- GITLAB_TIMEZONE=Kolkata
|
||||
version: '2'
|
||||
|
||||
- GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string
|
||||
- GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string
|
||||
- GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alpha-numeric-string
|
||||
services:
|
||||
postgresql:
|
||||
restart: always
|
||||
image: sameersbn/postgresql:9.5-1
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
- DB_USER=gitlab
|
||||
- DB_PASS=password
|
||||
- DB_NAME=gitlabhq_production
|
||||
- DB_EXTENSION=pg_trgm
|
||||
volumes:
|
||||
- /srv/docker/gitlab/postgresql:/var/lib/postgresql
|
||||
|
||||
- GITLAB_HOST=172.17.0.1
|
||||
- GITLAB_PORT=10080
|
||||
- GITLAB_SSH_PORT=10022
|
||||
- GITLAB_RELATIVE_URL_ROOT=
|
||||
gitlab:
|
||||
restart: always
|
||||
image: sameersbn/gitlab:9.4.1
|
||||
depends_on:
|
||||
- redis
|
||||
- postgresql
|
||||
ports:
|
||||
- "10080:80"
|
||||
- "10022:22"
|
||||
environment:
|
||||
- DEBUG=false
|
||||
|
||||
- GITLAB_NOTIFY_ON_BROKEN_BUILDS=true
|
||||
- GITLAB_NOTIFY_PUSHER=false
|
||||
- DB_ADAPTER=postgresql
|
||||
- DB_HOST=postgresql
|
||||
- DB_PORT=5432
|
||||
- DB_USER=gitlab
|
||||
- DB_PASS=password
|
||||
- DB_NAME=gitlabhq_production
|
||||
|
||||
- GITLAB_EMAIL=notifications@example.com
|
||||
- GITLAB_EMAIL_REPLY_TO=noreply@example.com
|
||||
- GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
|
||||
- GITLAB_BACKUP_SCHEDULE=daily
|
||||
- GITLAB_BACKUP_TIME=01:00
|
||||
- TZ=Asia/Kolkata
|
||||
- GITLAB_TIMEZONE=Kolkata
|
||||
|
||||
- SMTP_ENABLED=false
|
||||
- SMTP_DOMAIN=www.example.com
|
||||
- SMTP_HOST=smtp.gmail.com
|
||||
- SMTP_PORT=587
|
||||
- SMTP_USER=mailer@example.com
|
||||
- SMTP_PASS=password
|
||||
- SMTP_STARTTLS=true
|
||||
- SMTP_AUTHENTICATION=login
|
||||
- GITLAB_HTTPS=false
|
||||
- SSL_SELF_SIGNED=false
|
||||
|
||||
- IMAP_ENABLED=false
|
||||
- IMAP_HOST=imap.gmail.com
|
||||
- IMAP_PORT=993
|
||||
- IMAP_USER=mailer@example.com
|
||||
- IMAP_PASS=password
|
||||
- IMAP_SSL=true
|
||||
- IMAP_STARTTLS=false
|
||||
volumes:
|
||||
- /srv/docker/gitlab/gitlab:/home/git/data
|
||||
redis:
|
||||
container_name: docker-redis
|
||||
restart: always
|
||||
image: sameersbn/redis:latest
|
||||
volumes:
|
||||
- /srv/docker/gitlab/redis:/var/lib/redis
|
||||
jenkins:
|
||||
container_name: docker-jenkins
|
||||
restart: always
|
||||
image: jenkins:2.7.3
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "50000:50000"
|
||||
volumes:
|
||||
- /srv/docker/jenkins:/var/jenkins_home
|
||||
- GITLAB_HOST=localhost
|
||||
- GITLAB_PORT=10080
|
||||
- GITLAB_SSH_PORT=10022
|
||||
- GITLAB_RELATIVE_URL_ROOT=
|
||||
- GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string
|
||||
- GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string
|
||||
- GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alpha-numeric-string
|
||||
|
||||
- GITLAB_ROOT_PASSWORD=
|
||||
- GITLAB_ROOT_EMAIL=
|
||||
|
||||
- GITLAB_NOTIFY_ON_BROKEN_BUILDS=true
|
||||
- GITLAB_NOTIFY_PUSHER=false
|
||||
|
||||
- GITLAB_EMAIL=notifications@example.com
|
||||
- GITLAB_EMAIL_REPLY_TO=noreply@example.com
|
||||
- GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com
|
||||
|
||||
- GITLAB_BACKUP_SCHEDULE=daily
|
||||
- GITLAB_BACKUP_TIME=01:00
|
||||
|
||||
- SMTP_ENABLED=false
|
||||
- SMTP_DOMAIN=www.example.com
|
||||
- SMTP_HOST=smtp.gmail.com
|
||||
- SMTP_PORT=587
|
||||
- SMTP_USER=mailer@example.com
|
||||
- SMTP_PASS=password
|
||||
- SMTP_STARTTLS=true
|
||||
- SMTP_AUTHENTICATION=login
|
||||
|
||||
- IMAP_ENABLED=false
|
||||
- IMAP_HOST=imap.gmail.com
|
||||
- IMAP_PORT=993
|
||||
- IMAP_USER=mailer@example.com
|
||||
- IMAP_PASS=password
|
||||
- IMAP_SSL=true
|
||||
- IMAP_STARTTLS=false
|
||||
volumes:
|
||||
- /srv/docker/gitlab/gitlab:/home/git/data
|
||||
|
||||
redis:
|
||||
restart: always
|
||||
image: sameersbn/redis:latest
|
||||
volumes:
|
||||
- /srv/docker/gitlab/redis:/var/lib/redis
|
||||
|
||||
jenkins:
|
||||
restart: always
|
||||
image: jenkins/jenkins:lts
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "50000:50000"
|
||||
volumes:
|
||||
- /srv/docker/jenkins:/var/jenkins_home
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package com.dabsquared.gitlabjenkins;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionConfig;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.MergeRequestHook;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.NoteHook;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PipelineHook;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PushHook;
|
||||
import com.dabsquared.gitlabjenkins.publisher.GitLabAcceptMergeRequestPublisher;
|
||||
import com.dabsquared.gitlabjenkins.publisher.GitLabCommitStatusPublisher;
|
||||
|
@ -20,6 +22,7 @@ import com.dabsquared.gitlabjenkins.trigger.filter.MergeRequestLabelFilterConfig
|
|||
import com.dabsquared.gitlabjenkins.trigger.filter.MergeRequestLabelFilterFactory;
|
||||
import com.dabsquared.gitlabjenkins.trigger.handler.merge.MergeRequestHookTriggerHandler;
|
||||
import com.dabsquared.gitlabjenkins.trigger.handler.note.NoteHookTriggerHandler;
|
||||
import com.dabsquared.gitlabjenkins.trigger.handler.pipeline.PipelineHookTriggerHandler;
|
||||
import com.dabsquared.gitlabjenkins.trigger.handler.push.PushHookTriggerHandler;
|
||||
import com.dabsquared.gitlabjenkins.trigger.label.ProjectLabelsProvider;
|
||||
import com.dabsquared.gitlabjenkins.webhook.GitLabWebHook;
|
||||
|
@ -48,6 +51,7 @@ import org.jenkinsci.Symbol;
|
|||
import org.kohsuke.stapler.Ancestor;
|
||||
import org.kohsuke.stapler.AncestorInPath;
|
||||
import org.kohsuke.stapler.DataBoundConstructor;
|
||||
import org.kohsuke.stapler.DataBoundSetter;
|
||||
import org.kohsuke.stapler.QueryParameter;
|
||||
import org.kohsuke.stapler.Stapler;
|
||||
import org.kohsuke.stapler.StaplerRequest;
|
||||
|
@ -60,6 +64,7 @@ import java.security.SecureRandom;
|
|||
import static com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterConfig.BranchFilterConfigBuilder.branchFilterConfig;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.handler.merge.MergeRequestHookTriggerHandlerFactory.newMergeRequestHookTriggerHandler;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.handler.note.NoteHookTriggerHandlerFactory.newNoteHookTriggerHandler;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.handler.pipeline.PipelineHookTriggerHandlerFactory.newPipelineHookTriggerHandler;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.handler.push.PushHookTriggerHandlerFactory.newPushHookTriggerHandler;
|
||||
|
||||
|
||||
|
@ -74,9 +79,13 @@ public class GitLabPushTrigger extends Trigger<Job<?, ?>> {
|
|||
|
||||
private boolean triggerOnPush = true;
|
||||
private boolean triggerOnMergeRequest = true;
|
||||
private final TriggerOpenMergeRequest triggerOpenMergeRequestOnPush;
|
||||
private boolean triggerOnPipelineEvent = false;
|
||||
private boolean triggerOnAcceptedMergeRequest = false;
|
||||
private boolean triggerOnClosedMergeRequest = false;
|
||||
private boolean triggerOnApprovedMergeRequest = false;
|
||||
private TriggerOpenMergeRequest triggerOpenMergeRequestOnPush;
|
||||
private boolean triggerOnNoteRequest = true;
|
||||
private final String noteRegex;
|
||||
private String noteRegex = "";
|
||||
private boolean ciSkip = true;
|
||||
private boolean skipWorkInProgressMergeRequest;
|
||||
private boolean setBuildDescription = true;
|
||||
|
@ -89,30 +98,38 @@ public class GitLabPushTrigger extends Trigger<Job<?, ?>> {
|
|||
private String includeBranchesSpec;
|
||||
private String excludeBranchesSpec;
|
||||
private String targetBranchRegex;
|
||||
private final MergeRequestLabelFilterConfig mergeRequestLabelFilterConfig;
|
||||
private MergeRequestLabelFilterConfig mergeRequestLabelFilterConfig;
|
||||
private volatile Secret secretToken;
|
||||
|
||||
private transient BranchFilter branchFilter;
|
||||
private transient PushHookTriggerHandler pushHookTriggerHandler;
|
||||
private transient MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler;
|
||||
private transient NoteHookTriggerHandler noteHookTriggerHandler;
|
||||
private transient PipelineHookTriggerHandler pipelineTriggerHandler;
|
||||
private transient boolean acceptMergeRequestOnSuccess;
|
||||
private transient MergeRequestLabelFilter mergeRequestLabelFilter;
|
||||
|
||||
|
||||
@DataBoundConstructor
|
||||
/**
|
||||
* @deprecated use {@link #GitLabPushTrigger()} with setters to configure an instance of this class.
|
||||
*/
|
||||
@Deprecated
|
||||
@GeneratePojoBuilder(intoPackage = "*.builder.generated", withFactoryMethod = "*")
|
||||
public GitLabPushTrigger(boolean triggerOnPush, boolean triggerOnMergeRequest, TriggerOpenMergeRequest triggerOpenMergeRequestOnPush,
|
||||
boolean triggerOnNoteRequest, String noteRegex, boolean skipWorkInProgressMergeRequest, boolean ciSkip,
|
||||
public GitLabPushTrigger(boolean triggerOnPush, boolean triggerOnMergeRequest, boolean triggerOnAcceptedMergeRequest, boolean triggerOnClosedMergeRequest,
|
||||
TriggerOpenMergeRequest triggerOpenMergeRequestOnPush, boolean triggerOnNoteRequest, String noteRegex,
|
||||
boolean skipWorkInProgressMergeRequest, boolean ciSkip,
|
||||
boolean setBuildDescription, boolean addNoteOnMergeRequest, boolean addCiMessage, boolean addVoteOnMergeRequest,
|
||||
boolean acceptMergeRequestOnSuccess, BranchFilterType branchFilterType,
|
||||
String includeBranchesSpec, String excludeBranchesSpec, String targetBranchRegex,
|
||||
MergeRequestLabelFilterConfig mergeRequestLabelFilterConfig, String secretToken) {
|
||||
MergeRequestLabelFilterConfig mergeRequestLabelFilterConfig, String secretToken, boolean triggerOnPipelineEvent,
|
||||
boolean triggerOnApprovedMergeRequest) {
|
||||
this.triggerOnPush = triggerOnPush;
|
||||
this.triggerOnMergeRequest = triggerOnMergeRequest;
|
||||
this.triggerOnAcceptedMergeRequest = triggerOnAcceptedMergeRequest;
|
||||
this.triggerOnClosedMergeRequest = triggerOnClosedMergeRequest;
|
||||
this.triggerOnNoteRequest = triggerOnNoteRequest;
|
||||
this.noteRegex = noteRegex;
|
||||
this.triggerOpenMergeRequestOnPush = triggerOpenMergeRequestOnPush;
|
||||
this.triggerOnPipelineEvent = triggerOnPipelineEvent;
|
||||
this.ciSkip = ciSkip;
|
||||
this.skipWorkInProgressMergeRequest = skipWorkInProgressMergeRequest;
|
||||
this.setBuildDescription = setBuildDescription;
|
||||
|
@ -126,20 +143,26 @@ public class GitLabPushTrigger extends Trigger<Job<?, ?>> {
|
|||
this.acceptMergeRequestOnSuccess = acceptMergeRequestOnSuccess;
|
||||
this.mergeRequestLabelFilterConfig = mergeRequestLabelFilterConfig;
|
||||
this.secretToken = Secret.fromString(secretToken);
|
||||
this.triggerOnApprovedMergeRequest = triggerOnApprovedMergeRequest;
|
||||
|
||||
initializeTriggerHandler();
|
||||
initializeBranchFilter();
|
||||
initializeMergeRequestLabelFilter();
|
||||
}
|
||||
|
||||
@DataBoundConstructor
|
||||
public GitLabPushTrigger() { }
|
||||
|
||||
@Initializer(after = InitMilestone.JOB_LOADED)
|
||||
public static void migrateJobs() throws IOException {
|
||||
GitLabPushTrigger.DescriptorImpl oldConfig = Trigger.all().get(GitLabPushTrigger.DescriptorImpl.class);
|
||||
if (!oldConfig.jobsMigrated) {
|
||||
GitLabConnectionConfig gitLabConfig = (GitLabConnectionConfig) Jenkins.getInstance().getDescriptor(GitLabConnectionConfig.class);
|
||||
gitLabConfig.getConnections().add(new GitLabConnection(oldConfig.gitlabHostUrl,
|
||||
gitLabConfig.getConnections().add(new GitLabConnection(
|
||||
oldConfig.gitlabHostUrl,
|
||||
oldConfig.gitlabHostUrl,
|
||||
oldConfig.gitlabApiToken,
|
||||
"autodetect",
|
||||
oldConfig.ignoreCertificateErrors,
|
||||
10,
|
||||
10));
|
||||
|
@ -188,10 +211,20 @@ public class GitLabPushTrigger extends Trigger<Job<?, ?>> {
|
|||
return triggerOnMergeRequest;
|
||||
}
|
||||
|
||||
public boolean isTriggerOnAcceptedMergeRequest() {
|
||||
return triggerOnAcceptedMergeRequest;
|
||||
}
|
||||
|
||||
public boolean isTriggerOnClosedMergeRequest() {
|
||||
return triggerOnClosedMergeRequest;
|
||||
}
|
||||
|
||||
public boolean getTriggerOnNoteRequest() {
|
||||
return triggerOnNoteRequest;
|
||||
}
|
||||
|
||||
public boolean getTriggerOnPipelineEvent() { return triggerOnPipelineEvent; }
|
||||
|
||||
public String getNoteRegex() {
|
||||
return this.noteRegex == null ? "" : this.noteRegex;
|
||||
}
|
||||
|
@ -236,25 +269,170 @@ public class GitLabPushTrigger extends Trigger<Job<?, ?>> {
|
|||
return secretToken == null ? null : secretToken.getPlainText();
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTriggerOnPush(boolean triggerOnPush) {
|
||||
this.triggerOnPush = triggerOnPush;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTriggerOnApprovedMergeRequest(boolean triggerOnApprovedMergeRequest) {
|
||||
this.triggerOnApprovedMergeRequest = triggerOnApprovedMergeRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTriggerOnMergeRequest(boolean triggerOnMergeRequest) {
|
||||
this.triggerOnMergeRequest = triggerOnMergeRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTriggerOnAcceptedMergeRequest(boolean triggerOnAcceptedMergeRequest) {
|
||||
this.triggerOnAcceptedMergeRequest = triggerOnAcceptedMergeRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTriggerOnClosedMergeRequest(boolean triggerOnClosedMergeRequest) {
|
||||
this.triggerOnClosedMergeRequest = triggerOnClosedMergeRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTriggerOpenMergeRequestOnPush(TriggerOpenMergeRequest triggerOpenMergeRequestOnPush) {
|
||||
this.triggerOpenMergeRequestOnPush = triggerOpenMergeRequestOnPush;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTriggerOnNoteRequest(boolean triggerOnNoteRequest) {
|
||||
this.triggerOnNoteRequest = triggerOnNoteRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setNoteRegex(String noteRegex) {
|
||||
this.noteRegex = noteRegex;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setCiSkip(boolean ciSkip) {
|
||||
this.ciSkip = ciSkip;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setSkipWorkInProgressMergeRequest(boolean skipWorkInProgressMergeRequest) {
|
||||
this.skipWorkInProgressMergeRequest = skipWorkInProgressMergeRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setSetBuildDescription(boolean setBuildDescription) {
|
||||
this.setBuildDescription = setBuildDescription;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setAddNoteOnMergeRequest(boolean addNoteOnMergeRequest) {
|
||||
this.addNoteOnMergeRequest = addNoteOnMergeRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setAddCiMessage(boolean addCiMessage) {
|
||||
this.addCiMessage = addCiMessage;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setAddVoteOnMergeRequest(boolean addVoteOnMergeRequest) {
|
||||
this.addVoteOnMergeRequest = addVoteOnMergeRequest;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setBranchFilterName(String branchFilterName) {
|
||||
this.branchFilterName = branchFilterName;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setBranchFilterType(BranchFilterType branchFilterType) {
|
||||
this.branchFilterType = branchFilterType;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setIncludeBranchesSpec(String includeBranchesSpec) {
|
||||
this.includeBranchesSpec = includeBranchesSpec;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setExcludeBranchesSpec(String excludeBranchesSpec) {
|
||||
this.excludeBranchesSpec = excludeBranchesSpec;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setTargetBranchRegex(String targetBranchRegex) {
|
||||
this.targetBranchRegex = targetBranchRegex;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setMergeRequestLabelFilterConfig(MergeRequestLabelFilterConfig mergeRequestLabelFilterConfig) {
|
||||
this.mergeRequestLabelFilterConfig = mergeRequestLabelFilterConfig;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setSecretToken(String secretToken) {
|
||||
this.secretToken = Secret.fromString(secretToken);
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setAcceptMergeRequestOnSuccess(boolean acceptMergeRequestOnSuccess) {
|
||||
this.acceptMergeRequestOnSuccess = acceptMergeRequestOnSuccess;
|
||||
}
|
||||
|
||||
// executes when the Trigger receives a push request
|
||||
public void onPost(final PushHook hook) {
|
||||
if (branchFilter == null) {
|
||||
initializeBranchFilter();
|
||||
}
|
||||
if (mergeRequestLabelFilter == null) {
|
||||
initializeMergeRequestLabelFilter();
|
||||
}
|
||||
if (pushHookTriggerHandler == null) {
|
||||
initializeTriggerHandler();
|
||||
}
|
||||
pushHookTriggerHandler.handle(job, hook, ciSkip, branchFilter, mergeRequestLabelFilter);
|
||||
}
|
||||
|
||||
// executes when the Trigger receives a merge request
|
||||
public void onPost(final MergeRequestHook hook) {
|
||||
if (branchFilter == null) {
|
||||
initializeBranchFilter();
|
||||
}
|
||||
if (mergeRequestLabelFilter == null) {
|
||||
initializeMergeRequestLabelFilter();
|
||||
}
|
||||
if (mergeRequestHookTriggerHandler == null) {
|
||||
initializeTriggerHandler();
|
||||
}
|
||||
mergeRequestHookTriggerHandler.handle(job, hook, ciSkip, branchFilter, mergeRequestLabelFilter);
|
||||
}
|
||||
|
||||
// executes when the Trigger receives a note request
|
||||
public void onPost(final NoteHook hook) {
|
||||
if (branchFilter == null) {
|
||||
initializeBranchFilter();
|
||||
}
|
||||
if (mergeRequestLabelFilter == null) {
|
||||
initializeMergeRequestLabelFilter();
|
||||
}
|
||||
if (noteHookTriggerHandler == null) {
|
||||
initializeTriggerHandler();
|
||||
}
|
||||
noteHookTriggerHandler.handle(job, hook, ciSkip, branchFilter, mergeRequestLabelFilter);
|
||||
}
|
||||
|
||||
// executes when the Trigger receives a pipeline event
|
||||
public void onPost(final PipelineHook hook) {
|
||||
pipelineTriggerHandler.handle(job, hook, ciSkip, branchFilter, mergeRequestLabelFilter);
|
||||
}
|
||||
|
||||
private void initializeTriggerHandler() {
|
||||
mergeRequestHookTriggerHandler = newMergeRequestHookTriggerHandler(triggerOnMergeRequest, triggerOpenMergeRequestOnPush, skipWorkInProgressMergeRequest);
|
||||
mergeRequestHookTriggerHandler = newMergeRequestHookTriggerHandler(triggerOnMergeRequest,
|
||||
triggerOnAcceptedMergeRequest, triggerOnClosedMergeRequest, triggerOpenMergeRequestOnPush,
|
||||
skipWorkInProgressMergeRequest, triggerOnApprovedMergeRequest);
|
||||
noteHookTriggerHandler = newNoteHookTriggerHandler(triggerOnNoteRequest, noteRegex);
|
||||
pushHookTriggerHandler = newPushHookTriggerHandler(triggerOnPush, triggerOpenMergeRequestOnPush, skipWorkInProgressMergeRequest);
|
||||
pipelineTriggerHandler = newPipelineHookTriggerHandler(triggerOnPipelineEvent);
|
||||
}
|
||||
|
||||
private void initializeBranchFilter() {
|
||||
|
@ -404,5 +582,9 @@ public class GitLabPushTrigger extends Trigger<Job<?, ?>> {
|
|||
String secretToken = Util.toHexString(random);
|
||||
response.setHeader("script", "document.getElementById('secretToken').value='" + secretToken + "'");
|
||||
}
|
||||
|
||||
public void doClearSecretToken(@AncestorInPath final Job<?, ?> project, StaplerResponse response) {;
|
||||
response.setHeader("script", "document.getElementById('secretToken').value=''");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.dabsquared.gitlabjenkins.cause;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import hudson.markup.EscapedMarkupFormatter;
|
||||
import jenkins.model.Jenkins;
|
||||
import net.karneim.pojobuilder.GeneratePojoBuilder;
|
||||
|
@ -8,10 +9,7 @@ import org.apache.commons.lang.builder.EqualsBuilder;
|
|||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
|
@ -36,6 +34,10 @@ public final class CauseData {
|
|||
private final String mergeRequestDescription;
|
||||
private final Integer mergeRequestId;
|
||||
private final Integer mergeRequestIid;
|
||||
private final String mergeRequestState;
|
||||
private final String mergedByUser;
|
||||
private final String mergeRequestAssignee;
|
||||
private final Integer mergeRequestTargetProjectId;
|
||||
private final String targetBranch;
|
||||
private final String targetRepoName;
|
||||
private final String targetNamespace;
|
||||
|
@ -47,14 +49,24 @@ public final class CauseData {
|
|||
private final String lastCommit;
|
||||
private final String targetProjectUrl;
|
||||
private final String triggerPhrase;
|
||||
private final String ref;
|
||||
private final String beforeSha;
|
||||
private final String isTag;
|
||||
private final String sha;
|
||||
private final String status;
|
||||
private final String stages;
|
||||
private final String createdAt;
|
||||
private final String finishedAt;
|
||||
private final String buildDuration;
|
||||
|
||||
@GeneratePojoBuilder(withFactoryMethod = "*")
|
||||
CauseData(ActionType actionType, Integer sourceProjectId, Integer targetProjectId, String branch, String sourceBranch, String userName,
|
||||
String userEmail, String sourceRepoHomepage, String sourceRepoName, String sourceNamespace, String sourceRepoUrl,
|
||||
String sourceRepoSshUrl, String sourceRepoHttpUrl, String mergeRequestTitle, String mergeRequestDescription, Integer mergeRequestId,
|
||||
Integer mergeRequestIid, String targetBranch, String targetRepoName, String targetNamespace, String targetRepoSshUrl,
|
||||
Integer mergeRequestIid, Integer mergeRequestTargetProjectId, String targetBranch, String targetRepoName, String targetNamespace, String targetRepoSshUrl,
|
||||
String targetRepoHttpUrl, String triggeredByUser, String before, String after, String lastCommit, String targetProjectUrl,
|
||||
String triggerPhrase) {
|
||||
String triggerPhrase, String mergeRequestState, String mergedByUser, String mergeRequestAssignee, String ref, String isTag,
|
||||
String sha, String beforeSha, String status, String stages, String createdAt, String finishedAt, String buildDuration) {
|
||||
this.actionType = checkNotNull(actionType, "actionType must not be null.");
|
||||
this.sourceProjectId = checkNotNull(sourceProjectId, "sourceProjectId must not be null.");
|
||||
this.targetProjectId = checkNotNull(targetProjectId, "targetProjectId must not be null.");
|
||||
|
@ -72,6 +84,10 @@ public final class CauseData {
|
|||
this.mergeRequestDescription = mergeRequestDescription == null ? "" : mergeRequestDescription;
|
||||
this.mergeRequestId = mergeRequestId;
|
||||
this.mergeRequestIid = mergeRequestIid;
|
||||
this.mergeRequestState = mergeRequestState == null ? "" : mergeRequestState;
|
||||
this.mergedByUser = mergedByUser == null ? "" : mergedByUser;
|
||||
this.mergeRequestAssignee = mergeRequestAssignee == null ? "" : mergeRequestAssignee;
|
||||
this.mergeRequestTargetProjectId = mergeRequestTargetProjectId;
|
||||
this.targetBranch = checkNotNull(targetBranch, "targetBranch must not be null.");
|
||||
this.targetRepoName = checkNotNull(targetRepoName, "targetRepoName must not be null.");
|
||||
this.targetNamespace = checkNotNull(targetNamespace, "targetNamespace must not be null.");
|
||||
|
@ -83,6 +99,15 @@ public final class CauseData {
|
|||
this.lastCommit = checkNotNull(lastCommit, "lastCommit must not be null");
|
||||
this.targetProjectUrl = targetProjectUrl;
|
||||
this.triggerPhrase = triggerPhrase;
|
||||
this.ref = ref;
|
||||
this.isTag = isTag;
|
||||
this.sha = sha;
|
||||
this.beforeSha = beforeSha;
|
||||
this.status = status;
|
||||
this.stages = stages;
|
||||
this.createdAt = createdAt;
|
||||
this.finishedAt = finishedAt;
|
||||
this.buildDuration = buildDuration;
|
||||
}
|
||||
|
||||
public Map<String, String> getBuildVariables() {
|
||||
|
@ -102,7 +127,11 @@ public final class CauseData {
|
|||
variables.put("gitlabMergeRequestDescription", mergeRequestDescription);
|
||||
variables.put("gitlabMergeRequestId", mergeRequestId == null ? "" : mergeRequestId.toString());
|
||||
variables.put("gitlabMergeRequestIid", mergeRequestIid == null ? "" : mergeRequestIid.toString());
|
||||
variables.put("gitlabMergeRequestTargetProjectId", mergeRequestTargetProjectId == null ? "" : mergeRequestTargetProjectId.toString());
|
||||
variables.put("gitlabMergeRequestLastCommit", lastCommit);
|
||||
variables.putIfNotNull("gitlabMergeRequestState", mergeRequestState);
|
||||
variables.putIfNotNull("gitlabMergedByUser", mergedByUser);
|
||||
variables.putIfNotNull("gitlabMergeRequestAssignee", mergeRequestAssignee);
|
||||
variables.put("gitlabTargetBranch", targetBranch);
|
||||
variables.put("gitlabTargetRepoName", targetRepoName);
|
||||
variables.put("gitlabTargetNamespace", targetNamespace);
|
||||
|
@ -110,7 +139,16 @@ public final class CauseData {
|
|||
variables.put("gitlabTargetRepoHttpUrl", targetRepoHttpUrl);
|
||||
variables.put("gitlabBefore", before);
|
||||
variables.put("gitlabAfter", after);
|
||||
variables.pufIfNotNull("gitlabTriggerPhrase", triggerPhrase);
|
||||
variables.put("ref", ref);
|
||||
variables.put("beforeSha", beforeSha);
|
||||
variables.put("isTag", isTag);
|
||||
variables.put("sha", sha);
|
||||
variables.put("status", status);
|
||||
variables.put("stages", stages);
|
||||
variables.put("createdAt", createdAt);
|
||||
variables.put("finishedAt", finishedAt);
|
||||
variables.put("duration", buildDuration);
|
||||
variables.putIfNotNull("gitlabTriggerPhrase", triggerPhrase);
|
||||
return variables;
|
||||
}
|
||||
|
||||
|
@ -182,6 +220,10 @@ public final class CauseData {
|
|||
return mergeRequestIid;
|
||||
}
|
||||
|
||||
public Integer getMergeRequestTargetProjectId() {
|
||||
return mergeRequestTargetProjectId;
|
||||
}
|
||||
|
||||
public String getTargetBranch() {
|
||||
return targetBranch;
|
||||
}
|
||||
|
@ -222,10 +264,50 @@ public final class CauseData {
|
|||
return targetProjectUrl;
|
||||
}
|
||||
|
||||
public String getRef() { return ref; }
|
||||
|
||||
public String getIsTag() { return isTag; }
|
||||
|
||||
public String getSha() { return sha; }
|
||||
|
||||
public String getBeforeSha() {return beforeSha; }
|
||||
|
||||
public String getStatus() { return status; }
|
||||
|
||||
public String getStages() { return stages; }
|
||||
|
||||
public String getCreatedAt() { return createdAt; }
|
||||
|
||||
public String getFinishedAt() { return finishedAt; }
|
||||
|
||||
public String getBuildDuration() { return buildDuration; }
|
||||
|
||||
|
||||
String getShortDescription() {
|
||||
return actionType.getShortDescription(this);
|
||||
}
|
||||
|
||||
public String getMergeRequestState() {
|
||||
return mergeRequestState;
|
||||
}
|
||||
|
||||
public String getMergedByUser() {
|
||||
return mergedByUser;
|
||||
}
|
||||
|
||||
public String getMergeRequestAssignee() {
|
||||
return mergeRequestAssignee;
|
||||
}
|
||||
|
||||
public MergeRequest getMergeRequest() {
|
||||
if (mergeRequestId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new MergeRequest(mergeRequestId, mergeRequestIid, sourceBranch, targetBranch, mergeRequestTitle,
|
||||
sourceProjectId, targetProjectId, mergeRequestDescription, mergeRequestState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
@ -253,6 +335,10 @@ public final class CauseData {
|
|||
.append(mergeRequestDescription, causeData.mergeRequestDescription)
|
||||
.append(mergeRequestId, causeData.mergeRequestId)
|
||||
.append(mergeRequestIid, causeData.mergeRequestIid)
|
||||
.append(mergeRequestState, causeData.mergeRequestState)
|
||||
.append(mergedByUser, causeData.mergedByUser)
|
||||
.append(mergeRequestAssignee, causeData.mergeRequestAssignee)
|
||||
.append(mergeRequestTargetProjectId, causeData.mergeRequestTargetProjectId)
|
||||
.append(targetBranch, causeData.targetBranch)
|
||||
.append(targetRepoName, causeData.targetRepoName)
|
||||
.append(targetNamespace, causeData.targetNamespace)
|
||||
|
@ -263,6 +349,15 @@ public final class CauseData {
|
|||
.append(after, causeData.after)
|
||||
.append(lastCommit, causeData.lastCommit)
|
||||
.append(targetProjectUrl, causeData.targetProjectUrl)
|
||||
.append(ref, causeData.getRef())
|
||||
.append(isTag, causeData.getIsTag())
|
||||
.append(sha, causeData.getSha())
|
||||
.append(beforeSha, causeData.getBeforeSha())
|
||||
.append(status, causeData.getStatus())
|
||||
.append(stages, causeData.getStages())
|
||||
.append(createdAt, causeData.getCreatedAt())
|
||||
.append(finishedAt, causeData.getFinishedAt())
|
||||
.append(buildDuration, causeData.getBuildDuration())
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
|
@ -286,6 +381,10 @@ public final class CauseData {
|
|||
.append(mergeRequestDescription)
|
||||
.append(mergeRequestId)
|
||||
.append(mergeRequestIid)
|
||||
.append(mergeRequestState)
|
||||
.append(mergedByUser)
|
||||
.append(mergeRequestAssignee)
|
||||
.append(mergeRequestTargetProjectId)
|
||||
.append(targetBranch)
|
||||
.append(targetRepoName)
|
||||
.append(targetNamespace)
|
||||
|
@ -296,6 +395,15 @@ public final class CauseData {
|
|||
.append(after)
|
||||
.append(lastCommit)
|
||||
.append(targetProjectUrl)
|
||||
.append(ref)
|
||||
.append(isTag)
|
||||
.append(sha)
|
||||
.append(beforeSha)
|
||||
.append(status)
|
||||
.append(stages)
|
||||
.append(createdAt)
|
||||
.append(finishedAt)
|
||||
.append(buildDuration)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
|
@ -319,6 +427,10 @@ public final class CauseData {
|
|||
.append("mergeRequestDescription", mergeRequestDescription)
|
||||
.append("mergeRequestId", mergeRequestId)
|
||||
.append("mergeRequestIid", mergeRequestIid)
|
||||
.append("mergeRequestState", mergeRequestState)
|
||||
.append("mergedByUser", mergedByUser)
|
||||
.append("mergeRequestAssignee", mergeRequestAssignee)
|
||||
.append("mergeRequestTargetProjectId", mergeRequestTargetProjectId)
|
||||
.append("targetBranch", targetBranch)
|
||||
.append("targetRepoName", targetRepoName)
|
||||
.append("targetNamespace", targetNamespace)
|
||||
|
@ -329,6 +441,15 @@ public final class CauseData {
|
|||
.append("after", after)
|
||||
.append("lastCommit", lastCommit)
|
||||
.append("targetProjectUrl", targetProjectUrl)
|
||||
.append("ref", ref)
|
||||
.append("isTag", isTag)
|
||||
.append("sha", sha)
|
||||
.append("beforeSha", beforeSha)
|
||||
.append("status", status)
|
||||
.append("stages", stages)
|
||||
.append("createdAt", createdAt)
|
||||
.append("finishedAt", finishedAt)
|
||||
.append("duration", buildDuration)
|
||||
.toString();
|
||||
}
|
||||
|
||||
|
@ -336,12 +457,12 @@ public final class CauseData {
|
|||
PUSH {
|
||||
@Override
|
||||
String getShortDescription(CauseData data) {
|
||||
String pushedBy = data.getTriggeredByUser();
|
||||
if (pushedBy == null) {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_PushHook_noUser();
|
||||
} else {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_PushHook(pushedBy);
|
||||
}
|
||||
return getShortDescriptionPush(data);
|
||||
}
|
||||
}, TAG_PUSH {
|
||||
@Override
|
||||
String getShortDescription(CauseData data) {
|
||||
return getShortDescriptionPush(data);
|
||||
}
|
||||
}, MERGE {
|
||||
@Override
|
||||
|
@ -365,19 +486,38 @@ public final class CauseData {
|
|||
String forkNamespace = StringUtils.equals(data.getSourceNamespace(), data.getTargetBranch()) ? "" : data.getSourceNamespace() + "/";
|
||||
if (Jenkins.getActiveInstance().getMarkupFormatter() instanceof EscapedMarkupFormatter || data.getTargetProjectUrl() == null) {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_NoteHook_plain(triggeredBy,
|
||||
String.valueOf(data.getMergeRequestIid()),
|
||||
forkNamespace + data.getSourceBranch(),
|
||||
data.getTargetBranch());
|
||||
String.valueOf(data.getMergeRequestIid()),
|
||||
forkNamespace + data.getSourceBranch(),
|
||||
data.getTargetBranch());
|
||||
} else {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_NoteHook_html(triggeredBy,
|
||||
String.valueOf(data.getMergeRequestIid()),
|
||||
forkNamespace + data.getSourceBranch(),
|
||||
data.getTargetBranch(),
|
||||
data.getTargetProjectUrl());
|
||||
String.valueOf(data.getMergeRequestIid()),
|
||||
forkNamespace + data.getSourceBranch(),
|
||||
data.getTargetBranch(),
|
||||
data.getTargetProjectUrl());
|
||||
}
|
||||
}
|
||||
}, PIPELINE {
|
||||
@Override
|
||||
String getShortDescription(CauseData data) {
|
||||
String getStatus = data.getStatus();
|
||||
if (getStatus == null) {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_PipelineHook_noStatus();
|
||||
} else {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_PipelineHook(getStatus);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static String getShortDescriptionPush(CauseData data) {
|
||||
String pushedBy = data.getTriggeredByUser();
|
||||
if (pushedBy == null) {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_PushHook_noUser();
|
||||
} else {
|
||||
return Messages.GitLabWebHookCause_ShortDescription_PushHook(pushedBy);
|
||||
}
|
||||
}
|
||||
|
||||
abstract String getShortDescription(CauseData data);
|
||||
}
|
||||
|
||||
|
@ -385,7 +525,7 @@ public final class CauseData {
|
|||
|
||||
private final Map<K, V> map;
|
||||
|
||||
public MapWrapper(Map<K, V> map) {
|
||||
MapWrapper(Map<K, V> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
|
@ -399,7 +539,7 @@ public final class CauseData {
|
|||
return map.entrySet();
|
||||
}
|
||||
|
||||
public void pufIfNotNull(K key, V value) {
|
||||
void putIfNotNull(K key, V value) {
|
||||
if (value != null) {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
|
|
@ -1,39 +1,83 @@
|
|||
package com.dabsquared.gitlabjenkins.connection;
|
||||
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsMatchers;
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.common.StandardCredentials;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.AutodetectGitLabClientBuilder;
|
||||
import hudson.init.InitMilestone;
|
||||
import hudson.init.Initializer;
|
||||
import hudson.model.Item;
|
||||
import hudson.security.ACL;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
|
||||
import org.kohsuke.accmod.Restricted;
|
||||
import org.kohsuke.accmod.restrictions.NoExternalUse;
|
||||
import org.kohsuke.stapler.DataBoundConstructor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials;
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder.getGitLabClientBuilderById;
|
||||
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
public class GitLabConnection {
|
||||
|
||||
private final String name;
|
||||
private final String url;
|
||||
private transient String apiToken;
|
||||
// TODO make final when migration code gets removed
|
||||
private String apiTokenId;
|
||||
private GitLabClientBuilder clientBuilder;
|
||||
private final boolean ignoreCertificateErrors;
|
||||
private final Integer connectionTimeout;
|
||||
private final Integer readTimeout;
|
||||
private transient GitLabClient apiCache;
|
||||
|
||||
public GitLabConnection(String name, String url, String apiTokenId, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) {
|
||||
this(
|
||||
name,
|
||||
url,
|
||||
apiTokenId,
|
||||
new AutodetectGitLabClientBuilder(),
|
||||
ignoreCertificateErrors,
|
||||
connectionTimeout,
|
||||
readTimeout
|
||||
);
|
||||
}
|
||||
|
||||
@DataBoundConstructor
|
||||
public GitLabConnection(String name, String url, String apiTokenId, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) {
|
||||
public GitLabConnection(String name, String url, String apiTokenId, String clientBuilderId, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) {
|
||||
this(
|
||||
name,
|
||||
url,
|
||||
apiTokenId,
|
||||
getGitLabClientBuilderById(clientBuilderId),
|
||||
ignoreCertificateErrors,
|
||||
connectionTimeout,
|
||||
readTimeout
|
||||
);
|
||||
}
|
||||
|
||||
@Restricted(NoExternalUse.class)
|
||||
public GitLabConnection(String name, String url, String apiTokenId, GitLabClientBuilder clientBuilder, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.apiTokenId = apiTokenId;
|
||||
this.clientBuilder = clientBuilder;
|
||||
this.ignoreCertificateErrors = ignoreCertificateErrors;
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
this.readTimeout = readTimeout;
|
||||
|
@ -51,6 +95,10 @@ public class GitLabConnection {
|
|||
return apiTokenId;
|
||||
}
|
||||
|
||||
public String getClientBuilderId() {
|
||||
return clientBuilder.id();
|
||||
}
|
||||
|
||||
public boolean isIgnoreCertificateErrors() {
|
||||
return ignoreCertificateErrors;
|
||||
}
|
||||
|
@ -63,10 +111,38 @@ public class GitLabConnection {
|
|||
return readTimeout;
|
||||
}
|
||||
|
||||
public GitLabClient getClient() {
|
||||
if (apiCache == null) {
|
||||
apiCache = clientBuilder.buildClient(url, getApiToken(apiTokenId), ignoreCertificateErrors, connectionTimeout, readTimeout);
|
||||
}
|
||||
|
||||
return apiCache;
|
||||
}
|
||||
|
||||
private String getApiToken(String apiTokenId) {
|
||||
StandardCredentials credentials = CredentialsMatchers.firstOrNull(
|
||||
lookupCredentials(StandardCredentials.class, (Item) null, ACL.SYSTEM, new ArrayList<DomainRequirement>()),
|
||||
CredentialsMatchers.withId(apiTokenId));
|
||||
if (credentials != null) {
|
||||
if (credentials instanceof GitLabApiToken) {
|
||||
return ((GitLabApiToken) credentials).getApiToken().getPlainText();
|
||||
}
|
||||
if (credentials instanceof StringCredentials) {
|
||||
return ((StringCredentials) credentials).getSecret().getPlainText();
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No credentials found for credentialsId: " + apiTokenId);
|
||||
}
|
||||
|
||||
|
||||
protected GitLabConnection readResolve() {
|
||||
if (connectionTimeout == null || readTimeout == null) {
|
||||
return new GitLabConnection(name, url, apiTokenId, ignoreCertificateErrors, 10, 10);
|
||||
return new GitLabConnection(name, url, apiTokenId, new AutodetectGitLabClientBuilder(), ignoreCertificateErrors, 10, 10);
|
||||
}
|
||||
if (clientBuilder == null) {
|
||||
return new GitLabConnection(name, url, apiTokenId, new AutodetectGitLabClientBuilder(), ignoreCertificateErrors, connectionTimeout, readTimeout);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package com.dabsquared.gitlabjenkins.connection;
|
||||
|
||||
|
||||
import com.cloudbees.plugins.credentials.Credentials;
|
||||
import com.cloudbees.plugins.credentials.CredentialsMatcher;
|
||||
import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel;
|
||||
import com.cloudbees.plugins.credentials.common.StandardCredentials;
|
||||
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
|
||||
import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import edu.umd.cs.findbugs.annotations.NonNull;
|
||||
import hudson.Extension;
|
||||
import hudson.model.Item;
|
||||
|
@ -29,16 +30,18 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder.getAllGitLabClientBuilders;
|
||||
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
@Extension
|
||||
public class GitLabConnectionConfig extends GlobalConfiguration {
|
||||
|
||||
private boolean useAuthenticatedEndpoint;
|
||||
private Boolean useAuthenticatedEndpoint = true;
|
||||
private List<GitLabConnection> connections = new ArrayList<>();
|
||||
private transient Map<String, GitLabConnection> connectionMap = new HashMap<>();
|
||||
private transient Map<String, GitLabApi> clients = new HashMap<>();
|
||||
|
||||
public GitLabConnectionConfig() {
|
||||
load();
|
||||
|
@ -50,7 +53,6 @@ public class GitLabConnectionConfig extends GlobalConfiguration {
|
|||
connections = req.bindJSONToList(GitLabConnection.class, json.get("connections"));
|
||||
useAuthenticatedEndpoint = json.getBoolean("useAuthenticatedEndpoint");
|
||||
refreshConnectionMap();
|
||||
clients.clear();
|
||||
save();
|
||||
return super.configure(req, json);
|
||||
}
|
||||
|
@ -72,11 +74,19 @@ public class GitLabConnectionConfig extends GlobalConfiguration {
|
|||
connectionMap.put(connection.getName(), connection);
|
||||
}
|
||||
|
||||
public GitLabApi getClient(String connectionName) {
|
||||
if (!clients.containsKey(connectionName) && connectionMap.containsKey(connectionName)) {
|
||||
clients.put(connectionName, GitLabClientBuilder.buildClient(connectionMap.get(connectionName)));
|
||||
public void setConnections(List<GitLabConnection> newConnections) {
|
||||
connections = new ArrayList<>();
|
||||
connectionMap = new HashMap<>();
|
||||
for (GitLabConnection connection: newConnections){
|
||||
addConnection(connection);
|
||||
}
|
||||
return clients.get(connectionName);
|
||||
}
|
||||
|
||||
public GitLabClient getClient(String connectionName) {
|
||||
if (!connectionMap.containsKey(connectionName)) {
|
||||
return null;
|
||||
}
|
||||
return connectionMap.get(connectionName).getClient();
|
||||
}
|
||||
|
||||
public FormValidation doCheckName(@QueryParameter String id, @QueryParameter String value) {
|
||||
|
@ -123,11 +133,12 @@ public class GitLabConnectionConfig extends GlobalConfiguration {
|
|||
|
||||
public FormValidation doTestConnection(@QueryParameter String url,
|
||||
@QueryParameter String apiTokenId,
|
||||
@QueryParameter String clientBuilderId,
|
||||
@QueryParameter boolean ignoreCertificateErrors,
|
||||
@QueryParameter int connectionTimeout,
|
||||
@QueryParameter int readTimeout) {
|
||||
try {
|
||||
GitLabClientBuilder.buildClient(url, apiTokenId, ignoreCertificateErrors, connectionTimeout, readTimeout).headCurrentUser();
|
||||
new GitLabConnection("", url, apiTokenId, clientBuilderId, ignoreCertificateErrors, connectionTimeout, readTimeout).getClient().getCurrentUser();
|
||||
return FormValidation.ok(Messages.connection_success());
|
||||
} catch (WebApplicationException e) {
|
||||
return FormValidation.error(Messages.connection_error(e.getMessage()));
|
||||
|
@ -159,6 +170,15 @@ public class GitLabConnectionConfig extends GlobalConfiguration {
|
|||
return new StandardListBoxModel();
|
||||
}
|
||||
|
||||
public ListBoxModel doFillClientBuilderIdItems() {
|
||||
ListBoxModel model = new ListBoxModel();
|
||||
for (GitLabClientBuilder builder : getAllGitLabClientBuilders()) {
|
||||
model.add(builder.id());
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private void refreshConnectionMap() {
|
||||
connectionMap.clear();
|
||||
for (GitLabConnection connection : connections) {
|
||||
|
@ -176,4 +196,11 @@ public class GitLabConnectionConfig extends GlobalConfiguration {
|
|||
}
|
||||
}
|
||||
}
|
||||
//For backwards compatibility. ReadResolve is called on startup
|
||||
protected GitLabConnectionConfig readResolve() {
|
||||
if (useAuthenticatedEndpoint == null) {
|
||||
setUseAuthenticatedEndpoint(false);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.dabsquared.gitlabjenkins.connection;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import hudson.Extension;
|
||||
import hudson.model.Job;
|
||||
import hudson.model.JobProperty;
|
||||
|
@ -30,7 +31,7 @@ public class GitLabConnectionProperty extends JobProperty<Job<?, ?>> {
|
|||
return gitLabConnection;
|
||||
}
|
||||
|
||||
public GitLabApi getClient() {
|
||||
public GitLabClient getClient() {
|
||||
if (StringUtils.isNotEmpty(gitLabConnection)) {
|
||||
GitLabConnectionConfig connectionConfig = (GitLabConnectionConfig) Jenkins.getInstance().getDescriptor(GitLabConnectionConfig.class);
|
||||
return connectionConfig != null ? connectionConfig.getClient(gitLabConnection) : null;
|
||||
|
@ -38,7 +39,7 @@ public class GitLabConnectionProperty extends JobProperty<Job<?, ?>> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static GitLabApi getClient(Run<?, ?> build) {
|
||||
public static GitLabClient getClient(Run<?, ?> build) {
|
||||
final GitLabConnectionProperty connectionProperty = build.getParent().getProperty(GitLabConnectionProperty.class);
|
||||
if (connectionProperty != null) {
|
||||
return connectionProperty.getClient();
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.dabsquared.gitlabjenkins.environment;
|
|||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import hudson.EnvVars;
|
||||
import hudson.Extension;
|
||||
import hudson.matrix.MatrixRun;
|
||||
import hudson.matrix.MatrixBuild;
|
||||
import hudson.model.EnvironmentContributor;
|
||||
import hudson.model.Run;
|
||||
import hudson.model.TaskListener;
|
||||
|
@ -17,7 +19,15 @@ import java.io.IOException;
|
|||
public class GitLabEnvironmentContributor extends EnvironmentContributor {
|
||||
@Override
|
||||
public void buildEnvironmentFor(@Nonnull Run r, @Nonnull EnvVars envs, @Nonnull TaskListener listener) throws IOException, InterruptedException {
|
||||
GitLabWebHookCause cause = (GitLabWebHookCause) r.getCause(GitLabWebHookCause.class);
|
||||
GitLabWebHookCause cause = null;
|
||||
if (r instanceof MatrixRun) {
|
||||
MatrixBuild parent = ((MatrixRun)r).getParentBuild();
|
||||
if (parent != null) {
|
||||
cause = (GitLabWebHookCause) parent.getCause(GitLabWebHookCause.class);
|
||||
}
|
||||
} else {
|
||||
cause = (GitLabWebHookCause) r.getCause(GitLabWebHookCause.class);
|
||||
}
|
||||
if (cause != null) {
|
||||
envs.overrideAll(cause.getData().getBuildVariables());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface GitLabClient {
|
||||
String getHostUrl();
|
||||
|
||||
Project createProject(String projectName);
|
||||
|
||||
MergeRequest createMergeRequest(Integer projectId, String sourceBranch, String targetBranch, String title);
|
||||
|
||||
Project getProject(String projectName);
|
||||
|
||||
Project updateProject(String projectId, String name, String path);
|
||||
|
||||
void deleteProject(String projectId);
|
||||
|
||||
void addProjectHook(String projectId, String url, Boolean pushEvents, Boolean mergeRequestEvents, Boolean noteEvents);
|
||||
|
||||
void changeBuildStatus(String projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description);
|
||||
|
||||
void changeBuildStatus(Integer projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description);
|
||||
|
||||
void getCommit(String projectId, String sha);
|
||||
|
||||
void acceptMergeRequest(MergeRequest mr, String mergeCommitMessage, boolean shouldRemoveSourceBranch);
|
||||
|
||||
void createMergeRequestNote(MergeRequest mr, String body);
|
||||
|
||||
List<MergeRequest> getMergeRequests(String projectId, State state, int page, int perPage);
|
||||
|
||||
List<Branch> getBranches(String projectId);
|
||||
|
||||
Branch getBranch(String projectId, String branch);
|
||||
|
||||
User getCurrentUser();
|
||||
|
||||
User addUser(String email, String username, String name, String password);
|
||||
|
||||
User updateUser(String userId, String email, String username, String name, String password);
|
||||
|
||||
List<Label> getLabels(String projectId);
|
||||
|
||||
List<Pipeline> getPipelines(String projectName);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api;
|
||||
|
||||
|
||||
import hudson.ExtensionPoint;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.kohsuke.accmod.Restricted;
|
||||
import org.kohsuke.accmod.restrictions.NoExternalUse;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import static java.util.Collections.sort;
|
||||
|
||||
@Restricted(NoExternalUse.class)
|
||||
public abstract class GitLabClientBuilder implements Comparable<GitLabClientBuilder>, ExtensionPoint, Serializable {
|
||||
public static GitLabClientBuilder getGitLabClientBuilderById(String id) {
|
||||
for (GitLabClientBuilder provider : getAllGitLabClientBuilders()) {
|
||||
if (provider.id().equals(id)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NoSuchElementException("unknown client-builder-id: " + id);
|
||||
}
|
||||
|
||||
public static List<GitLabClientBuilder> getAllGitLabClientBuilders() {
|
||||
List<GitLabClientBuilder> builders = new ArrayList<>(Jenkins.getInstance().getExtensionList(GitLabClientBuilder.class));
|
||||
sort(builders);
|
||||
return builders;
|
||||
}
|
||||
|
||||
private final String id;
|
||||
private final int ordinal;
|
||||
|
||||
protected GitLabClientBuilder(String id, int ordinal) {
|
||||
this.id = id;
|
||||
this.ordinal = ordinal;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public abstract GitLabClient buildClient(String url, String token, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout);
|
||||
|
||||
@Override
|
||||
public final int compareTo(@Nonnull GitLabClientBuilder other) {
|
||||
int o = ordinal - other.ordinal;
|
||||
return o != 0 ? o : id().compareTo(other.id());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import hudson.Extension;
|
||||
import org.kohsuke.accmod.Restricted;
|
||||
import org.kohsuke.accmod.restrictions.NoExternalUse;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
@Extension
|
||||
@Restricted(NoExternalUse.class)
|
||||
public final class AutodetectGitLabClientBuilder extends GitLabClientBuilder {
|
||||
public AutodetectGitLabClientBuilder() {
|
||||
super("autodetect", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public GitLabClient buildClient(String url, String token, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) {
|
||||
Collection<GitLabClientBuilder> candidates = new ArrayList<>(getAllGitLabClientBuilders());
|
||||
candidates.remove(this);
|
||||
return new AutodetectingGitLabClient(candidates, url, token, ignoreCertificateErrors, connectionTimeout, readTimeout);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
|
||||
final class AutodetectingGitLabClient implements GitLabClient {
|
||||
private final Iterable<GitLabClientBuilder> builders;
|
||||
private final String url;
|
||||
private final String token;
|
||||
private final boolean ignoreCertificateErrors;
|
||||
private final int connectionTimeout;
|
||||
private final int readTimeout;
|
||||
private GitLabClient delegate;
|
||||
|
||||
|
||||
AutodetectingGitLabClient(Iterable<GitLabClientBuilder> builders, String url, String token, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) {
|
||||
this.builders = builders;
|
||||
this.url = url;
|
||||
this.token = token;
|
||||
this.ignoreCertificateErrors = ignoreCertificateErrors;
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
this.readTimeout = readTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project createProject(final String projectName) {
|
||||
return execute(
|
||||
new GitLabOperation<Project>() {
|
||||
@Override
|
||||
Project execute(GitLabClient client) {
|
||||
return client.createProject(projectName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergeRequest createMergeRequest(final Integer projectId, final String sourceBranch, final String targetBranch, final String title) {
|
||||
return execute(
|
||||
new GitLabOperation<MergeRequest>() {
|
||||
@Override
|
||||
MergeRequest execute(GitLabClient client) {
|
||||
return client.createMergeRequest(projectId, sourceBranch, targetBranch, title);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project getProject(final String projectName) {
|
||||
return execute(
|
||||
new GitLabOperation<Project>() {
|
||||
@Override
|
||||
Project execute(GitLabClient client) {
|
||||
return client.getProject(projectName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project updateProject(final String projectId, final String name, final String path) {
|
||||
return execute(
|
||||
new GitLabOperation<Project>() {
|
||||
@Override
|
||||
Project execute(GitLabClient client) {
|
||||
return client.updateProject(projectId, name, path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProject(final String projectId) {
|
||||
execute(
|
||||
new GitLabOperation<Void>() {
|
||||
@Override
|
||||
Void execute(GitLabClient client) {
|
||||
client.deleteProject(projectId);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProjectHook(final String projectId, final String url, final Boolean pushEvents, final Boolean mergeRequestEvents, final Boolean noteEvents) {
|
||||
execute(
|
||||
new GitLabOperation<Void>() {
|
||||
@Override
|
||||
Void execute(GitLabClient client) {
|
||||
client.addProjectHook(projectId, url, pushEvents, mergeRequestEvents, noteEvents);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(final String projectId, final String sha, final BuildState state, final String ref, final String context, final String targetUrl, final String description) {
|
||||
execute(
|
||||
new GitLabOperation<Void>() {
|
||||
@Override
|
||||
Void execute(GitLabClient client) {
|
||||
client.changeBuildStatus(projectId, sha, state, ref, context, targetUrl, description);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(final Integer projectId, final String sha, final BuildState state, final String ref, final String context, final String targetUrl, final String description) {
|
||||
execute(
|
||||
new GitLabOperation<Void>() {
|
||||
@Override
|
||||
Void execute(GitLabClient client) {
|
||||
client.changeBuildStatus(projectId, sha, state, ref, context, targetUrl, description);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCommit(final String projectId, final String sha) {
|
||||
execute(
|
||||
new GitLabOperation<Void>() {
|
||||
@Override
|
||||
Void execute(GitLabClient client) {
|
||||
client.getCommit(projectId, sha);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptMergeRequest(final MergeRequest mr, final String mergeCommitMessage, final boolean shouldRemoveSourceBranch) {
|
||||
execute(
|
||||
new GitLabOperation<Void>() {
|
||||
@Override
|
||||
Void execute(GitLabClient client) {
|
||||
client.acceptMergeRequest(mr, mergeCommitMessage, shouldRemoveSourceBranch);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMergeRequestNote(final MergeRequest mr, final String body) {
|
||||
execute(
|
||||
new GitLabOperation<Void>() {
|
||||
@Override
|
||||
Void execute(GitLabClient client) {
|
||||
client.createMergeRequestNote(mr, body);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MergeRequest> getMergeRequests(final String projectId, final State state, final int page, final int perPage) {
|
||||
return execute(
|
||||
new GitLabOperation<List<MergeRequest>>() {
|
||||
@Override
|
||||
List<MergeRequest> execute(GitLabClient client) {
|
||||
return client.getMergeRequests(projectId, state, page, perPage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Branch> getBranches(final String projectId) {
|
||||
return execute(
|
||||
new GitLabOperation<List<Branch>>() {
|
||||
@Override
|
||||
List<Branch> execute(GitLabClient client) {
|
||||
return client.getBranches(projectId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Branch getBranch(final String projectId, final String branch) {
|
||||
return execute(
|
||||
new GitLabOperation<Branch>() {
|
||||
@Override
|
||||
Branch execute(GitLabClient client) {
|
||||
return client.getBranch(projectId, branch);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getCurrentUser() {
|
||||
return execute(
|
||||
new GitLabOperation<User>() {
|
||||
@Override
|
||||
User execute(GitLabClient client) {
|
||||
return client.getCurrentUser();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public User addUser(final String email, final String username, final String name, final String password) {
|
||||
return execute(
|
||||
new GitLabOperation<User>() {
|
||||
@Override
|
||||
User execute(GitLabClient client) {
|
||||
return client.addUser(email, username, name, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public User updateUser(final String userId, final String email, final String username, final String name, final String password) {
|
||||
return execute(
|
||||
new GitLabOperation<User>() {
|
||||
@Override
|
||||
User execute(GitLabClient client) {
|
||||
return client.updateUser(userId, email, username, name, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Label> getLabels(final String projectId) {
|
||||
return execute(
|
||||
new GitLabOperation<List<Label>>() {
|
||||
@Override
|
||||
List<Label> execute(GitLabClient client) {
|
||||
return client.getLabels(projectId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pipeline> getPipelines(final String projectName) {
|
||||
return execute(
|
||||
new GitLabOperation<List<Pipeline>>() {
|
||||
@Override
|
||||
List<Pipeline> execute(GitLabClient client) {
|
||||
return client.getPipelines(projectName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private GitLabClient delegate(boolean reset) {
|
||||
if (reset || delegate == null) {
|
||||
delegate = autodetectOrDie();
|
||||
}
|
||||
|
||||
return delegate;
|
||||
}
|
||||
|
||||
private GitLabClient autodetectOrDie() {
|
||||
GitLabClient client = autodetect();
|
||||
if (client != null) {
|
||||
return client;
|
||||
}
|
||||
|
||||
throw new NoSuchElementException("no client-builder found that supports server at " + url);
|
||||
}
|
||||
|
||||
private GitLabClient autodetect() {
|
||||
for (GitLabClientBuilder candidate : builders) {
|
||||
GitLabClient client = candidate.buildClient(url, token, ignoreCertificateErrors, connectionTimeout, readTimeout);
|
||||
try {
|
||||
client.getCurrentUser();
|
||||
return client;
|
||||
} catch (NotFoundException ignored) {
|
||||
// api-endpoint not found (== api-level not supported by this client)
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private <R> R execute(GitLabOperation<R> operation) {
|
||||
return operation.execute(false);
|
||||
}
|
||||
|
||||
|
||||
private abstract class GitLabOperation<R> {
|
||||
private R execute(boolean reset) {
|
||||
try {
|
||||
return execute(delegate(reset));
|
||||
} catch (NotFoundException e) {
|
||||
if (reset) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return execute(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
abstract R execute(GitLabClient client);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
interface GitLabApiProxy {
|
||||
Project createProject(String projectName);
|
||||
|
||||
MergeRequest createMergeRequest(Integer projectId, String sourceBranch, String targetBranch, String title);
|
||||
|
||||
Project getProject(String projectName);
|
||||
|
||||
Project updateProject(String projectId, String name, String path);
|
||||
|
||||
void deleteProject(String projectId);
|
||||
|
||||
void addProjectHook(String projectId, String url, Boolean pushEvents, Boolean mergeRequestEvents, Boolean noteEvents);
|
||||
|
||||
void changeBuildStatus(String projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description);
|
||||
|
||||
void changeBuildStatus(Integer projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description);
|
||||
|
||||
void getCommit(String projectId, String sha);
|
||||
|
||||
void acceptMergeRequest(Integer projectId, Integer mergeRequestId, String mergeCommitMessage, boolean shouldRemoveSourceBranch);
|
||||
|
||||
void createMergeRequestNote(Integer projectId, Integer mergeRequestId, String body);
|
||||
|
||||
List<MergeRequest> getMergeRequests(String projectId, State state, int page, int perPage);
|
||||
|
||||
List<Branch> getBranches(String projectId);
|
||||
|
||||
Branch getBranch(String projectId, String branch);
|
||||
|
||||
void headCurrentUser();
|
||||
|
||||
User getCurrentUser();
|
||||
|
||||
User addUser(String email, String username, String name, String password);
|
||||
|
||||
User updateUser(String userId, String email, String username, String name, String password);
|
||||
|
||||
List<Label> getLabels(String projectId);
|
||||
|
||||
List<Pipeline> getPipelines(String projectName);
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
final class ResteasyGitLabClient implements GitLabClient {
|
||||
private final String hostUrl;
|
||||
private final GitLabApiProxy api;
|
||||
private final Function<MergeRequest, Integer> mergeRequestIdProvider;
|
||||
|
||||
ResteasyGitLabClient(String hostUrl, GitLabApiProxy api, Function<MergeRequest, Integer> mergeRequestIdProvider) {
|
||||
this.hostUrl = hostUrl;
|
||||
this.api = api;
|
||||
this.mergeRequestIdProvider = mergeRequestIdProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getHostUrl() {
|
||||
return hostUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project createProject(String projectName) {
|
||||
return api.createProject(projectName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergeRequest createMergeRequest(Integer projectId, String sourceBranch, String targetBranch, String title) {
|
||||
return api.createMergeRequest(projectId, sourceBranch, targetBranch, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project getProject(String projectName) {
|
||||
return api.getProject(projectName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project updateProject(String projectId, String name, String path) {
|
||||
return api.updateProject(projectId, name, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProject(String projectId) {
|
||||
api.deleteProject(projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProjectHook(String projectId, String url, Boolean pushEvents, Boolean mergeRequestEvents, Boolean noteEvents) {
|
||||
api.addProjectHook(projectId, url, pushEvents, mergeRequestEvents, noteEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(String projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description) {
|
||||
api.changeBuildStatus(projectId, sha, state, ref, context, targetUrl, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(Integer projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description) {
|
||||
api.changeBuildStatus(projectId, sha, state, ref, context, targetUrl, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCommit(String projectId, String sha) {
|
||||
api.getCommit(projectId, sha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptMergeRequest(MergeRequest mr, String mergeCommitMessage, boolean shouldRemoveSourceBranch) {
|
||||
api.acceptMergeRequest(mr.getProjectId(), mergeRequestIdProvider.apply(mr), mergeCommitMessage, shouldRemoveSourceBranch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMergeRequestNote(MergeRequest mr, String body) {
|
||||
api.createMergeRequestNote(mr.getProjectId(), mergeRequestIdProvider.apply(mr), body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MergeRequest> getMergeRequests(String projectId, State state, int page, int perPage) {
|
||||
return api.getMergeRequests(projectId, state, page, perPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Branch> getBranches(String projectId) {
|
||||
return api.getBranches(projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Branch getBranch(String projectId, String branch) {
|
||||
return api.getBranch(projectId, branch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getCurrentUser() {
|
||||
return api.getCurrentUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public User addUser(String email, String username, String name, String password) {
|
||||
return api.addUser(email, username, name, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User updateUser(String userId, String email, String username, String name, String password) {
|
||||
return api.updateUser(userId, email, username, name, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Label> getLabels(String projectId) {
|
||||
return api.getLabels(projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pipeline> getPipelines(String projectName) {
|
||||
return api.getPipelines(projectName);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab;
|
||||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsMatchers;
|
||||
import com.cloudbees.plugins.credentials.common.StandardCredentials;
|
||||
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabApiToken;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.JacksonConfig;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.dabsquared.gitlabjenkins.util.JsonUtil;
|
||||
import com.dabsquared.gitlabjenkins.util.LoggerUtil;
|
||||
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
|
||||
|
@ -15,8 +14,6 @@ import com.google.common.collect.FluentIterable;
|
|||
import hudson.ProxyConfiguration;
|
||||
import hudson.init.InitMilestone;
|
||||
import hudson.init.Initializer;
|
||||
import hudson.model.Item;
|
||||
import hudson.security.ACL;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -29,8 +26,10 @@ import org.jboss.resteasy.client.jaxrs.ClientHttpEngine;
|
|||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
|
||||
import org.jboss.resteasy.plugins.providers.JaxrsFormProvider;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
|
||||
import org.kohsuke.accmod.Restricted;
|
||||
import org.kohsuke.accmod.restrictions.NoExternalUse;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Priority;
|
||||
import javax.ws.rs.Priorities;
|
||||
|
@ -48,93 +47,90 @@ import java.net.InetSocketAddress;
|
|||
import java.net.MalformedURLException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials;
|
||||
import static java.net.Proxy.NO_PROXY;
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
public class GitLabClientBuilder {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(GitLabClientBuilder.class.getName());
|
||||
@Restricted(NoExternalUse.class)
|
||||
public class ResteasyGitLabClientBuilder extends GitLabClientBuilder {
|
||||
private static final Logger LOGGER = Logger.getLogger(ResteasyGitLabClientBuilder.class.getName());
|
||||
private static final String PRIVATE_TOKEN = "PRIVATE-TOKEN";
|
||||
|
||||
public static GitLabApi buildClient(String gitlabHostUrl, final String gitlabApiTokenId, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) {
|
||||
ResteasyClientBuilder builder = new ResteasyClientBuilder();
|
||||
if (ignoreCertificateErrors) {
|
||||
builder.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY);
|
||||
builder.disableTrustManager();
|
||||
}
|
||||
ProxyConfiguration proxyConfiguration = Jenkins.getActiveInstance().proxy;
|
||||
Proxy proxy = proxyConfiguration == null ? Proxy.NO_PROXY : proxyConfiguration.createProxy(getHost(gitlabHostUrl));
|
||||
if (!proxy.equals(Proxy.NO_PROXY)) {
|
||||
InetSocketAddress address = (InetSocketAddress) proxy.address();
|
||||
builder.defaultProxy(address.getHostName().replaceFirst("^.*://", ""),
|
||||
address.getPort(),
|
||||
address.getHostName().startsWith("https") ? "https" : "http",
|
||||
proxyConfiguration.getUserName(),
|
||||
proxyConfiguration.getPassword());
|
||||
}
|
||||
|
||||
return builder
|
||||
.connectionPoolSize(60)
|
||||
.maxPooledPerRoute(30)
|
||||
.establishConnectionTimeout(connectionTimeout, TimeUnit.SECONDS)
|
||||
.socketTimeout(readTimeout, TimeUnit.SECONDS)
|
||||
.register(new JacksonJsonProvider())
|
||||
.register(new JacksonConfig())
|
||||
.register(new ApiHeaderTokenFilter(getApiToken(gitlabApiTokenId)))
|
||||
.register(new LoggingFilter())
|
||||
.register(new RemoveAcceptEncodingFilter())
|
||||
.register(new JaxrsFormProvider())
|
||||
.build().target(gitlabHostUrl)
|
||||
.proxyBuilder(GitLabApi.class)
|
||||
.classloader(GitLabApi.class.getClassLoader())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static GitLabApi buildClient(GitLabConnection connection) {
|
||||
return buildClient(connection.getUrl(),
|
||||
connection.getApiTokenId(),
|
||||
connection.isIgnoreCertificateErrors(),
|
||||
connection.getConnectionTimeout(),
|
||||
connection.getReadTimeout());
|
||||
}
|
||||
|
||||
@Initializer(before = InitMilestone.PLUGINS_STARTED)
|
||||
public static void setRuntimeDelegate() {
|
||||
RuntimeDelegate.setInstance(new ResteasyProviderFactory());
|
||||
}
|
||||
|
||||
private static String getHost(String gitlabUrl) {
|
||||
private final Class<? extends GitLabApiProxy> apiProxyClass;
|
||||
private final Function<MergeRequest, Integer> mergeRequestIdProvider;
|
||||
|
||||
ResteasyGitLabClientBuilder(String id, int ordinal, Class<? extends GitLabApiProxy> apiProxyClass, Function<MergeRequest, Integer> mergeRequestIdProvider) {
|
||||
super(id, ordinal);
|
||||
this.apiProxyClass = apiProxyClass;
|
||||
this.mergeRequestIdProvider = mergeRequestIdProvider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final GitLabClient buildClient(String url, String apiToken, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) {
|
||||
return buildClient(
|
||||
url,
|
||||
apiToken,
|
||||
Jenkins.getActiveInstance().proxy,
|
||||
ignoreCertificateErrors,
|
||||
connectionTimeout,
|
||||
readTimeout
|
||||
);
|
||||
}
|
||||
|
||||
private GitLabClient buildClient(String url, String apiToken, ProxyConfiguration httpProxyConfig, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) {
|
||||
ResteasyClientBuilder builder = new ResteasyClientBuilder();
|
||||
if (ignoreCertificateErrors) {
|
||||
builder.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY);
|
||||
builder.disableTrustManager();
|
||||
}
|
||||
|
||||
Proxy proxy = httpProxyConfig != null ? httpProxyConfig.createProxy(getHost(url)) : NO_PROXY;
|
||||
if (proxy != NO_PROXY) {
|
||||
InetSocketAddress address = (InetSocketAddress) proxy.address();
|
||||
builder.defaultProxy(address.getHostName().replaceFirst("^.*://", ""),
|
||||
address.getPort(),
|
||||
address.getHostName().startsWith("https") ? "https" : "http",
|
||||
httpProxyConfig.getUserName(),
|
||||
httpProxyConfig.getPassword());
|
||||
}
|
||||
|
||||
GitLabApiProxy apiProxy = builder
|
||||
.connectionPoolSize(60)
|
||||
.maxPooledPerRoute(30)
|
||||
.establishConnectionTimeout(connectionTimeout, TimeUnit.SECONDS)
|
||||
.socketTimeout(readTimeout, TimeUnit.SECONDS)
|
||||
.register(new JacksonJsonProvider())
|
||||
.register(new JacksonConfig())
|
||||
.register(new ApiHeaderTokenFilter(apiToken))
|
||||
.register(new LoggingFilter())
|
||||
.register(new RemoveAcceptEncodingFilter())
|
||||
.register(new JaxrsFormProvider())
|
||||
.build().target(url)
|
||||
.proxyBuilder(apiProxyClass)
|
||||
.classloader(apiProxyClass.getClassLoader())
|
||||
.build();
|
||||
return new ResteasyGitLabClient(url, apiProxy, mergeRequestIdProvider);
|
||||
}
|
||||
|
||||
private String getHost(String url) {
|
||||
try {
|
||||
return new URL(gitlabUrl).getHost();
|
||||
return new URL(url).getHost();
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getApiToken(String apiTokenId) {
|
||||
StandardCredentials credentials = CredentialsMatchers.firstOrNull(
|
||||
lookupCredentials(StandardCredentials.class, (Item) null, ACL.SYSTEM, new ArrayList<DomainRequirement>()),
|
||||
CredentialsMatchers.withId(apiTokenId));
|
||||
if (credentials != null) {
|
||||
if (credentials instanceof GitLabApiToken) {
|
||||
return ((GitLabApiToken) credentials).getApiToken().getPlainText();
|
||||
}
|
||||
if (credentials instanceof StringCredentials) {
|
||||
return ((StringCredentials) credentials).getSecret().getPlainText();
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No credentials found for credentialsId: " + apiTokenId);
|
||||
}
|
||||
|
||||
@Priority(Priorities.HEADER_DECORATOR)
|
||||
private static class ApiHeaderTokenFilter implements ClientRequestFilter {
|
||||
private final String gitlabApiToken;
|
||||
|
@ -230,9 +226,9 @@ public class GitLabClientBuilder {
|
|||
}
|
||||
|
||||
private static class ResteasyClientBuilder extends org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder {
|
||||
|
||||
private CredentialsProvider proxyCredentials;
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
ResteasyClientBuilder defaultProxy(String hostname, int port, final String scheme, String username, String password) {
|
||||
super.defaultProxy(hostname, port, scheme);
|
||||
if (username != null && password != null) {
|
||||
|
@ -242,6 +238,7 @@ public class GitLabClientBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected ClientHttpEngine initDefaultEngine() {
|
||||
ApacheHttpClient4Engine httpEngine = (ApacheHttpClient4Engine) super.initDefaultEngine();
|
|
@ -1,11 +1,7 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api;
|
||||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Branch;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Label;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Project;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.User;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
|
@ -22,23 +18,29 @@ import javax.ws.rs.QueryParam;
|
|||
import javax.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.impl.V3GitLabApiProxy.ID;
|
||||
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
@Path("/api/v3")
|
||||
public interface GitLabApi {
|
||||
@Path("/api/" + ID)
|
||||
interface V3GitLabApiProxy extends GitLabApiProxy {
|
||||
String ID = "v3";
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects")
|
||||
@Override
|
||||
Project createProject(@FormParam("name") String projectName);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/merge_requests")
|
||||
void createMergeRequest(
|
||||
@Override
|
||||
MergeRequest createMergeRequest(
|
||||
@PathParam("projectId") Integer projectId,
|
||||
@FormParam("source_branch") String sourceBranch,
|
||||
@FormParam("target_branch") String targetBranch,
|
||||
|
@ -47,24 +49,28 @@ public interface GitLabApi {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectName}")
|
||||
@Override
|
||||
Project getProject(@PathParam("projectName") String projectName);
|
||||
|
||||
@PUT
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}")
|
||||
@Override
|
||||
Project updateProject(@PathParam("projectId") String projectId,
|
||||
@FormParam("name") String name,
|
||||
@FormParam("path") String path);
|
||||
|
||||
@DELETE
|
||||
@Path("/projects/{projectId}")
|
||||
@Override
|
||||
void deleteProject(@PathParam("projectId") String projectId);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/hooks")
|
||||
@Override
|
||||
void addProjectHook(@PathParam("projectId") String projectId,
|
||||
@FormParam("url") String url,
|
||||
@FormParam("push_events") Boolean pushEvents,
|
||||
|
@ -75,6 +81,7 @@ public interface GitLabApi {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/statuses/{sha}")
|
||||
@Override
|
||||
void changeBuildStatus(@PathParam("projectId") String projectId,
|
||||
@PathParam("sha") String sha,
|
||||
@FormParam("state") BuildState state,
|
||||
|
@ -87,6 +94,7 @@ public interface GitLabApi {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/statuses/{sha}")
|
||||
@Override
|
||||
void changeBuildStatus(@PathParam("projectId") Integer projectId,
|
||||
@PathParam("sha") String sha,
|
||||
@FormParam("state") BuildState state,
|
||||
|
@ -98,6 +106,7 @@ public interface GitLabApi {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/repository/commits/{sha}")
|
||||
@Override
|
||||
void getCommit(@PathParam("projectId") String projectId, @PathParam("sha") String sha);
|
||||
|
||||
|
||||
|
@ -105,6 +114,7 @@ public interface GitLabApi {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/merge_requests/{mergeRequestId}/merge")
|
||||
@Override
|
||||
void acceptMergeRequest(@PathParam("projectId") Integer projectId,
|
||||
@PathParam("mergeRequestId") Integer mergeRequestId,
|
||||
@FormParam("merge_commit_message") String mergeCommitMessage,
|
||||
|
@ -114,6 +124,7 @@ public interface GitLabApi {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/merge_requests/{mergeRequestId}/notes")
|
||||
@Override
|
||||
void createMergeRequestNote(@PathParam("projectId") Integer projectId,
|
||||
@PathParam("mergeRequestId") Integer mergeRequestId,
|
||||
@FormParam("body") String body);
|
||||
|
@ -121,6 +132,7 @@ public interface GitLabApi {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/merge_requests")
|
||||
@Override
|
||||
List<MergeRequest> getMergeRequests(@PathParam("projectId") String projectId,
|
||||
@QueryParam("state") State state,
|
||||
@QueryParam("page") int page,
|
||||
|
@ -129,28 +141,33 @@ public interface GitLabApi {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/repository/branches")
|
||||
@Override
|
||||
List<Branch> getBranches(@PathParam("projectId") String projectId);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/repository/branches/{branch}")
|
||||
@Override
|
||||
Branch getBranch(@PathParam("projectId") String projectId,
|
||||
@PathParam("branch") String branch);
|
||||
|
||||
@HEAD
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/user")
|
||||
@Override
|
||||
void headCurrentUser();
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/user")
|
||||
@Override
|
||||
User getCurrentUser();
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/users")
|
||||
@Override
|
||||
User addUser(@FormParam("email") String email,
|
||||
@FormParam("username") String username,
|
||||
@FormParam("name") String name,
|
||||
|
@ -160,6 +177,7 @@ public interface GitLabApi {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/users/{userId}")
|
||||
@Override
|
||||
User updateUser(@PathParam("userId") String userId,
|
||||
@FormParam("email") String email,
|
||||
@FormParam("username") String username,
|
||||
|
@ -169,5 +187,12 @@ public interface GitLabApi {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/labels")
|
||||
@Override
|
||||
List<Label> getLabels(@PathParam("projectId") String projectId);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/pipelines")
|
||||
@Override
|
||||
List<Pipeline> getPipelines(@PathParam("projectId") String projectId);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.google.common.base.Function;
|
||||
import hudson.Extension;
|
||||
import org.kohsuke.accmod.Restricted;
|
||||
import org.kohsuke.accmod.restrictions.NoExternalUse;
|
||||
|
||||
|
||||
@Extension
|
||||
@Restricted(NoExternalUse.class)
|
||||
public final class V3GitLabClientBuilder extends ResteasyGitLabClientBuilder {
|
||||
private static final int ORDINAL = 2;
|
||||
private static final Function<MergeRequest, Integer> MERGE_REQUEST_ID_PROVIDER = new Function<MergeRequest, Integer>() {
|
||||
@Override
|
||||
public Integer apply(MergeRequest mergeRequest) {
|
||||
return mergeRequest.getId();
|
||||
}
|
||||
};
|
||||
|
||||
public V3GitLabClientBuilder() {
|
||||
super(V3GitLabApiProxy.ID, ORDINAL, V3GitLabApiProxy.class, MERGE_REQUEST_ID_PROVIDER);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HEAD;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.impl.V4GitLabApiProxy.ID;
|
||||
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
@Path("/api/" + ID)
|
||||
interface V4GitLabApiProxy extends GitLabApiProxy {
|
||||
String ID = "v4";
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects")
|
||||
@Override
|
||||
Project createProject(@FormParam("name") String projectName);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/merge_requests")
|
||||
@Override
|
||||
MergeRequest createMergeRequest(
|
||||
@PathParam("projectId") Integer projectId,
|
||||
@FormParam("source_branch") String sourceBranch,
|
||||
@FormParam("target_branch") String targetBranch,
|
||||
@FormParam("title") String title);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectName}")
|
||||
@Override
|
||||
Project getProject(@PathParam("projectName") String projectName);
|
||||
|
||||
@PUT
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}")
|
||||
@Override
|
||||
Project updateProject(@PathParam("projectId") String projectId,
|
||||
@FormParam("name") String name,
|
||||
@FormParam("path") String path);
|
||||
|
||||
@DELETE
|
||||
@Path("/projects/{projectId}")
|
||||
@Override
|
||||
void deleteProject(@PathParam("projectId") String projectId);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/hooks")
|
||||
@Override
|
||||
void addProjectHook(@PathParam("projectId") String projectId,
|
||||
@FormParam("url") String url,
|
||||
@FormParam("push_events") Boolean pushEvents,
|
||||
@FormParam("merge_requests_events") Boolean mergeRequestEvents,
|
||||
@FormParam("note_events") Boolean noteEvents);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/statuses/{sha}")
|
||||
@Override
|
||||
void changeBuildStatus(@PathParam("projectId") String projectId,
|
||||
@PathParam("sha") String sha,
|
||||
@FormParam("state") BuildState state,
|
||||
@FormParam("ref") String ref,
|
||||
@FormParam("context") String context,
|
||||
@FormParam("target_url") String targetUrl,
|
||||
@FormParam("description") String description);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/statuses/{sha}")
|
||||
@Override
|
||||
void changeBuildStatus(@PathParam("projectId") Integer projectId,
|
||||
@PathParam("sha") String sha,
|
||||
@FormParam("state") BuildState state,
|
||||
@FormParam("ref") String ref,
|
||||
@FormParam("context") String context,
|
||||
@FormParam("target_url") String targetUrl,
|
||||
@FormParam("description") String description);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/repository/commits/{sha}")
|
||||
@Override
|
||||
void getCommit(@PathParam("projectId") String projectId, @PathParam("sha") String sha);
|
||||
|
||||
|
||||
@PUT
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/merge_requests/{mergeRequestIid}/merge")
|
||||
@Override
|
||||
void acceptMergeRequest(@PathParam("projectId") Integer projectId,
|
||||
@PathParam("mergeRequestIid") Integer mergeRequestIid,
|
||||
@FormParam("merge_commit_message") String mergeCommitMessage,
|
||||
@FormParam("should_remove_source_branch") boolean shouldRemoveSourceBranch);
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/projects/{projectId}/merge_requests/{mergeRequestIid}/notes")
|
||||
@Override
|
||||
void createMergeRequestNote(@PathParam("projectId") Integer projectId,
|
||||
@PathParam("mergeRequestIid") Integer mergeRequestIid,
|
||||
@FormParam("body") String body);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/merge_requests")
|
||||
@Override
|
||||
List<MergeRequest> getMergeRequests(@PathParam("projectId") String projectId,
|
||||
@QueryParam("state") State state,
|
||||
@QueryParam("page") int page,
|
||||
@QueryParam("per_page") int perPage);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/repository/branches")
|
||||
@Override
|
||||
List<Branch> getBranches(@PathParam("projectId") String projectId);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/repository/branches/{branch}")
|
||||
@Override
|
||||
Branch getBranch(@PathParam("projectId") String projectId,
|
||||
@PathParam("branch") String branch);
|
||||
|
||||
@HEAD
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/user")
|
||||
@Override
|
||||
void headCurrentUser();
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/user")
|
||||
@Override
|
||||
User getCurrentUser();
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/users")
|
||||
@Override
|
||||
User addUser(@FormParam("email") String email,
|
||||
@FormParam("username") String username,
|
||||
@FormParam("name") String name,
|
||||
@FormParam("password") String password);
|
||||
|
||||
@PUT
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/users/{userId}")
|
||||
@Override
|
||||
User updateUser(@PathParam("userId") String userId,
|
||||
@FormParam("email") String email,
|
||||
@FormParam("username") String username,
|
||||
@FormParam("name") String name,
|
||||
@FormParam("password") String password);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/labels")
|
||||
@Override
|
||||
List<Label> getLabels(@PathParam("projectId") String projectId);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/projects/{projectId}/pipelines")
|
||||
@Override
|
||||
List<Pipeline> getPipelines(@PathParam("projectId") String projectId);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.google.common.base.Function;
|
||||
import hudson.Extension;
|
||||
import org.kohsuke.accmod.Restricted;
|
||||
import org.kohsuke.accmod.restrictions.NoExternalUse;
|
||||
|
||||
|
||||
@Extension
|
||||
@Restricted(NoExternalUse.class)
|
||||
public final class V4GitLabClientBuilder extends ResteasyGitLabClientBuilder {
|
||||
private static final int ORDINAL = 1;
|
||||
private static final Function<MergeRequest, Integer> MERGE_REQUEST_ID_PROVIDER = new Function<MergeRequest, Integer>() {
|
||||
@Override
|
||||
public Integer apply(MergeRequest mergeRequest) {
|
||||
return mergeRequest.getIid();
|
||||
}
|
||||
};
|
||||
|
||||
public V4GitLabClientBuilder() {
|
||||
super(V4GitLabApiProxy.ID, ORDINAL, V4GitLabApiProxy.class, MERGE_REQUEST_ID_PROVIDER);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,6 @@ import java.util.List;
|
|||
*/
|
||||
@GeneratePojoBuilder(intoPackage = "*.builder.generated", withFactoryMethod = "*")
|
||||
public class MergeRequest {
|
||||
|
||||
private Integer id;
|
||||
private Integer iid;
|
||||
private String sourceBranch;
|
||||
|
@ -33,6 +32,22 @@ public class MergeRequest {
|
|||
private Boolean mergeWhenBuildSucceeds;
|
||||
private String mergeStatus;
|
||||
|
||||
public MergeRequest() { /* default-constructor for Resteasy-based-api-proxies */ }
|
||||
|
||||
public MergeRequest(int id, int iid, String sourceBranch, String targetBranch, String title,
|
||||
int sourceProjectId, int targetProjectId,
|
||||
String description, String mergeStatus) {
|
||||
this.id = id;
|
||||
this.iid= iid;
|
||||
this.sourceBranch = sourceBranch;
|
||||
this.targetBranch = targetBranch;
|
||||
this.title = title;
|
||||
this.sourceProjectId = sourceProjectId;
|
||||
this.projectId = targetProjectId;
|
||||
this.description = description;
|
||||
this.mergeStatus = mergeStatus;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.model;
|
||||
|
||||
import net.karneim.pojobuilder.GeneratePojoBuilder;
|
||||
|
||||
@GeneratePojoBuilder(intoPackage = "*.builder.generated", withFactoryMethod = "*")
|
||||
public class Pipeline {
|
||||
private Integer id;
|
||||
private String sha;
|
||||
private String status;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSha() {
|
||||
return sha;
|
||||
}
|
||||
|
||||
public void setSha(String sha) {
|
||||
this.sha = sha;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
|
@ -4,5 +4,5 @@ package com.dabsquared.gitlabjenkins.gitlab.hook.model;
|
|||
* @author Robin Müller
|
||||
*/
|
||||
public enum Action {
|
||||
open, update
|
||||
open, update, approved
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
|
|||
public class MergeRequestHook extends WebHook {
|
||||
|
||||
private User user;
|
||||
private User assignee;
|
||||
private Project project;
|
||||
private MergeRequestObjectAttributes objectAttributes;
|
||||
|
||||
|
@ -40,7 +41,15 @@ public class MergeRequestHook extends WebHook {
|
|||
this.objectAttributes = objectAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getAssignee() {
|
||||
return assignee;
|
||||
}
|
||||
|
||||
public void setAssignee(User assignee) {
|
||||
this.assignee = assignee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
|
@ -51,6 +60,7 @@ public class MergeRequestHook extends WebHook {
|
|||
MergeRequestHook that = (MergeRequestHook) o;
|
||||
return new EqualsBuilder()
|
||||
.append(user, that.user)
|
||||
.append(assignee, that.assignee)
|
||||
.append(project, that.project)
|
||||
.append(objectAttributes, that.objectAttributes)
|
||||
.isEquals();
|
||||
|
@ -60,6 +70,7 @@ public class MergeRequestHook extends WebHook {
|
|||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(user)
|
||||
.append(assignee)
|
||||
.append(project)
|
||||
.append(objectAttributes)
|
||||
.toHashCode();
|
||||
|
@ -69,6 +80,7 @@ public class MergeRequestHook extends WebHook {
|
|||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("user", user)
|
||||
.append("assignee", assignee)
|
||||
.append("project", project)
|
||||
.append("objectAttributes", objectAttributes)
|
||||
.toString();
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.hook.model;
|
||||
|
||||
import net.karneim.pojobuilder.GeneratePojoBuilder;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
@GeneratePojoBuilder(intoPackage = "*.builder.generated", withFactoryMethod = "*")
|
||||
public class PipelineEventObjectAttributes {
|
||||
|
||||
private Integer id;
|
||||
private String ref;
|
||||
private boolean tag;
|
||||
private String sha;
|
||||
private String beforeSha;
|
||||
private String status;
|
||||
private List<String> stages;
|
||||
private Date createdAt;
|
||||
private Date finishedAt;
|
||||
private int duration;
|
||||
|
||||
public String getRef() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
public void setRef(String ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
public boolean getIsTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(boolean tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getSha() {
|
||||
return sha;
|
||||
}
|
||||
|
||||
public void setSha(String sha) {
|
||||
this.sha = sha;
|
||||
}
|
||||
|
||||
public String getBeforeSha() {
|
||||
return beforeSha;
|
||||
}
|
||||
|
||||
public void setBeforeSha(String beforeSha) {
|
||||
this.beforeSha = beforeSha;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public List<String> getStages() {
|
||||
return stages;
|
||||
}
|
||||
|
||||
public void setStages(List<String> stages) {
|
||||
this.stages = stages;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Date getFinishedAt() {
|
||||
return finishedAt;
|
||||
}
|
||||
|
||||
public void setFinishedAt(Date finishedAt) {
|
||||
this.finishedAt = finishedAt;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PipelineEventObjectAttributes that = (PipelineEventObjectAttributes) o;
|
||||
return new EqualsBuilder()
|
||||
.append(id, that.id)
|
||||
.append(ref, that.ref)
|
||||
.append(tag, that.tag)
|
||||
.append(sha, that.sha)
|
||||
.append(beforeSha, that.beforeSha)
|
||||
.append(status, that.status)
|
||||
.append(stages, that.stages)
|
||||
.append(createdAt, that.createdAt)
|
||||
.append(finishedAt, that.finishedAt)
|
||||
.append(duration, that.duration)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(id)
|
||||
.append(ref)
|
||||
.append(tag)
|
||||
.append(sha)
|
||||
.append(beforeSha)
|
||||
.append(status)
|
||||
.append(stages)
|
||||
.append(createdAt)
|
||||
.append(finishedAt)
|
||||
.append(duration)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("id", id)
|
||||
.append("ref", ref)
|
||||
.append("tag", tag)
|
||||
.append("sha", sha)
|
||||
.append("beforeSha", beforeSha)
|
||||
.append("status", status)
|
||||
.append("stages", stages)
|
||||
.append("createdAt", createdAt)
|
||||
.append("finishedAt", finishedAt)
|
||||
.append("duration", duration)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.hook.model;
|
||||
|
||||
import net.karneim.pojobuilder.GeneratePojoBuilder;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
@GeneratePojoBuilder(intoPackage = "*.builder.generated", withFactoryMethod = "*")
|
||||
public class PipelineHook extends WebHook {
|
||||
|
||||
private User user;
|
||||
public Integer projectId;
|
||||
private List<Commit> commits;
|
||||
private Project project;
|
||||
private PipelineEventObjectAttributes objectAttributes;
|
||||
|
||||
public Integer getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public void setProjectId(Integer projectId) {
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public List<Commit> getCommits() {
|
||||
return commits;
|
||||
}
|
||||
|
||||
public void setCommits(List<Commit> commits) {
|
||||
this.commits = commits;
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public void setProject(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public PipelineEventObjectAttributes getObjectAttributes() {
|
||||
return objectAttributes;
|
||||
}
|
||||
|
||||
public void setObjectAttributes(PipelineEventObjectAttributes objectAttributes) {
|
||||
this.objectAttributes = objectAttributes;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PipelineHook that = (PipelineHook) o;
|
||||
return new EqualsBuilder()
|
||||
.append(user, that.user)
|
||||
.append(project, that.project)
|
||||
.append(projectId, that.projectId)
|
||||
.append(commits, that.commits)
|
||||
.append(objectAttributes, that.objectAttributes)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(user)
|
||||
.append(projectId)
|
||||
.append(project)
|
||||
.append(commits)
|
||||
.append(objectAttributes)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("user", user)
|
||||
.append("project", project)
|
||||
.append("projectId", projectId)
|
||||
.append("objectAttributes", objectAttributes)
|
||||
.append("commits", commits)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
|
|||
@GeneratePojoBuilder(intoPackage = "*.builder.generated", withFactoryMethod = "*")
|
||||
public class Project {
|
||||
|
||||
private Integer id;
|
||||
private String name;
|
||||
private String description;
|
||||
private String webUrl;
|
||||
|
@ -120,6 +121,14 @@ public class Project {
|
|||
this.httpUrl = httpUrl;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
@ -130,6 +139,7 @@ public class Project {
|
|||
}
|
||||
Project project = (Project) o;
|
||||
return new EqualsBuilder()
|
||||
.append(id, project.id)
|
||||
.append(name, project.name)
|
||||
.append(description, project.description)
|
||||
.append(webUrl, project.webUrl)
|
||||
|
@ -148,6 +158,7 @@ public class Project {
|
|||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(id)
|
||||
.append(name)
|
||||
.append(description)
|
||||
.append(webUrl)
|
||||
|
@ -166,6 +177,7 @@ public class Project {
|
|||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("id", id)
|
||||
.append("name", name)
|
||||
.append("description", description)
|
||||
.append("webUrl", webUrl)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import hudson.Extension;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.model.Result;
|
||||
|
@ -44,14 +46,14 @@ public class GitLabAcceptMergeRequestPublisher extends MergeRequestNotifier {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void perform(Run<?, ?> build, TaskListener listener, GitLabApi client, Integer projectId, Integer mergeRequestId) {
|
||||
protected void perform(Run<?, ?> build, TaskListener listener, GitLabClient client, MergeRequest mergeRequest) {
|
||||
try {
|
||||
if (build.getResult() == Result.SUCCESS) {
|
||||
client.acceptMergeRequest(projectId, mergeRequestId, "Merge Request accepted by jenkins build success", false);
|
||||
client.acceptMergeRequest(mergeRequest, "Merge Request accepted by jenkins build success", false);
|
||||
}
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
listener.getLogger().printf("Failed to accept merge request for project '%s': %s%n", projectId, e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to accept merge request for project '%s'", projectId), e);
|
||||
listener.getLogger().printf("Failed to accept merge request for project '%s': %s%n", mergeRequest.getProjectId(), e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to accept merge request for project '%s'", mergeRequest.getProjectId()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState;
|
|||
import com.dabsquared.gitlabjenkins.util.CommitStatusUpdater;
|
||||
import hudson.Extension;
|
||||
import hudson.Launcher;
|
||||
import hudson.matrix.MatrixAggregatable;
|
||||
import hudson.matrix.MatrixAggregator;
|
||||
import hudson.matrix.MatrixBuild;
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.model.BuildListener;
|
||||
|
@ -22,7 +25,7 @@ import java.io.IOException;
|
|||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
public class GitLabCommitStatusPublisher extends Notifier {
|
||||
public class GitLabCommitStatusPublisher extends Notifier implements MatrixAggregatable {
|
||||
|
||||
private String name;
|
||||
private boolean markUnstableAsSuccess;
|
||||
|
@ -71,6 +74,16 @@ public class GitLabCommitStatusPublisher extends Notifier {
|
|||
return this;
|
||||
}
|
||||
|
||||
public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
|
||||
return new MatrixAggregator(build, launcher, listener) {
|
||||
@Override
|
||||
public boolean endBuild() throws InterruptedException, IOException {
|
||||
perform(build, launcher, listener);
|
||||
return super.endBuild();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Extension
|
||||
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import hudson.Extension;
|
||||
import hudson.Util;
|
||||
import hudson.model.AbstractProject;
|
||||
|
@ -11,6 +13,7 @@ import hudson.tasks.BuildStepDescriptor;
|
|||
import hudson.tasks.Publisher;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.kohsuke.stapler.DataBoundConstructor;
|
||||
import org.kohsuke.stapler.DataBoundSetter;
|
||||
|
||||
import javax.ws.rs.ProcessingException;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
@ -29,22 +32,30 @@ public class GitLabMessagePublisher extends MergeRequestNotifier {
|
|||
private boolean replaceSuccessNote = false;
|
||||
private boolean replaceFailureNote = false;
|
||||
private boolean replaceAbortNote = false;
|
||||
private boolean replaceUnstableNote = false;
|
||||
private String successNoteText;
|
||||
private String failureNoteText;
|
||||
private String abortNoteText;
|
||||
private String unstableNoteText;
|
||||
|
||||
@DataBoundConstructor
|
||||
public GitLabMessagePublisher(boolean onlyForFailure, boolean replaceSuccessNote, boolean replaceFailureNote, boolean replaceAbortNote,
|
||||
String successNoteText, String failureNoteText, String abortNoteText) {
|
||||
/**
|
||||
* @deprecated use {@link #GitLabMessagePublisher()} with setters to configure an instance of this class.
|
||||
*/
|
||||
@Deprecated
|
||||
public GitLabMessagePublisher(boolean onlyForFailure, boolean replaceSuccessNote, boolean replaceFailureNote, boolean replaceAbortNote, boolean replaceUnstableNote,
|
||||
String successNoteText, String failureNoteText, String abortNoteText, String unstableNoteText) {
|
||||
this.onlyForFailure = onlyForFailure;
|
||||
this.replaceSuccessNote = replaceSuccessNote;
|
||||
this.replaceFailureNote = replaceFailureNote;
|
||||
this.replaceAbortNote = replaceAbortNote;
|
||||
this.replaceUnstableNote = replaceUnstableNote;
|
||||
this.successNoteText = successNoteText;
|
||||
this.failureNoteText = failureNoteText;
|
||||
this.abortNoteText = abortNoteText;
|
||||
this.unstableNoteText = unstableNoteText;
|
||||
}
|
||||
|
||||
@DataBoundConstructor
|
||||
public GitLabMessagePublisher() { }
|
||||
|
||||
public boolean isOnlyForFailure() {
|
||||
|
@ -63,6 +74,10 @@ public class GitLabMessagePublisher extends MergeRequestNotifier {
|
|||
return replaceAbortNote;
|
||||
}
|
||||
|
||||
public boolean isReplaceUnstableNote() {
|
||||
return replaceUnstableNote;
|
||||
}
|
||||
|
||||
public String getSuccessNoteText() {
|
||||
return this.successNoteText == null ? "" : this.successNoteText;
|
||||
}
|
||||
|
@ -75,6 +90,55 @@ public class GitLabMessagePublisher extends MergeRequestNotifier {
|
|||
return this.abortNoteText == null ? "" : this.abortNoteText;
|
||||
}
|
||||
|
||||
public String getUnstableNoteText() {
|
||||
return this.unstableNoteText == null ? "" : this.unstableNoteText;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setOnlyForFailure(boolean onlyForFailure) {
|
||||
this.onlyForFailure = onlyForFailure;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setReplaceSuccessNote(boolean replaceSuccessNote) {
|
||||
this.replaceSuccessNote = replaceSuccessNote;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setReplaceFailureNote(boolean replaceFailureNote) {
|
||||
this.replaceFailureNote = replaceFailureNote;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setReplaceAbortNote(boolean replaceAbortNote) {
|
||||
this.replaceAbortNote = replaceAbortNote;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setReplaceUnstableNote(boolean replaceUnstableNote) {
|
||||
this.replaceUnstableNote = replaceUnstableNote;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setSuccessNoteText(String successNoteText) {
|
||||
this.successNoteText = successNoteText;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setFailureNoteText(String failureNoteText) {
|
||||
this.failureNoteText = failureNoteText;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setAbortNoteText(String abortNoteText) {
|
||||
this.abortNoteText = abortNoteText;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setUnstableNoteText(String unstableNoteText) {
|
||||
this.unstableNoteText = unstableNoteText;
|
||||
}
|
||||
|
||||
@Extension
|
||||
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
|
||||
|
||||
|
@ -95,14 +159,14 @@ public class GitLabMessagePublisher extends MergeRequestNotifier {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void perform(Run<?, ?> build, TaskListener listener, GitLabApi client, Integer projectId, Integer mergeRequestId) {
|
||||
protected void perform(Run<?, ?> build, TaskListener listener, GitLabClient client, MergeRequest mergeRequest) {
|
||||
try {
|
||||
if (!onlyForFailure || build.getResult() == Result.FAILURE) {
|
||||
client.createMergeRequestNote(projectId, mergeRequestId, getNote(build, listener));
|
||||
if (!onlyForFailure || build.getResult() == Result.FAILURE || build.getResult() == Result.UNSTABLE) {
|
||||
client.createMergeRequestNote(mergeRequest, getNote(build, listener));
|
||||
}
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
listener.getLogger().printf("Failed to add comment on Merge Request for project '%s': %s%n", projectId, e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to add comment on Merge Request for project '%s'", projectId), e);
|
||||
listener.getLogger().printf("Failed to add comment on Merge Request for project '%s': %s%n", mergeRequest.getProjectId(), e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to add comment on Merge Request for project '%s'", mergeRequest.getProjectId()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +175,8 @@ public class GitLabMessagePublisher extends MergeRequestNotifier {
|
|||
return ":white_check_mark:";
|
||||
} else if (result == Result.ABORTED) {
|
||||
return ":point_up:";
|
||||
} else if (result == Result.UNSTABLE) {
|
||||
return ":warning:";
|
||||
} else {
|
||||
return ":negative_squared_cross_mark:";
|
||||
}
|
||||
|
@ -151,6 +217,8 @@ public class GitLabMessagePublisher extends MergeRequestNotifier {
|
|||
message = replaceMacros(build, listener, this.getSuccessNoteText());
|
||||
} else if (this.replaceAbortNote && build.getResult() == Result.ABORTED) {
|
||||
message = replaceMacros(build, listener, this.getAbortNoteText());
|
||||
} else if (this.replaceUnstableNote && build.getResult() == Result.UNSTABLE) {
|
||||
message = replaceMacros(build, listener, this.getUnstableNoteText());
|
||||
} else if (this.replaceFailureNote && build.getResult() == Result.FAILURE) {
|
||||
message = replaceMacros(build, listener, this.getFailureNoteText());
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import hudson.Extension;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.model.Result;
|
||||
|
@ -44,12 +46,12 @@ public class GitLabVotePublisher extends MergeRequestNotifier {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void perform(Run<?, ?> build, TaskListener listener, GitLabApi client, Integer projectId, Integer mergeRequestId) {
|
||||
protected void perform(Run<?, ?> build, TaskListener listener, GitLabClient client, MergeRequest mergeRequest) {
|
||||
try {
|
||||
client.createMergeRequestNote(projectId, mergeRequestId, getResultIcon(build.getResult()));
|
||||
client.createMergeRequestNote(mergeRequest, getResultIcon(build.getResult()));
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
listener.getLogger().printf("Failed to add vote on Merge Request for project '%s': %s%n", projectId, e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to add vote on Merge Request for project '%s'", projectId), e);
|
||||
listener.getLogger().printf("Failed to add vote on Merge Request for project '%s': %s%n", mergeRequest.getProjectId(), e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to add vote on Merge Request for project '%s'", mergeRequest.getProjectId()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import hudson.Launcher;
|
||||
import hudson.matrix.MatrixAggregatable;
|
||||
import hudson.matrix.MatrixAggregator;
|
||||
import hudson.matrix.MatrixBuild;
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.Run;
|
||||
|
@ -17,35 +21,41 @@ import static com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty.g
|
|||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
public abstract class MergeRequestNotifier extends Notifier {
|
||||
public abstract class MergeRequestNotifier extends Notifier implements MatrixAggregatable {
|
||||
public BuildStepMonitor getRequiredMonitorService() {
|
||||
return BuildStepMonitor.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
|
||||
GitLabApi client = getClient(build);
|
||||
GitLabClient client = getClient(build);
|
||||
if (client == null) {
|
||||
listener.getLogger().println("No GitLab connection configured");
|
||||
return true;
|
||||
}
|
||||
Integer projectId = getProjectId(build);
|
||||
Integer mergeRequestId = getMergeRequestId(build);
|
||||
if (projectId != null && mergeRequestId != null) {
|
||||
perform(build, listener, client, projectId, mergeRequestId);
|
||||
|
||||
MergeRequest mergeRequest = getMergeRequest(build);
|
||||
if (mergeRequest != null) {
|
||||
perform(build, listener, client, mergeRequest);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void perform(Run<?, ?> build, TaskListener listener, GitLabApi client, Integer projectId, Integer mergeRequestId);
|
||||
|
||||
Integer getProjectId(Run<?, ?> build) {
|
||||
GitLabWebHookCause cause = build.getCause(GitLabWebHookCause.class);
|
||||
return cause == null ? null : cause.getData().getTargetProjectId();
|
||||
public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
|
||||
return new MatrixAggregator(build, launcher, listener) {
|
||||
@Override
|
||||
public boolean endBuild() throws InterruptedException, IOException {
|
||||
perform(build, launcher, listener);
|
||||
return super.endBuild();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Integer getMergeRequestId(Run<?, ?> build) {
|
||||
GitLabWebHookCause cause = build.getCause(GitLabWebHookCause.class);
|
||||
return cause == null ? null : cause.getData().getMergeRequestId();
|
||||
protected abstract void perform(Run<?, ?> build, TaskListener listener, GitLabClient client, MergeRequest mergeRequest);
|
||||
|
||||
MergeRequest getMergeRequest(Run<?, ?> run) {
|
||||
GitLabWebHookCause cause = run.getCause(GitLabWebHookCause.class);
|
||||
return cause == null ? null : cause.getData().getMergeRequest();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.dabsquared.gitlabjenkins.service;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Branch;
|
||||
import com.dabsquared.gitlabjenkins.util.LoggerUtil;
|
||||
import com.dabsquared.gitlabjenkins.util.ProjectIdUtil;
|
||||
|
@ -37,7 +38,7 @@ public class GitLabProjectBranchesService {
|
|||
return gitLabProjectBranchesService;
|
||||
}
|
||||
|
||||
public List<String> getBranches(GitLabApi client, String sourceRepositoryString) {
|
||||
public List<String> getBranches(GitLabClient client, String sourceRepositoryString) {
|
||||
synchronized (projectBranchCache) {
|
||||
try {
|
||||
return projectBranchCache.get(sourceRepositoryString, new BranchNamesLoader(client, sourceRepositoryString));
|
||||
|
@ -54,10 +55,10 @@ public class GitLabProjectBranchesService {
|
|||
}
|
||||
|
||||
private static class BranchNamesLoader implements Callable<List<String>> {
|
||||
private final GitLabApi client;
|
||||
private final GitLabClient client;
|
||||
private final String sourceRepository;
|
||||
|
||||
private BranchNamesLoader(GitLabApi client, String sourceRepository) {
|
||||
private BranchNamesLoader(GitLabClient client, String sourceRepository) {
|
||||
this.client = client;
|
||||
this.sourceRepository = sourceRepository;
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ public class GitLabProjectBranchesService {
|
|||
@Override
|
||||
public List<String> call() throws Exception {
|
||||
List<String> result = new ArrayList<>();
|
||||
String projectId = ProjectIdUtil.retrieveProjectId(sourceRepository);
|
||||
String projectId = ProjectIdUtil.retrieveProjectId(client, sourceRepository);
|
||||
for (Branch branch : client.getBranches(projectId)) {
|
||||
result.add(branch.getName());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.dabsquared.gitlabjenkins.service;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Label;
|
||||
import com.dabsquared.gitlabjenkins.util.LoggerUtil;
|
||||
import com.dabsquared.gitlabjenkins.util.ProjectIdUtil;
|
||||
|
@ -37,7 +38,7 @@ public class GitLabProjectLabelsService {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public List<String> getLabels(GitLabApi client, String sourceRepositoryString) {
|
||||
public List<String> getLabels(GitLabClient client, String sourceRepositoryString) {
|
||||
synchronized (projectLabelsCache) {
|
||||
try {
|
||||
return projectLabelsCache.get(sourceRepositoryString, new LabelNamesLoader(client, sourceRepositoryString));
|
||||
|
@ -54,10 +55,10 @@ public class GitLabProjectLabelsService {
|
|||
}
|
||||
|
||||
private static class LabelNamesLoader implements Callable<List<String>> {
|
||||
private final GitLabApi client;
|
||||
private final GitLabClient client;
|
||||
private final String sourceRepository;
|
||||
|
||||
private LabelNamesLoader(GitLabApi client, String sourceRepository) {
|
||||
private LabelNamesLoader(GitLabClient client, String sourceRepository) {
|
||||
this.client = client;
|
||||
this.sourceRepository = sourceRepository;
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ public class GitLabProjectLabelsService {
|
|||
@Override
|
||||
public List<String> call() throws Exception {
|
||||
List<String> result = new ArrayList<>();
|
||||
String projectId = ProjectIdUtil.retrieveProjectId(sourceRepository);
|
||||
String projectId = ProjectIdUtil.retrieveProjectId(client, sourceRepository);
|
||||
for (Label label : client.getLabels(projectId)) {
|
||||
result.add(label.getName());
|
||||
}
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.filter;
|
||||
|
||||
import org.kohsuke.stapler.DataBoundConstructor;
|
||||
import org.kohsuke.stapler.DataBoundSetter;
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
public class MergeRequestLabelFilterConfig {
|
||||
|
||||
private final String include;
|
||||
private final String exclude;
|
||||
private String include;
|
||||
private String exclude;
|
||||
|
||||
@DataBoundConstructor
|
||||
/**
|
||||
* @deprecated use {@link #MergeRequestLabelFilterConfig()} with setters to configure an instance of this class.
|
||||
*/
|
||||
@Deprecated
|
||||
public MergeRequestLabelFilterConfig(String include, String exclude) {
|
||||
this.include = include;
|
||||
this.exclude = exclude;
|
||||
}
|
||||
|
||||
@DataBoundConstructor
|
||||
public MergeRequestLabelFilterConfig() { }
|
||||
|
||||
public String getInclude() {
|
||||
return include;
|
||||
}
|
||||
|
@ -23,4 +30,14 @@ public class MergeRequestLabelFilterConfig {
|
|||
public String getExclude() {
|
||||
return exclude;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setInclude(String include) {
|
||||
this.include = include;
|
||||
}
|
||||
|
||||
@DataBoundSetter
|
||||
public void setExclude(String exclude) {
|
||||
this.exclude = exclude;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.google.common.base.Splitter;
|
|||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -49,6 +50,9 @@ class NameBasedFilter implements BranchFilter {
|
|||
}
|
||||
|
||||
private List<String> convert(String commaSeparatedString) {
|
||||
if (commaSeparatedString == null)
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
ArrayList<String> result = new ArrayList<>();
|
||||
for (String s : Splitter.on(',').omitEmptyStrings().trimResults().split(commaSeparatedString)) {
|
||||
result.add(s);
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.dabsquared.gitlabjenkins.trigger.handler;
|
|||
import com.dabsquared.gitlabjenkins.cause.CauseData;
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.WebHook;
|
||||
import com.dabsquared.gitlabjenkins.publisher.GitLabCommitStatusPublisher;
|
||||
|
@ -63,7 +63,7 @@ public abstract class AbstractWebHookTriggerHandler<H extends WebHook> implement
|
|||
if (job instanceof AbstractProject && ((AbstractProject) job).getPublishersList().get(GitLabCommitStatusPublisher.class) != null) {
|
||||
GitLabCommitStatusPublisher publisher =
|
||||
(GitLabCommitStatusPublisher) ((AbstractProject) job).getPublishersList().get(GitLabCommitStatusPublisher.class);
|
||||
GitLabApi client = job.getProperty(GitLabConnectionProperty.class).getClient();
|
||||
GitLabClient client = job.getProperty(GitLabConnectionProperty.class).getClient();
|
||||
BuildStatusUpdate buildStatusUpdate = retrieveBuildStatusUpdate(hook);
|
||||
try {
|
||||
if (client == null) {
|
||||
|
@ -72,7 +72,7 @@ public abstract class AbstractWebHookTriggerHandler<H extends WebHook> implement
|
|||
String targetUrl =
|
||||
Jenkins.getInstance().getRootUrl() + job.getUrl() + job.getNextBuildNumber() + "/";
|
||||
client.changeBuildStatus(buildStatusUpdate.getProjectId(), buildStatusUpdate.getSha(),
|
||||
BuildState.pending, buildStatusUpdate.getRef(), publisher.getName(), targetUrl, null);
|
||||
BuildState.pending, buildStatusUpdate.getRef(), publisher.getName(), targetUrl, BuildState.pending.name());
|
||||
}
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to set build state to pending", e);
|
||||
|
@ -80,7 +80,7 @@ public abstract class AbstractWebHookTriggerHandler<H extends WebHook> implement
|
|||
}
|
||||
}
|
||||
|
||||
private Action[] createActions(Job<?, ?> job, H hook) {
|
||||
protected Action[] createActions(Job<?, ?> job, H hook) {
|
||||
ArrayList<Action> actions = new ArrayList<>();
|
||||
actions.add(new CauseAction(new GitLabWebHookCause(retrieveCauseData(hook))));
|
||||
try {
|
||||
|
@ -113,7 +113,7 @@ public abstract class AbstractWebHookTriggerHandler<H extends WebHook> implement
|
|||
return null;
|
||||
}
|
||||
|
||||
private void scheduleBuild(Job<?, ?> job, Action[] actions) {
|
||||
protected void scheduleBuild(Job<?, ?> job, Action[] actions) {
|
||||
int projectBuildDelay = 0;
|
||||
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
|
||||
ParameterizedJobMixIn.ParameterizedJob abstractProject = (ParameterizedJobMixIn.ParameterizedJob) job;
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.merge;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.Action;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
import com.dabsquared.gitlabjenkins.trigger.TriggerOpenMergeRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
|
@ -14,25 +17,46 @@ public final class MergeRequestHookTriggerHandlerFactory {
|
|||
private MergeRequestHookTriggerHandlerFactory() {}
|
||||
|
||||
public static MergeRequestHookTriggerHandler newMergeRequestHookTriggerHandler(boolean triggerOnMergeRequest,
|
||||
boolean triggerOnAcceptedMergeRequest,
|
||||
boolean triggerOnClosedMergeRequest,
|
||||
TriggerOpenMergeRequest triggerOpenMergeRequest,
|
||||
boolean skipWorkInProgressMergeRequest) {
|
||||
if (triggerOnMergeRequest || triggerOpenMergeRequest != TriggerOpenMergeRequest.never) {
|
||||
return new MergeRequestHookTriggerHandlerImpl(retrieveAllowedStates(triggerOnMergeRequest, triggerOpenMergeRequest),
|
||||
boolean skipWorkInProgressMergeRequest,
|
||||
boolean triggerOnApprovedMergeRequest) {
|
||||
if (triggerOnMergeRequest || triggerOnAcceptedMergeRequest || triggerOnClosedMergeRequest || triggerOpenMergeRequest != TriggerOpenMergeRequest.never || triggerOnApprovedMergeRequest) {
|
||||
return new MergeRequestHookTriggerHandlerImpl(retrieveAllowedStates(triggerOnMergeRequest, triggerOnAcceptedMergeRequest, triggerOnClosedMergeRequest, triggerOpenMergeRequest),
|
||||
retrieveAllowedActions(triggerOnApprovedMergeRequest),
|
||||
skipWorkInProgressMergeRequest);
|
||||
} else {
|
||||
return new NopMergeRequestHookTriggerHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private static List<State> retrieveAllowedStates(boolean triggerOnMergeRequest, TriggerOpenMergeRequest triggerOpenMergeRequest) {
|
||||
private static Set<Action> retrieveAllowedActions(boolean triggerOnApprovedMergeRequest) {
|
||||
Set<Action> allowedActions = EnumSet.noneOf(Action.class);
|
||||
if (triggerOnApprovedMergeRequest)
|
||||
allowedActions.add(Action.approved);
|
||||
return allowedActions;
|
||||
}
|
||||
|
||||
private static List<State> retrieveAllowedStates(boolean triggerOnMergeRequest,
|
||||
boolean triggerOnAcceptedMergeRequest,
|
||||
boolean triggerOnClosedMergeRequest,
|
||||
TriggerOpenMergeRequest triggerOpenMergeRequest) {
|
||||
List<State> result = new ArrayList<>();
|
||||
if (triggerOnMergeRequest) {
|
||||
result.add(State.opened);
|
||||
result.add(State.reopened);
|
||||
}
|
||||
if (triggerOnAcceptedMergeRequest) {
|
||||
result.add(State.merged);
|
||||
}
|
||||
if (triggerOnClosedMergeRequest) {
|
||||
result.add(State.closed);
|
||||
}
|
||||
if (triggerOpenMergeRequest != TriggerOpenMergeRequest.never) {
|
||||
result.add(State.updated);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.dabsquared.gitlabjenkins.trigger.handler.merge;
|
|||
|
||||
import com.dabsquared.gitlabjenkins.cause.CauseData;
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.Action;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.MergeRequestHook;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.MergeRequestObjectAttributes;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
@ -16,7 +17,8 @@ import hudson.plugins.git.GitSCM;
|
|||
import hudson.plugins.git.RevisionParameterAction;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -31,18 +33,24 @@ class MergeRequestHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<M
|
|||
|
||||
private static final Logger LOGGER = Logger.getLogger(MergeRequestHookTriggerHandlerImpl.class.getName());
|
||||
|
||||
private final List<State> allowedStates;
|
||||
private final Collection<State> allowedStates;
|
||||
private final boolean skipWorkInProgressMergeRequest;
|
||||
private final Collection<Action> allowedActions;
|
||||
|
||||
MergeRequestHookTriggerHandlerImpl(List<State> allowedStates, boolean skipWorkInProgressMergeRequest) {
|
||||
MergeRequestHookTriggerHandlerImpl(Collection<State> allowedStates, boolean skipWorkInProgressMergeRequest) {
|
||||
this(allowedStates, EnumSet.noneOf(Action.class),skipWorkInProgressMergeRequest);
|
||||
}
|
||||
|
||||
MergeRequestHookTriggerHandlerImpl(Collection<State> allowedStates, Collection<Action> allowedActions, boolean skipWorkInProgressMergeRequest) {
|
||||
this.allowedStates = allowedStates;
|
||||
this.allowedActions = allowedActions;
|
||||
this.skipWorkInProgressMergeRequest = skipWorkInProgressMergeRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Job<?, ?> job, MergeRequestHook hook, boolean ciSkip, BranchFilter branchFilter, MergeRequestLabelFilter mergeRequestLabelFilter) {
|
||||
MergeRequestObjectAttributes objectAttributes = hook.getObjectAttributes();
|
||||
if (allowedStates.contains(objectAttributes.getState())
|
||||
if (isAllowedByConfig(objectAttributes)
|
||||
&& isLastCommitNotYetBuild(job, hook)
|
||||
&& isNotSkipWorkInProgressMergeRequest(objectAttributes)
|
||||
&& mergeRequestLabelFilter.isMergeRequestAllowed(hook.getObjectAttributes().getLabels())) {
|
||||
|
@ -87,6 +95,10 @@ class MergeRequestHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<M
|
|||
.withMergeRequestDescription(hook.getObjectAttributes().getDescription())
|
||||
.withMergeRequestId(hook.getObjectAttributes().getId())
|
||||
.withMergeRequestIid(hook.getObjectAttributes().getIid())
|
||||
.withMergeRequestState(hook.getObjectAttributes().getState().toString())
|
||||
.withMergedByUser(hook.getUser() == null ? null : hook.getUser().getUsername())
|
||||
.withMergeRequestAssignee(hook.getAssignee() == null ? null : hook.getAssignee().getUsername())
|
||||
.withMergeRequestTargetProjectId(hook.getObjectAttributes().getTargetProjectId())
|
||||
.withTargetBranch(hook.getObjectAttributes().getTargetBranch())
|
||||
.withTargetRepoName(hook.getObjectAttributes().getTarget().getName())
|
||||
.withTargetNamespace(hook.getObjectAttributes().getTarget().getNamespace())
|
||||
|
@ -125,6 +137,11 @@ class MergeRequestHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<M
|
|||
|
||||
private boolean isLastCommitNotYetBuild(Job<?, ?> project, MergeRequestHook hook) {
|
||||
MergeRequestObjectAttributes objectAttributes = hook.getObjectAttributes();
|
||||
if (objectAttributes.getAction() == Action.approved) {
|
||||
LOGGER.log(Level.FINEST, "Skipping LastCommitNotYetBuild check for approve action");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (objectAttributes != null && objectAttributes.getLastCommit() != null) {
|
||||
Run<?, ?> mergeBuild = BuildUtil.getBuildBySHA1IncludingMergeBuilds(project, objectAttributes.getLastCommit().getId());
|
||||
if (mergeBuild != null && StringUtils.equals(getTargetBranchFromBuild(mergeBuild), objectAttributes.getTargetBranch())) {
|
||||
|
@ -140,6 +157,11 @@ class MergeRequestHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<M
|
|||
return cause == null ? null : cause.getData().getTargetBranch();
|
||||
}
|
||||
|
||||
private boolean isAllowedByConfig(MergeRequestObjectAttributes objectAttributes) {
|
||||
return allowedStates.contains(objectAttributes.getState())
|
||||
|| allowedActions.contains(objectAttributes.getAction());
|
||||
}
|
||||
|
||||
private boolean isNotSkipWorkInProgressMergeRequest(MergeRequestObjectAttributes objectAttributes) {
|
||||
Boolean workInProgress = objectAttributes.getWorkInProgress();
|
||||
if (skipWorkInProgressMergeRequest && workInProgress != null && workInProgress) {
|
||||
|
|
|
@ -75,6 +75,7 @@ class NoteHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<NoteHook>
|
|||
.withMergeRequestDescription(hook.getMergeRequest().getDescription())
|
||||
.withMergeRequestId(hook.getMergeRequest().getId())
|
||||
.withMergeRequestIid(hook.getMergeRequest().getIid())
|
||||
.withMergeRequestTargetProjectId(hook.getMergeRequest().getTargetProjectId())
|
||||
.withTargetBranch(hook.getMergeRequest().getTargetBranch())
|
||||
.withTargetRepoName(hook.getMergeRequest().getTarget().getName())
|
||||
.withTargetNamespace(hook.getMergeRequest().getTarget().getNamespace())
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.pipeline;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PipelineHook;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PushHook;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilter;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.MergeRequestLabelFilter;
|
||||
import com.dabsquared.gitlabjenkins.trigger.handler.push.PushHookTriggerHandler;
|
||||
import hudson.model.Job;
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
class NopPipelineHookTriggerHandler implements PipelineHookTriggerHandler {
|
||||
|
||||
@Override
|
||||
public void handle(Job<?, ?> job, PipelineHook hook, boolean ciSkip, BranchFilter branchFilter, MergeRequestLabelFilter mergeRequestLabelFilter) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.pipeline;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PipelineHook;
|
||||
import com.dabsquared.gitlabjenkins.trigger.handler.WebHookTriggerHandler;
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
public interface PipelineHookTriggerHandler extends WebHookTriggerHandler<PipelineHook> { }
|
|
@ -0,0 +1,34 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.pipeline;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
public final class PipelineHookTriggerHandlerFactory {
|
||||
|
||||
public static final String SUCCESS = "success";
|
||||
|
||||
private PipelineHookTriggerHandlerFactory() {
|
||||
}
|
||||
|
||||
public static PipelineHookTriggerHandler newPipelineHookTriggerHandler(boolean triggerOnPipelineEvent) {
|
||||
if (triggerOnPipelineEvent) {
|
||||
return new PipelineHookTriggerHandlerImpl(retrieve(triggerOnPipelineEvent));
|
||||
} else {
|
||||
return new NopPipelineHookTriggerHandler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static List<String> retrieve(boolean triggerOnPipelineEvent) {
|
||||
List<String> result = new ArrayList<>();
|
||||
if (triggerOnPipelineEvent) {
|
||||
result.add(SUCCESS);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.pipeline;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.cause.CauseData;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PipelineEventObjectAttributes;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PipelineHook;
|
||||
import com.dabsquared.gitlabjenkins.trigger.exception.NoRevisionToBuildException;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilter;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.MergeRequestLabelFilter;
|
||||
import com.dabsquared.gitlabjenkins.trigger.handler.AbstractWebHookTriggerHandler;
|
||||
import com.dabsquared.gitlabjenkins.util.BuildUtil;
|
||||
import com.dabsquared.gitlabjenkins.util.LoggerUtil;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.model.Job;
|
||||
import hudson.model.Run;
|
||||
import hudson.plugins.git.GitSCM;
|
||||
import hudson.plugins.git.RevisionParameterAction;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.cause.CauseDataBuilder.causeData;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.handler.builder.generated.BuildStatusUpdateBuilder.buildStatusUpdate;
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
class PipelineHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<PipelineHook> implements PipelineHookTriggerHandler {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(PipelineHookTriggerHandlerImpl.class.getName());
|
||||
|
||||
private final List<String> allowedStates;
|
||||
|
||||
PipelineHookTriggerHandlerImpl(List<String> allowedStates) {
|
||||
this.allowedStates = allowedStates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Job<?, ?> job, PipelineHook hook, boolean ciSkip, BranchFilter branchFilter, MergeRequestLabelFilter mergeRequestLabelFilter) {
|
||||
PipelineEventObjectAttributes objectAttributes = hook.getObjectAttributes();
|
||||
try {
|
||||
if (job instanceof AbstractProject<?, ?>) {
|
||||
GitLabConnectionProperty property = job.getProperty(GitLabConnectionProperty.class);
|
||||
|
||||
if (property != null && property.getClient() != null) {
|
||||
GitLabClient client = property.getClient();
|
||||
com.dabsquared.gitlabjenkins.gitlab.api.model.Project projectForName = client.getProject(hook.getProject().getPathWithNamespace());
|
||||
hook.setProjectId(projectForName.getId());
|
||||
}
|
||||
}
|
||||
} catch (WebApplicationException e) {
|
||||
LOGGER.log(Level.WARNING, "Failed to communicate with gitlab server to determine project id: " + e.getMessage(), e);
|
||||
}
|
||||
if (allowedStates.contains(objectAttributes.getStatus()) && !isLastAlreadyBuild(job,hook)) {
|
||||
if (ciSkip && isCiSkip(hook)) {
|
||||
LOGGER.log(Level.INFO, "Skipping due to ci-skip.");
|
||||
return;
|
||||
}
|
||||
//we do not call super here, since we do not want the status to be changed
|
||||
//in case of pipeline events that could lead to a deadlock
|
||||
String targetBranch = getTargetBranch(hook);
|
||||
if (branchFilter.isBranchAllowed(targetBranch)) {
|
||||
LOGGER.log(Level.INFO, "{0} triggered for {1}.", LoggerUtil.toArray(job.getFullName(), getTriggerType()));
|
||||
|
||||
super.scheduleBuild(job, createActions(job, hook));
|
||||
} else {
|
||||
LOGGER.log(Level.INFO, "branch {0} is not allowed", targetBranch);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCiSkip(PipelineHook hook) {
|
||||
//we don't get a commit message or suchlike that could contain ci-skip
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTargetBranch(PipelineHook hook) {
|
||||
return hook.getObjectAttributes().getRef() == null ? null : hook.getObjectAttributes().getRef().replaceFirst("^refs/heads/", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTriggerType() {
|
||||
return "pipeline event";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CauseData retrieveCauseData(PipelineHook hook) {
|
||||
return causeData()
|
||||
.withActionType(CauseData.ActionType.PIPELINE)
|
||||
.withSourceProjectId(hook.getProjectId())
|
||||
.withBranch(getTargetBranch(hook)==null?"":getTargetBranch(hook))
|
||||
.withSourceBranch(getTargetBranch(hook)==null?"":getTargetBranch(hook))
|
||||
.withUserName(hook.getUser()==null||hook.getUser().getName()==null?"":hook.getUser().getName())
|
||||
.withSourceRepoName(hook.getRepository()==null||hook.getRepository().getName()==null?"":hook.getRepository().getName())
|
||||
.withSourceNamespace(hook.getProject()==null||hook.getProject().getNamespace()==null?"":hook.getProject().getNamespace())
|
||||
.withSourceRepoSshUrl(hook.getRepository()==null||hook.getRepository().getGitSshUrl()==null?"":hook.getRepository().getGitSshUrl())
|
||||
.withSourceRepoHttpUrl(hook.getRepository()==null||hook.getRepository()==null?"":hook.getRepository().getGitHttpUrl())
|
||||
.withMergeRequestTitle("")
|
||||
.withTargetProjectId(hook.getProjectId())
|
||||
.withTargetBranch(getTargetBranch(hook)==null?"":getTargetBranch(hook))
|
||||
.withTargetRepoName("")
|
||||
.withTargetNamespace("")
|
||||
.withTargetRepoSshUrl("")
|
||||
.withTargetRepoHttpUrl("")
|
||||
.withLastCommit(hook.getObjectAttributes().getSha())
|
||||
.withTriggeredByUser(hook.getUser()==null||hook.getUser().getName()==null?"":hook.getUser().getName())
|
||||
.withRef(hook.getObjectAttributes().getRef()==null?"":hook.getObjectAttributes().getRef())
|
||||
.withSha(hook.getObjectAttributes().getSha()==null?"":hook.getObjectAttributes().getSha())
|
||||
.withBeforeSha(hook.getObjectAttributes().getBeforeSha()==null?"":hook.getObjectAttributes().getBeforeSha())
|
||||
.withStatus(hook.getObjectAttributes().getStatus()==null?"":hook.getObjectAttributes().getStatus().toString())
|
||||
.withStages(hook.getObjectAttributes().getStages()==null?"":hook.getObjectAttributes().getStages().toString())
|
||||
.withCreatedAt(hook.getObjectAttributes().getCreatedAt()==null?"":hook.getObjectAttributes().getCreatedAt().toString())
|
||||
.withFinishedAt(hook.getObjectAttributes().getFinishedAt()==null?"":hook.getObjectAttributes().getFinishedAt().toString())
|
||||
.withBuildDuration(String.valueOf(hook.getObjectAttributes().getDuration()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RevisionParameterAction createRevisionParameter(PipelineHook hook, GitSCM gitSCM) throws NoRevisionToBuildException {
|
||||
return new RevisionParameterAction(retrieveRevisionToBuild(hook), retrieveUrIish(hook));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BuildStatusUpdate retrieveBuildStatusUpdate(PipelineHook hook) {
|
||||
return buildStatusUpdate()
|
||||
.withProjectId(hook.getProjectId())
|
||||
.withSha(hook.getObjectAttributes().getSha())
|
||||
.withRef(hook.getObjectAttributes().getRef())
|
||||
.build();
|
||||
}
|
||||
|
||||
private String retrieveRevisionToBuild(PipelineHook hook) throws NoRevisionToBuildException {
|
||||
if (hook.getObjectAttributes() != null
|
||||
&& hook.getObjectAttributes().getSha() != null) {
|
||||
return hook.getObjectAttributes().getSha();
|
||||
} else {
|
||||
throw new NoRevisionToBuildException();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLastAlreadyBuild(Job<?, ?> project, PipelineHook hook) {
|
||||
PipelineEventObjectAttributes objectAttributes = hook.getObjectAttributes();
|
||||
if (objectAttributes != null && objectAttributes.getSha() != null) {
|
||||
Run<?, ?> lastBuild = BuildUtil.getBuildBySHA1IncludingMergeBuilds(project, objectAttributes.getSha());
|
||||
if (lastBuild != null) {
|
||||
LOGGER.log(Level.INFO, "Last commit has already been built in build #" + lastBuild.getNumber());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.push;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.GitLabPushTrigger;
|
||||
import com.dabsquared.gitlabjenkins.cause.CauseData;
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Branch;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
|
@ -20,8 +21,10 @@ import hudson.model.Action;
|
|||
import hudson.model.CauseAction;
|
||||
import hudson.model.Job;
|
||||
import hudson.plugins.git.RevisionParameterAction;
|
||||
import hudson.triggers.Trigger;
|
||||
import jenkins.model.Jenkins;
|
||||
import jenkins.model.ParameterizedJobMixIn;
|
||||
import jenkins.model.ParameterizedJobMixIn.ParameterizedJob;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
|
||||
import javax.ws.rs.ProcessingException;
|
||||
|
@ -51,27 +54,34 @@ class OpenMergeRequestPushHookTriggerHandler implements PushHookTriggerHandler {
|
|||
|
||||
@Override
|
||||
public void handle(Job<?, ?> job, PushHook hook, boolean ciSkip, BranchFilter branchFilter, MergeRequestLabelFilter mergeRequestLabelFilter) {
|
||||
try {
|
||||
if (job instanceof AbstractProject<?, ?>) {
|
||||
AbstractProject<?, ?> project = (AbstractProject<?, ?>) job;
|
||||
try {
|
||||
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
|
||||
ParameterizedJob project = (ParameterizedJobMixIn.ParameterizedJob) job;
|
||||
GitLabConnectionProperty property = job.getProperty(GitLabConnectionProperty.class);
|
||||
final GitLabPushTrigger trigger = project.getTrigger(GitLabPushTrigger.class);
|
||||
Integer projectId = hook.getProjectId();
|
||||
if (property != null && property.getClient() != null && projectId != null && trigger != null) {
|
||||
GitLabApi client = property.getClient();
|
||||
for (MergeRequest mergeRequest : getOpenMergeRequests(client, projectId.toString())) {
|
||||
if (mergeRequestLabelFilter.isMergeRequestAllowed(mergeRequest.getLabels())) {
|
||||
handleMergeRequest(job, hook, ciSkip, branchFilter, client, mergeRequest);
|
||||
for (Trigger t : project.getTriggers().values()) {
|
||||
if (t instanceof GitLabPushTrigger) {
|
||||
final GitLabPushTrigger trigger = (GitLabPushTrigger) t;
|
||||
Integer projectId = hook.getProjectId();
|
||||
if (property != null && property.getClient() != null && projectId != null && trigger != null) {
|
||||
GitLabClient client = property.getClient();
|
||||
for (MergeRequest mergeRequest : getOpenMergeRequests(client, projectId.toString())) {
|
||||
if (mergeRequestLabelFilter.isMergeRequestAllowed(mergeRequest.getLabels())) {
|
||||
handleMergeRequest(job, hook, ciSkip, branchFilter, client, mergeRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
LOGGER.log(Level.FINE, "Not a ParameterizedJob: {0}",LoggerUtil.toArray(job.getClass().getName()));
|
||||
}
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
LOGGER.log(Level.WARNING, "Failed to communicate with gitlab server to determine if this is an update for a merge request: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<MergeRequest> getOpenMergeRequests(GitLabApi client, String projectId) {
|
||||
private List<MergeRequest> getOpenMergeRequests(GitLabClient client, String projectId) {
|
||||
List<MergeRequest> result = new ArrayList<>();
|
||||
Integer page = 1;
|
||||
do {
|
||||
|
@ -82,7 +92,7 @@ class OpenMergeRequestPushHookTriggerHandler implements PushHookTriggerHandler {
|
|||
return result;
|
||||
}
|
||||
|
||||
private void handleMergeRequest(Job<?, ?> job, PushHook hook, boolean ciSkip, BranchFilter branchFilter, GitLabApi client, MergeRequest mergeRequest) {
|
||||
private void handleMergeRequest(Job<?, ?> job, PushHook hook, boolean ciSkip, BranchFilter branchFilter, GitLabClient client, MergeRequest mergeRequest) {
|
||||
if (ciSkip && mergeRequest.getDescription() != null && mergeRequest.getDescription().contains("[ci-skip]")) {
|
||||
LOGGER.log(Level.INFO, "Skipping MR " + mergeRequest.getTitle() + " due to ci-skip.");
|
||||
return;
|
||||
|
@ -96,7 +106,7 @@ class OpenMergeRequestPushHookTriggerHandler implements PushHookTriggerHandler {
|
|||
|
||||
String targetBranch = mergeRequest.getTargetBranch();
|
||||
String sourceBranch = mergeRequest.getSourceBranch();
|
||||
if (targetBranch != null && branchFilter.isBranchAllowed(targetBranch) && hook.getRef().endsWith(targetBranch) && sourceBranch != null) {
|
||||
if (targetBranch != null && branchFilter.isBranchAllowed(targetBranch) && hook.getRef().equals("refs/heads/"+targetBranch) && sourceBranch != null) {
|
||||
LOGGER.log(Level.INFO, "{0} triggered for push to target branch of open merge request #{1}.",
|
||||
LoggerUtil.toArray(job.getFullName(), mergeRequest.getId()));
|
||||
|
||||
|
@ -130,6 +140,7 @@ class OpenMergeRequestPushHookTriggerHandler implements PushHookTriggerHandler {
|
|||
.withMergeRequestDescription(mergeRequest.getDescription())
|
||||
.withMergeRequestId(mergeRequest.getId())
|
||||
.withMergeRequestIid(mergeRequest.getIid())
|
||||
.withMergeRequestTargetProjectId(mergeRequest.getTargetProjectId())
|
||||
.withTargetBranch(mergeRequest.getTargetBranch())
|
||||
.withTargetRepoName(hook.getRepository().getName())
|
||||
.withTargetNamespace(hook.getProject().getNamespace())
|
||||
|
@ -145,10 +156,10 @@ class OpenMergeRequestPushHookTriggerHandler implements PushHookTriggerHandler {
|
|||
if (job instanceof AbstractProject && ((AbstractProject) job).getPublishersList().get(GitLabCommitStatusPublisher.class) != null) {
|
||||
GitLabCommitStatusPublisher publisher =
|
||||
(GitLabCommitStatusPublisher) ((AbstractProject) job).getPublishersList().get(GitLabCommitStatusPublisher.class);
|
||||
GitLabApi client = job.getProperty(GitLabConnectionProperty.class).getClient();
|
||||
GitLabClient client = job.getProperty(GitLabConnectionProperty.class).getClient();
|
||||
try {
|
||||
String targetUrl = Jenkins.getInstance().getRootUrl() + job.getUrl() + job.getNextBuildNumber() + "/";
|
||||
client.changeBuildStatus(projectId, commit, BuildState.pending, ref, publisher.getName(), targetUrl, null);
|
||||
client.changeBuildStatus(projectId, commit, BuildState.pending, ref, publisher.getName(), targetUrl, BuildState.pending.name());
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to set build state to pending", e);
|
||||
}
|
||||
|
|
|
@ -42,8 +42,9 @@ class PushHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<PushHook>
|
|||
|
||||
@Override
|
||||
protected CauseData retrieveCauseData(PushHook hook) {
|
||||
CauseData.ActionType actionType = hook.getObjectKind().equals("tag_push") ? CauseData.ActionType.TAG_PUSH : CauseData.ActionType.PUSH;
|
||||
return causeData()
|
||||
.withActionType(CauseData.ActionType.PUSH)
|
||||
.withActionType(actionType)
|
||||
.withSourceProjectId(hook.getProjectId())
|
||||
.withTargetProjectId(hook.getProjectId())
|
||||
.withBranch(getTargetBranch(hook))
|
||||
|
@ -60,6 +61,10 @@ class PushHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<PushHook>
|
|||
.withMergeRequestDescription("")
|
||||
.withMergeRequestId(null)
|
||||
.withMergeRequestIid(null)
|
||||
.withMergeRequestState(null)
|
||||
.withMergedByUser("")
|
||||
.withMergeRequestAssignee("")
|
||||
.withMergeRequestTargetProjectId(null)
|
||||
.withTargetBranch(getTargetBranch(hook))
|
||||
.withTargetRepoName("")
|
||||
.withTargetNamespace("")
|
||||
|
|
|
@ -14,7 +14,7 @@ public class BuildUtil {
|
|||
for (Run<?, ?> build : project.getBuilds()) {
|
||||
BuildData data = build.getAction(BuildData.class);
|
||||
MergeRecord merge = build.getAction(MergeRecord.class);
|
||||
if (hasLastBuild(data) && isNoMergeBuild(data, merge)) {
|
||||
if (hasLastBuild(data) && isNoMergeBuild(data, merge)) {
|
||||
for (Branch branch : data.lastBuild.getRevision().getBranches()) {
|
||||
if (branch.getName().endsWith("/" + branchName)) {
|
||||
return build;
|
||||
|
@ -27,10 +27,11 @@ public class BuildUtil {
|
|||
|
||||
public static Run<?, ?> getBuildBySHA1WithoutMergeBuilds(Job<?, ?> project, String sha1) {
|
||||
for (Run<?, ?> build : project.getBuilds()) {
|
||||
BuildData data = build.getAction(BuildData.class);
|
||||
MergeRecord merge = build.getAction(MergeRecord.class);
|
||||
if (hasLastBuild(data) && isNoMergeBuild(data, merge) && data.lastBuild.isFor(sha1)) {
|
||||
return build;
|
||||
for(BuildData data : build.getActions(BuildData.class)) {
|
||||
if (hasLastBuild(data) && isNoMergeBuild(data, merge) && data.lastBuild.isFor(sha1)) {
|
||||
return build;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -38,12 +39,13 @@ public class BuildUtil {
|
|||
|
||||
public static Run<?, ?> getBuildBySHA1IncludingMergeBuilds(Job<?, ?> project, String sha1) {
|
||||
for (Run<?, ?> build : project.getBuilds()) {
|
||||
BuildData data = build.getAction(BuildData.class);
|
||||
if (data != null
|
||||
&& data.lastBuild != null
|
||||
&& data.lastBuild.getMarked() != null
|
||||
&& data.lastBuild.getMarked().getSha1String().equals(sha1)) {
|
||||
return build;
|
||||
for(BuildData data : build.getActions(BuildData.class)) {
|
||||
if (data != null
|
||||
&& data.lastBuild != null
|
||||
&& data.lastBuild.getMarked() != null
|
||||
&& data.lastBuild.getMarked().getSha1String().equals(sha1)) {
|
||||
return build;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
package com.dabsquared.gitlabjenkins.util;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState;
|
||||
import hudson.EnvVars;
|
||||
import hudson.model.Cause;
|
||||
import hudson.model.Run;
|
||||
import hudson.model.TaskListener;
|
||||
import hudson.model.Cause.UpstreamCause;
|
||||
import hudson.plugins.git.Revision;
|
||||
import hudson.plugins.git.util.Build;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import jenkins.model.Jenkins;
|
||||
import jenkins.plugins.git.AbstractGitSCMSource;
|
||||
import jenkins.scm.api.SCMRevision;
|
||||
import jenkins.scm.api.SCMRevisionAction;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.jenkinsci.plugins.displayurlapi.DisplayURLProvider;
|
||||
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.ProcessingException;
|
||||
|
@ -18,6 +28,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -32,24 +43,23 @@ public class CommitStatusUpdater {
|
|||
private final static Logger LOGGER = Logger.getLogger(CommitStatusUpdater.class.getName());
|
||||
|
||||
public static void updateCommitStatus(Run<?, ?> build, TaskListener listener, BuildState state, String name) {
|
||||
GitLabApi client = getClient(build);
|
||||
GitLabClient client = getClient(build);
|
||||
if (client == null) {
|
||||
println(listener, "No GitLab connection configured");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String commitHash = getBuildRevision(build);
|
||||
String buildUrl = getBuildUrl(build);
|
||||
final String buildUrl = getBuildUrl(build);
|
||||
|
||||
for (String gitlabProjectId : retrieveGitlabProjectIds(build, build.getEnvironment(listener))) {
|
||||
for (final GitLabBranchBuild gitLabBranchBuild : retrieveGitlabProjectIds(build, build.getEnvironment(listener))) {
|
||||
try {
|
||||
if (existsCommit(client, gitlabProjectId, commitHash)) {
|
||||
client.changeBuildStatus(gitlabProjectId, commitHash, state, getBuildBranch(build), name, buildUrl, null);
|
||||
if (existsCommit(client, gitLabBranchBuild.getProjectId(), gitLabBranchBuild.getRevisionHash())) {
|
||||
client.changeBuildStatus(gitLabBranchBuild.getProjectId(), gitLabBranchBuild.getRevisionHash(), state, getBuildBranch(build), name, buildUrl, state.name());
|
||||
}
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
printf(listener, "Failed to update Gitlab commit status for project '%s': %s%n", gitlabProjectId, e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to update Gitlab commit status for project '%s'", gitlabProjectId), e);
|
||||
printf(listener, "Failed to update Gitlab commit status for project '%s': %s%n", gitLabBranchBuild.getProjectId(), e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to update Gitlab commit status for project '%s'", gitLabBranchBuild.getProjectId()), e);
|
||||
}
|
||||
}
|
||||
} catch (IOException | InterruptedException | IllegalStateException e) {
|
||||
|
@ -73,6 +83,82 @@ public class CommitStatusUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean existsCommit(GitLabClient client, String gitlabProjectId, String commitHash) {
|
||||
try {
|
||||
client.getCommit(gitlabProjectId, commitHash);
|
||||
return true;
|
||||
} catch (NotFoundException e) {
|
||||
LOGGER.log(Level.FINE, String.format("Project (%s) and commit (%s) combination not found", gitlabProjectId, commitHash));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getBuildBranch(Run<?, ?> build) {
|
||||
GitLabWebHookCause cause = build.getCause(GitLabWebHookCause.class);
|
||||
return cause == null ? null : cause.getData().getSourceBranch();
|
||||
}
|
||||
|
||||
private static String getBuildUrl(Run<?, ?> build) {
|
||||
return DisplayURLProvider.get().getRunURL(build);
|
||||
}
|
||||
|
||||
private static List<GitLabBranchBuild> retrieveGitlabProjectIds(Run<?, ?> build, EnvVars environment) {
|
||||
LOGGER.log(Level.INFO, "Retrieving gitlab project ids");
|
||||
final List<GitLabBranchBuild> result = new ArrayList<>();
|
||||
|
||||
GitLabWebHookCause gitlabCause = build.getCause(GitLabWebHookCause.class);
|
||||
if (gitlabCause != null) {
|
||||
return Collections.singletonList(new GitLabBranchBuild(
|
||||
gitlabCause.getData().getSourceProjectId().toString(), gitlabCause.getData().getLastCommit()));
|
||||
}
|
||||
|
||||
// Check upstream causes for GitLabWebHookCause
|
||||
List<GitLabBranchBuild> builds = findBuildsFromUpstreamCauses(build.getCauses());
|
||||
if (!builds.isEmpty()) {
|
||||
return builds;
|
||||
}
|
||||
|
||||
final GitLabClient gitLabClient = getClient(build);
|
||||
if (gitLabClient == null) {
|
||||
LOGGER.log(Level.WARNING, "No gitlab client found.");
|
||||
return result;
|
||||
}
|
||||
|
||||
final List<BuildData> buildDatas = build.getActions(BuildData.class);
|
||||
if (CollectionUtils.isEmpty(buildDatas)) {
|
||||
LOGGER.log(Level.INFO, "Build does not contain build data.");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (buildDatas.size() == 1) {
|
||||
addGitLabBranchBuild(result, getBuildRevision(build), buildDatas.get(0).getRemoteUrls(), environment, gitLabClient);
|
||||
} else {
|
||||
final SCMRevisionAction scmRevisionAction = build.getAction(SCMRevisionAction.class);
|
||||
|
||||
if (scmRevisionAction == null) {
|
||||
LOGGER.log(Level.INFO, "Build does not contain SCM revision action.");
|
||||
return result;
|
||||
}
|
||||
|
||||
final SCMRevision scmRevision = scmRevisionAction.getRevision();
|
||||
|
||||
String scmRevisionHash = null;
|
||||
if (scmRevision instanceof AbstractGitSCMSource.SCMRevisionImpl) {
|
||||
scmRevisionHash = ((AbstractGitSCMSource.SCMRevisionImpl) scmRevision).getHash();
|
||||
}
|
||||
|
||||
for (final BuildData buildData : buildDatas) {
|
||||
for (final Entry<String, Build> buildByBranchName : buildData.getBuildsByBranchName().entrySet()) {
|
||||
if (buildByBranchName.getValue().getSHA1().equals(ObjectId.fromString(scmRevisionHash))) {
|
||||
addGitLabBranchBuild(result, scmRevisionHash, buildData.getRemoteUrls(), environment, gitLabClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String getBuildRevision(Run<?, ?> build) {
|
||||
GitLabWebHookCause cause = build.getCause(GitLabWebHookCause.class);
|
||||
if (cause != null) {
|
||||
|
@ -92,67 +178,66 @@ public class CommitStatusUpdater {
|
|||
return action.getLastBuild(lastBuiltRevision.getSha1()).getMarked().getSha1String();
|
||||
}
|
||||
|
||||
private static boolean existsCommit(GitLabApi client, String gitlabProjectId, String commitHash) {
|
||||
try {
|
||||
client.getCommit(gitlabProjectId, commitHash);
|
||||
return true;
|
||||
} catch (NotFoundException e) {
|
||||
LOGGER.log(Level.FINE, String.format("Project (%s) and commit (%s) combination not found", gitlabProjectId, commitHash));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getBuildBranch(Run<?, ?> build) {
|
||||
GitLabWebHookCause cause = build.getCause(GitLabWebHookCause.class);
|
||||
return cause == null ? null : cause.getData().getSourceBranch();
|
||||
}
|
||||
|
||||
private static String getBuildUrl(Run<?, ?> build) {
|
||||
return Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
}
|
||||
|
||||
private static List<String> retrieveGitlabProjectIds(Run<?, ?> build, EnvVars environment) {
|
||||
LOGGER.log(Level.INFO, "Retrieving gitlab project ids");
|
||||
|
||||
GitLabWebHookCause cause = build.getCause(GitLabWebHookCause.class);
|
||||
if (cause != null) {
|
||||
return Collections.singletonList(cause.getData().getSourceProjectId().toString());
|
||||
}
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
GitLabApi gitLabClient = getClient(build);
|
||||
if (gitLabClient == null) {
|
||||
LOGGER.log(Level.WARNING, "No gitlab client found.");
|
||||
return result;
|
||||
}
|
||||
|
||||
final BuildData buildData = build.getAction(BuildData.class);
|
||||
if (buildData == null) {
|
||||
LOGGER.log(Level.INFO, "Build does not contain build data.");
|
||||
return result;
|
||||
}
|
||||
|
||||
final Set<String> remoteUrls = buildData.getRemoteUrls();
|
||||
private static void addGitLabBranchBuild(List<GitLabBranchBuild> result, String scmRevisionHash,
|
||||
Set<String> remoteUrls, EnvVars environment, GitLabClient gitLabClient) {
|
||||
for (String remoteUrl : remoteUrls) {
|
||||
try {
|
||||
LOGGER.log(Level.INFO, "Retrieving the gitlab project id from remote url {0}", remoteUrl);
|
||||
final String projectNameWithNameSpace = ProjectIdUtil.retrieveProjectId(environment.expand(remoteUrl));
|
||||
final String projectNameWithNameSpace = ProjectIdUtil.retrieveProjectId(gitLabClient, environment.expand(remoteUrl));
|
||||
if (StringUtils.isNotBlank(projectNameWithNameSpace)) {
|
||||
String projectId = projectNameWithNameSpace;
|
||||
if (projectNameWithNameSpace.contains(".")) {
|
||||
try {
|
||||
projectId = gitLabClient.getProject(projectNameWithNameSpace).getId().toString();
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to retrieve projectId for project '%s'", projectNameWithNameSpace), e);
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to retrieve projectId for project '%s'",
|
||||
projectNameWithNameSpace), e);
|
||||
}
|
||||
}
|
||||
result.add(projectId);
|
||||
result.add(new GitLabBranchBuild(projectId, scmRevisionHash));
|
||||
}
|
||||
} catch (ProjectIdUtil.ProjectIdResolutionException e) {
|
||||
// nothing to do
|
||||
LOGGER.log(Level.WARNING, "Did not match project id in remote url.");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<GitLabBranchBuild> findBuildsFromUpstreamCauses(List<Cause> causes) {
|
||||
for (Cause cause : causes) {
|
||||
if (cause instanceof UpstreamCause) {
|
||||
List<Cause> upCauses = ((UpstreamCause) cause).getUpstreamCauses(); // Non null, returns empty list when none are set
|
||||
for (Cause upCause : upCauses) {
|
||||
if (upCause instanceof GitLabWebHookCause) {
|
||||
GitLabWebHookCause gitlabCause = (GitLabWebHookCause) upCause;
|
||||
return Collections.singletonList(
|
||||
new GitLabBranchBuild(gitlabCause.getData().getSourceProjectId().toString(),
|
||||
gitlabCause.getData().getLastCommit()));
|
||||
}
|
||||
}
|
||||
List<GitLabBranchBuild> builds = findBuildsFromUpstreamCauses(upCauses);
|
||||
if (!builds.isEmpty()) {
|
||||
return builds;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static class GitLabBranchBuild {
|
||||
private final String projectId;
|
||||
private final String revisionHash;
|
||||
|
||||
public GitLabBranchBuild(final String projectId, final String revisionHash) {
|
||||
this.projectId = projectId;
|
||||
this.revisionHash = revisionHash;
|
||||
}
|
||||
|
||||
public String getProjectId() {
|
||||
return this.projectId;
|
||||
}
|
||||
|
||||
public String getRevisionHash() {
|
||||
return this.revisionHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public final class JsonUtil {
|
|||
|
||||
private static class DateModule extends SimpleModule {
|
||||
private static final String[] DATE_FORMATS = new String[] {
|
||||
"yyyy-MM-dd HH:mm:ss Z", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "yyyy-MM-dd'T'HH:mm:ssX"
|
||||
"yyyy-MM-dd HH:mm:ss Z", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "yyyy-MM-dd'T'HH:mm:ssX", "yyyy-MM-dd'T'HH:mm:ss.SSSX", "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
||||
};
|
||||
|
||||
private DateModule() {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.dabsquared.gitlabjenkins.util;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -11,13 +13,23 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
public final class ProjectIdUtil {
|
||||
|
||||
private static final Pattern PROJECT_ID_PATTERN = Pattern.compile("^/?(.*/)?(?<projectId>.*/.*)(\\.git)$");
|
||||
private static final Pattern PROJECT_ID_PATTERN = Pattern.compile("^/?(?<projectId>.*)(\\.git)$");
|
||||
|
||||
private ProjectIdUtil() { }
|
||||
|
||||
public static String retrieveProjectId(String remoteUrl) throws ProjectIdResolutionException {
|
||||
public static String retrieveProjectId(GitLabClient client, String remoteUrl) throws ProjectIdResolutionException {
|
||||
try {
|
||||
String projectId = new URIish(remoteUrl).getPath();
|
||||
String baseUri = client.getHostUrl();
|
||||
String projectId;
|
||||
if (baseUri != null && remoteUrl.startsWith(baseUri)) {
|
||||
projectId = new URIish(remoteUrl.substring(baseUri.length(), remoteUrl.length())).getPath();
|
||||
} else {
|
||||
projectId = new URIish(remoteUrl).getPath();
|
||||
}
|
||||
if (projectId.startsWith(":")) {
|
||||
projectId = projectId.substring(1);
|
||||
}
|
||||
|
||||
Matcher matcher = PROJECT_ID_PATTERN.matcher(projectId);
|
||||
if (matcher.matches()) {
|
||||
return matcher.group("projectId");
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.dabsquared.gitlabjenkins.webhook;
|
|||
import com.dabsquared.gitlabjenkins.util.ACLUtil;
|
||||
import com.dabsquared.gitlabjenkins.webhook.build.MergeRequestBuildAction;
|
||||
import com.dabsquared.gitlabjenkins.webhook.build.NoteBuildAction;
|
||||
import com.dabsquared.gitlabjenkins.webhook.build.PipelineBuildAction;
|
||||
import com.dabsquared.gitlabjenkins.webhook.build.PushBuildAction;
|
||||
import com.dabsquared.gitlabjenkins.webhook.status.BranchBuildPageRedirectAction;
|
||||
import com.dabsquared.gitlabjenkins.webhook.status.BranchStatusPngAction;
|
||||
|
@ -110,7 +111,9 @@ public class ActionResolver {
|
|||
case "Tag Push Hook":
|
||||
return new PushBuildAction(project, getRequestBody(request), tokenHeader);
|
||||
case "Note Hook":
|
||||
return new NoteBuildAction(project, getRequestBody(request), tokenHeader);
|
||||
return new NoteBuildAction(project, getRequestBody(request), tokenHeader);
|
||||
case "Pipeline Hook":
|
||||
return new PipelineBuildAction(project, getRequestBody(request), tokenHeader);
|
||||
default:
|
||||
LOGGER.log(Level.FINE, "Unsupported X-Gitlab-Event header: {0}", eventHeader);
|
||||
return new NoopAction();
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package com.dabsquared.gitlabjenkins.webhook.build;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.GitLabPushTrigger;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.*;
|
||||
import com.dabsquared.gitlabjenkins.util.JsonUtil;
|
||||
import hudson.model.Item;
|
||||
import hudson.model.Job;
|
||||
import hudson.security.ACL;
|
||||
import hudson.util.HttpResponses;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.util.JsonUtil.toPrettyPrint;
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
public class PipelineBuildAction extends BuildWebHookAction {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(PipelineBuildAction.class.getName());
|
||||
private Item project;
|
||||
private PipelineHook pipelineBuildHook;
|
||||
private final String secretToken;
|
||||
|
||||
public PipelineBuildAction(Item project, String json, String secretToken) {
|
||||
LOGGER.log(Level.FINE, "Pipeline event: {0}", toPrettyPrint(json));
|
||||
this.project = project;
|
||||
this.pipelineBuildHook = JsonUtil.read(json, PipelineHook.class);
|
||||
this.secretToken = secretToken;
|
||||
}
|
||||
|
||||
void processForCompatibility() {
|
||||
//if no project is defined, set it here
|
||||
if (this.pipelineBuildHook.getProject() == null && this.pipelineBuildHook.getRepository() != null) {
|
||||
try {
|
||||
String path = new URL(this.pipelineBuildHook.getRepository().getGitHttpUrl()).getPath();
|
||||
if (StringUtils.isNotBlank(path)) {
|
||||
Project project = new Project();
|
||||
project.setNamespace(path.replaceFirst("/", "").substring(0, path.lastIndexOf("/")));
|
||||
this.pipelineBuildHook.setProject(project);
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, "Could not find suitable namespace.");
|
||||
}
|
||||
} catch (MalformedURLException ignored) {
|
||||
LOGGER.log(Level.WARNING, "Invalid repository url found while building namespace.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void execute() {
|
||||
if (!(project instanceof Job<?, ?>)) {
|
||||
throw HttpResponses.errorWithoutStack(409, "Pipeline Hook is not supported for this project");
|
||||
}
|
||||
ACL.impersonate(ACL.SYSTEM, new TriggerNotifier(project, secretToken, Jenkins.getAuthentication()) {
|
||||
@Override
|
||||
protected void performOnPost(GitLabPushTrigger trigger) {
|
||||
trigger.onPost(pipelineBuildHook);
|
||||
}
|
||||
});
|
||||
throw HttpResponses.ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -10,17 +10,16 @@ import javax.ws.rs.ProcessingException;
|
|||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution;
|
||||
import org.jenkinsci.plugins.workflow.steps.Step;
|
||||
import org.jenkinsci.plugins.workflow.steps.StepContext;
|
||||
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
|
||||
import org.jenkinsci.plugins.workflow.steps.StepExecution;
|
||||
import org.jenkinsci.plugins.workflow.steps.*;
|
||||
|
||||
import org.kohsuke.stapler.DataBoundConstructor;
|
||||
import org.kohsuke.stapler.DataBoundSetter;
|
||||
import org.kohsuke.stapler.export.ExportedBean;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import hudson.Extension;
|
||||
|
@ -73,18 +72,17 @@ public class AcceptGitLabMergeRequestStep extends Step {
|
|||
protected Void run() throws Exception {
|
||||
GitLabWebHookCause cause = run.getCause(GitLabWebHookCause.class);
|
||||
if (cause != null) {
|
||||
Integer projectId = cause.getData().getTargetProjectId();
|
||||
Integer mergeRequestId = cause.getData().getMergeRequestId();
|
||||
if (projectId != null && mergeRequestId != null) {
|
||||
GitLabApi client = getClient(run);
|
||||
MergeRequest mergeRequest = cause.getData().getMergeRequest();
|
||||
if (mergeRequest != null) {
|
||||
GitLabClient client = getClient(run);
|
||||
if (client == null) {
|
||||
println("No GitLab connection configured");
|
||||
} else {
|
||||
try {
|
||||
client.acceptMergeRequest(projectId, mergeRequestId, step.mergeCommitMessage, false);
|
||||
client.acceptMergeRequest(mergeRequest, step.mergeCommitMessage, false);
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
printf("Failed to accept merge request for project '%s': %s%n", projectId, e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to accept merge request for project '%s'", projectId), e);
|
||||
printf("Failed to accept merge request for project '%s': %s%n", mergeRequest.getProjectId(), e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to accept merge request for project '%s'", mergeRequest.getProjectId()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import org.kohsuke.stapler.export.ExportedBean;
|
|||
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import hudson.Extension;
|
||||
|
@ -73,18 +75,17 @@ public class AddGitLabMergeRequestCommentStep extends Step {
|
|||
protected Void run() throws Exception {
|
||||
GitLabWebHookCause cause = run.getCause(GitLabWebHookCause.class);
|
||||
if (cause != null) {
|
||||
Integer projectId = cause.getData().getTargetProjectId();
|
||||
Integer mergeRequestId = cause.getData().getMergeRequestId();
|
||||
if (projectId != null && mergeRequestId != null) {
|
||||
GitLabApi client = getClient(run);
|
||||
MergeRequest mergeRequest = cause.getData().getMergeRequest();
|
||||
if (mergeRequest != null) {
|
||||
GitLabClient client = getClient(run);
|
||||
if (client == null) {
|
||||
println("No GitLab connection configured");
|
||||
} else {
|
||||
try {
|
||||
client.createMergeRequestNote(projectId, mergeRequestId, step.getComment());
|
||||
client.createMergeRequestNote(mergeRequest, step.getComment());
|
||||
} catch (WebApplicationException | ProcessingException e) {
|
||||
printf("Failed to add comment on Merge Request for project '%s': %s%n", projectId, e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to add comment on Merge Request for project '%s'", projectId), e);
|
||||
printf("Failed to add comment on Merge Request for project '%s': %s%n", mergeRequest.getProjectId(), e.getMessage());
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to add comment on Merge Request for project '%s'", mergeRequest.getProjectId()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,25 @@
|
|||
<f:entry title="Push Events" field="triggerOnPush">
|
||||
<f:checkbox default="true"/>
|
||||
</f:entry>
|
||||
<f:entry title="Merge Request Events" field="triggerOnMergeRequest">
|
||||
<f:entry title="Opened Merge Request Events" field="triggerOnMergeRequest">
|
||||
<f:checkbox default="true"/>
|
||||
</f:entry>
|
||||
<f:entry title="Accepted Merge Request Events" field="triggerOnAcceptedMergeRequest">
|
||||
<f:checkbox default="false"/>
|
||||
</f:entry>
|
||||
<f:entry title="Closed Merge Request Events" field="triggerOnClosedMergeRequest">
|
||||
<f:checkbox default="false"/>
|
||||
</f:entry>
|
||||
<f:entry title="Rebuild open Merge Requests" field="triggerOpenMergeRequestOnPush">
|
||||
<f:select/>
|
||||
</f:entry>
|
||||
<f:entry title="Approved Merge Requests (EE-only)" field="triggerOnApprovedMergeRequest">
|
||||
<f:checkbox default="true"/>
|
||||
</f:entry>
|
||||
<f:entry title="Comments" field="triggerOnNoteRequest">
|
||||
<f:checkbox default="true"/>
|
||||
</f:entry>
|
||||
<f:entry title="Comment for triggering a build" help="/plugin/gitlab-plugin/help/help-noteRegex.html">
|
||||
<f:entry title="Comment (regex) for triggering a build" help="/plugin/gitlab-plugin/help/help-noteRegex.html">
|
||||
<f:textbox field="noteRegex" default="Jenkins please retry a build"/>
|
||||
</f:entry>
|
||||
</table>
|
||||
|
@ -30,6 +39,9 @@
|
|||
<f:entry title="Set build description to build cause (eg. Merge request or Git Push )" field="setBuildDescription">
|
||||
<f:checkbox default="true"/>
|
||||
</f:entry>
|
||||
<f:entry title="Build on successful pipeline events" field="triggerOnPipelineEvent">
|
||||
<f:checkbox default="false"/>
|
||||
</f:entry>
|
||||
|
||||
<f:entry title="Allowed branches">
|
||||
<table>
|
||||
|
@ -73,6 +85,7 @@
|
|||
<table>
|
||||
<f:readOnlyTextbox field="secretToken" id="secretToken"/>
|
||||
<f:validateButton title="${%Generate}" method="generateSecretToken"/>
|
||||
<f:validateButton title="${%Clear}" method="clearSecretToken"/>
|
||||
</table>
|
||||
</f:entry>
|
||||
</f:advanced>
|
||||
|
|
|
@ -4,3 +4,5 @@ GitLabWebHookCause.ShortDescription.MergeRequestHook_html=Triggered by <a href="
|
|||
GitLabWebHookCause.ShortDescription.MergeRequestHook_plain=Triggered by GitLab Merge Request #{0}: {1} => {2}
|
||||
GitLabWebHookCause.ShortDescription.NoteHook_html=Triggered by {0} <a href="{4}/merge_requests/{1}" target="_blank">GitLab Merge Request #{1}</a>: {2} => {3}
|
||||
GitLabWebHookCause.ShortDescription.NoteHook_plain=Triggered by {0} GitLab Merge Request #{1}: {2} => {3}
|
||||
GitLabWebHookCause.ShortDescription.PipelineHook_noStatus=Started by GitLab Pipeline event
|
||||
GitLabWebHookCause.ShortDescription.PipelineHook=Started by GitLab Pipeline event {0}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:c="/lib/credentials" xmlns:st="jelly:stapler">
|
||||
<f:section title="Gitlab">
|
||||
<f:entry title="${%Enable authentication for '/project' end-point}" field="useAuthenticatedEndpoint">
|
||||
<f:checkbox/>
|
||||
<f:checkbox default="true"/>
|
||||
</f:entry>
|
||||
<f:entry title="${%GitLab connections}">
|
||||
<f:repeatable var="connection" items="${descriptor.connections}" name="connections">
|
||||
|
@ -18,6 +18,9 @@
|
|||
<c:select/>
|
||||
</f:entry>
|
||||
<f:advanced>
|
||||
<f:entry title="${%API-Level}" field="clientBuilderId" description="${%API Level for accessing Gitlab}">
|
||||
<f:select value="${connection.clientBuilderId}" default="autodetect"/>
|
||||
</f:entry>
|
||||
<f:entry title="${%Ignore SSL Certificate Errors}" field="ignoreCertificateErrors">
|
||||
<f:checkbox checked="${connection.ignoreCertificateErrors}"/>
|
||||
</f:entry>
|
||||
|
@ -30,7 +33,7 @@
|
|||
<st:include page="configure-advanced.jelly" optional="true" />
|
||||
</f:advanced>
|
||||
<f:validateButton title="${%Test Connection}" progress="${%Testing...}" method="testConnection"
|
||||
with="apiTokenId,url,ignoreCertificateErrors"/>
|
||||
with="apiTokenId,clientBuilderId,url,ignoreCertificateErrors"/>
|
||||
<f:entry title="">
|
||||
<div align="right">
|
||||
<f:repeatableDeleteButton/>
|
||||
|
|
|
@ -20,5 +20,10 @@
|
|||
<f:textarea name="abortNoteText" field="abortNoteText"/>
|
||||
</f:entry>
|
||||
</f:optionalBlock>
|
||||
<f:optionalBlock name="replaceUnstableNote" checked="${instance.replaceUnstableNote}" title="Custom message on unstable" inline="true">
|
||||
<f:entry>
|
||||
<f:textarea name="unstableNoteText" field="unstableNoteText"/>
|
||||
</f:entry>
|
||||
</f:optionalBlock>
|
||||
</f:advanced>
|
||||
</j:jelly>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div>
|
||||
<div>
|
||||
<p>When filled, commenting this phrase in the merge request will trigger a build.</p>
|
||||
<p>When filled, a comment in the merge request matching this regular expression will trigger a build.</p>
|
||||
</div>
|
||||
</div>
|
|
@ -1,5 +1,6 @@
|
|||
package com.dabsquared.gitlabjenkins.connection;
|
||||
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
|
@ -87,7 +88,7 @@ public class GitLabConnectionConfigSSLTest {
|
|||
public void doCheckConnection_ignoreCertificateErrors() {
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
|
||||
FormValidation formValidation = connectionConfig.doTestConnection("https://localhost:" + port + "/gitlab", API_TOKEN_ID, true, 10, 10);
|
||||
FormValidation formValidation = connectionConfig.doTestConnection("https://localhost:" + port + "/gitlab", API_TOKEN_ID, "v3", true, 10, 10);
|
||||
assertThat(formValidation.getMessage(), is(Messages.connection_success()));
|
||||
}
|
||||
|
||||
|
@ -95,7 +96,7 @@ public class GitLabConnectionConfigSSLTest {
|
|||
public void doCheckConnection_certificateError() throws IOException {
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
|
||||
FormValidation formValidation = connectionConfig.doTestConnection("https://localhost:" + port + "/gitlab", API_TOKEN_ID, false, 10, 10);
|
||||
FormValidation formValidation = connectionConfig.doTestConnection("https://localhost:" + port + "/gitlab", API_TOKEN_ID, "v3", false, 10, 10);
|
||||
assertThat(formValidation.getMessage(), containsString(Messages.connection_error("")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package com.dabsquared.gitlabjenkins.connection;
|
||||
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.GitLabPushTrigger;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.V3GitLabClientBuilder;
|
||||
import hudson.model.FreeStyleProject;
|
||||
import hudson.model.Item;
|
||||
import hudson.security.GlobalMatrixAuthorizationStrategy;
|
||||
|
@ -33,10 +36,14 @@ import java.io.IOException;
|
|||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
import static junit.framework.TestCase.assertSame;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockserver.model.HttpRequest.request;
|
||||
import static org.mockserver.model.HttpResponse.response;
|
||||
|
@ -70,31 +77,33 @@ public class GitLabConnectionConfigTest {
|
|||
|
||||
@Test
|
||||
public void doCheckConnection_success() {
|
||||
HttpRequest request = request().withPath("/gitlab/api/v3/.*").withHeader("PRIVATE-TOKEN", API_TOKEN);
|
||||
mockServerClient.when(request).respond(response().withStatusCode(Response.Status.OK.getStatusCode()));
|
||||
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
FormValidation formValidation = connectionConfig.doTestConnection(gitLabUrl, API_TOKEN_ID, false, 10, 10);
|
||||
|
||||
assertThat(formValidation.getMessage(), is(Messages.connection_success()));
|
||||
mockServerClient.verify(request);
|
||||
String expected = Messages.connection_success();
|
||||
assertThat(doCheckConnection("v3", Response.Status.OK), is(expected));
|
||||
assertThat(doCheckConnection("v4", Response.Status.OK), is(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doCheckConnection_forbidden() throws IOException {
|
||||
HttpRequest request = request().withPath("/gitlab/api/v3/.*").withHeader("PRIVATE-TOKEN", API_TOKEN);
|
||||
mockServerClient.when(request).respond(response().withStatusCode(Response.Status.FORBIDDEN.getStatusCode()));
|
||||
String expected = Messages.connection_error("HTTP 403 Forbidden");
|
||||
assertThat(doCheckConnection("v3", Response.Status.FORBIDDEN), is(expected));
|
||||
assertThat(doCheckConnection("v4", Response.Status.FORBIDDEN), is(expected));
|
||||
}
|
||||
|
||||
private String doCheckConnection(String clientBuilderId, Response.Status status) {
|
||||
HttpRequest request = request().withPath("/gitlab/api/" + clientBuilderId + "/.*").withHeader("PRIVATE-TOKEN", API_TOKEN);
|
||||
mockServerClient.when(request).respond(response().withStatusCode(status.getStatusCode()));
|
||||
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
FormValidation formValidation = connectionConfig.doTestConnection(gitLabUrl, API_TOKEN_ID, false, 10, 10);
|
||||
|
||||
assertThat(formValidation.getMessage(), is(Messages.connection_error("HTTP 403 Forbidden")));
|
||||
FormValidation formValidation = connectionConfig.doTestConnection(gitLabUrl, API_TOKEN_ID, clientBuilderId, false, 10, 10);
|
||||
mockServerClient.verify(request);
|
||||
return formValidation.getMessage();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void authenticationEnabled_anonymous_forbidden() throws IOException, URISyntaxException {
|
||||
jenkins.get(GitLabConnectionConfig.class).setUseAuthenticatedEndpoint(true);
|
||||
Boolean defaultValue = jenkins.get(GitLabConnectionConfig.class).isUseAuthenticatedEndpoint();
|
||||
assertTrue(defaultValue);
|
||||
jenkins.getInstance().setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy());
|
||||
URL jenkinsURL = jenkins.getURL();
|
||||
FreeStyleProject project = jenkins.createFreeStyleProject("test");
|
||||
|
@ -114,7 +123,6 @@ public class GitLabConnectionConfigTest {
|
|||
@Test
|
||||
public void authenticationEnabled_registered_success() throws Exception {
|
||||
String username = "test-user";
|
||||
jenkins.get(GitLabConnectionConfig.class).setUseAuthenticatedEndpoint(true);
|
||||
jenkins.getInstance().setSecurityRealm(jenkins.createDummySecurityRealm());
|
||||
GlobalMatrixAuthorizationStrategy authorizationStrategy = new GlobalMatrixAuthorizationStrategy();
|
||||
authorizationStrategy.add(Item.BUILD, username);
|
||||
|
@ -150,4 +158,39 @@ public class GitLabConnectionConfigTest {
|
|||
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConnectionsTest() {
|
||||
GitLabConnection connection1 = new GitLabConnection("1", "http://localhost", null, new V3GitLabClientBuilder(), false, 10, 10);
|
||||
GitLabConnection connection2 = new GitLabConnection("2", "http://localhost", null, new V3GitLabClientBuilder(), false, 10, 10);
|
||||
GitLabConnectionConfig config = jenkins.get(GitLabConnectionConfig.class);
|
||||
List<GitLabConnection> connectionList1 = new ArrayList<>();
|
||||
connectionList1.add(connection1);
|
||||
|
||||
config.setConnections(connectionList1);
|
||||
assertThat(config.getConnections(), is(connectionList1));
|
||||
|
||||
List<GitLabConnection> connectionList2 = new ArrayList<>();
|
||||
connectionList2.add(connection1);
|
||||
connectionList2.add(connection2);
|
||||
|
||||
config.setConnections(connectionList2);
|
||||
assertThat(config.getConnections(), is(connectionList2));
|
||||
|
||||
config.setConnections(connectionList1);
|
||||
assertThat(config.getConnections(), is(connectionList1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getClient_is_cached() {
|
||||
GitLabConnection connection = new GitLabConnection("test", "http://localhost", API_TOKEN_ID, new V3GitLabClientBuilder(), false, 10, 10);
|
||||
GitLabConnectionConfig config = jenkins.get(GitLabConnectionConfig.class);
|
||||
List<GitLabConnection> connectionList1 = new ArrayList<>();
|
||||
connectionList1.add(connection);
|
||||
config.setConnections(connectionList1);
|
||||
|
||||
GitLabClient client = config.getClient(connection.getName());
|
||||
assertNotNull(client);
|
||||
assertSame(client, config.getClient(connection.getName()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
package com.dabsquared.gitlabjenkins.environment;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.cause.CauseData;
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import hudson.EnvVars;
|
||||
import hudson.matrix.AxisList;
|
||||
import hudson.matrix.MatrixBuild;
|
||||
import hudson.matrix.MatrixProject;
|
||||
import hudson.matrix.MatrixRun;
|
||||
import hudson.matrix.TextAxis;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.FreeStyleProject;
|
||||
import hudson.model.FreeStyleBuild;
|
||||
import hudson.model.StreamBuildListener;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.cause.CauseDataBuilder.causeData;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Evgeni Golov
|
||||
*/
|
||||
public class GitLabEnvironmentContributorTest {
|
||||
|
||||
@ClassRule
|
||||
public static JenkinsRule jenkins = new JenkinsRule();
|
||||
|
||||
private BuildListener listener;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
listener = new StreamBuildListener(jenkins.createTaskListener().getLogger(), Charset.defaultCharset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void freeStyleProjectTest() throws IOException, InterruptedException, ExecutionException {
|
||||
FreeStyleProject p = jenkins.createFreeStyleProject();
|
||||
GitLabWebHookCause cause = new GitLabWebHookCause(generateCauseData());
|
||||
FreeStyleBuild b = p.scheduleBuild2(0, cause).get();
|
||||
EnvVars env = b.getEnvironment(listener);
|
||||
|
||||
assertEnv(env);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matrixProjectTest() throws IOException, InterruptedException, ExecutionException {
|
||||
EnvVars env;
|
||||
MatrixProject p = jenkins.jenkins.createProject(MatrixProject.class, "matrixbuild");
|
||||
GitLabWebHookCause cause = new GitLabWebHookCause(generateCauseData());
|
||||
// set up 2x2 matrix
|
||||
AxisList axes = new AxisList();
|
||||
axes.add(new TextAxis("db","mysql","oracle"));
|
||||
axes.add(new TextAxis("direction","north","south"));
|
||||
p.setAxes(axes);
|
||||
|
||||
MatrixBuild build = p.scheduleBuild2(0, cause).get();
|
||||
List<MatrixRun> runs = build.getRuns();
|
||||
assertEquals(4,runs.size());
|
||||
for (MatrixRun run : runs) {
|
||||
env = run.getEnvironment(listener);
|
||||
assertNotNull(env.get("db"));
|
||||
assertEnv(env);
|
||||
}
|
||||
}
|
||||
|
||||
private CauseData generateCauseData() {
|
||||
return causeData()
|
||||
.withActionType(CauseData.ActionType.MERGE)
|
||||
.withSourceProjectId(1)
|
||||
.withTargetProjectId(1)
|
||||
.withBranch("feature")
|
||||
.withSourceBranch("feature")
|
||||
.withUserName("")
|
||||
.withSourceRepoHomepage("https://gitlab.org/test")
|
||||
.withSourceRepoName("test")
|
||||
.withSourceNamespace("test-namespace")
|
||||
.withSourceRepoUrl("git@gitlab.org:test.git")
|
||||
.withSourceRepoSshUrl("git@gitlab.org:test.git")
|
||||
.withSourceRepoHttpUrl("https://gitlab.org/test.git")
|
||||
.withMergeRequestTitle("Test")
|
||||
.withMergeRequestId(1)
|
||||
.withMergeRequestIid(1)
|
||||
.withTargetBranch("master")
|
||||
.withTargetRepoName("test")
|
||||
.withTargetNamespace("test-namespace")
|
||||
.withTargetRepoSshUrl("git@gitlab.org:test.git")
|
||||
.withTargetRepoHttpUrl("https://gitlab.org/test.git")
|
||||
.withTriggeredByUser("test")
|
||||
.withLastCommit("123")
|
||||
.withTargetProjectUrl("https://gitlab.org/test")
|
||||
.build();
|
||||
}
|
||||
|
||||
private void assertEnv(EnvVars env) {
|
||||
assertEquals("1", env.get("gitlabMergeRequestId"));
|
||||
assertEquals("git@gitlab.org:test.git", env.get("gitlabSourceRepoUrl"));
|
||||
assertEquals("master", env.get("gitlabTargetBranch"));
|
||||
assertEquals("test", env.get("gitlabTargetRepoName"));
|
||||
assertEquals("feature", env.get("gitlabSourceBranch"));
|
||||
assertEquals("test", env.get("gitlabSourceRepoName"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.AutodetectGitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.V3GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.V4GitLabClientBuilder;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder.getAllGitLabClientBuilders;
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder.getGitLabClientBuilderById;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
|
||||
|
||||
public class GitLabClientBuilderTest {
|
||||
@Rule
|
||||
public JenkinsRule jenkins = new JenkinsRule();
|
||||
|
||||
@Test
|
||||
public void getAllGitLabClientBuilders_list_is_sorted_by_ordinal() {
|
||||
List<GitLabClientBuilder> builders = getAllGitLabClientBuilders();
|
||||
assertThat(builders.get(0), instanceOf(AutodetectGitLabClientBuilder.class));
|
||||
assertThat(builders.get(1), instanceOf(V4GitLabClientBuilder.class));
|
||||
assertThat(builders.get(2), instanceOf(V3GitLabClientBuilder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getGitLabClientBuilderById_success() {
|
||||
assertThat(getGitLabClientBuilderById(new V3GitLabClientBuilder().id()), instanceOf(V3GitLabClientBuilder.class));
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchElementException.class)
|
||||
public void getGitLabClientBuilderById_no_match() {
|
||||
getGitLabClientBuilderById("unknown");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.mockserver.client.server.MockServerClient;
|
||||
import org.mockserver.junit.MockServerRule;
|
||||
import org.mockserver.model.HttpRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.impl.TestUtility.*;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockserver.matchers.Times.exactly;
|
||||
import static org.mockserver.matchers.Times.once;
|
||||
|
||||
public class AutodetectingGitLabClientTest {
|
||||
@Rule
|
||||
public MockServerRule mockServer = new MockServerRule(this);
|
||||
@Rule
|
||||
public JenkinsRule jenkins = new JenkinsRule();
|
||||
private MockServerClient mockServerClient;
|
||||
private String gitLabUrl;
|
||||
private GitLabClientBuilder clientBuilder;
|
||||
private AutodetectingGitLabClient api;
|
||||
private HttpRequest v3Request;
|
||||
private HttpRequest v4Request;
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException {
|
||||
gitLabUrl = "http://localhost:" + mockServer.getPort() + "/gitlab";
|
||||
addGitLabApiToken();
|
||||
|
||||
List<GitLabClientBuilder> builders = Arrays.<GitLabClientBuilder>asList(new V3GitLabClientBuilder(), new V4GitLabClientBuilder());
|
||||
api = new AutodetectingGitLabClient(builders, gitLabUrl, API_TOKEN, true, 10, 10);
|
||||
|
||||
v3Request = versionRequest(V3GitLabApiProxy.ID);
|
||||
v4Request = versionRequest(V4GitLabApiProxy.ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildClient_success_v3() throws Exception {
|
||||
mockServerClient.when(v3Request).respond(responseOk());
|
||||
api.getCurrentUser();
|
||||
assertApiImpl(api, V3GitLabApiProxy.class);
|
||||
mockServerClient.verify(v3Request, v3Request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildClient_success_v4() throws Exception {
|
||||
mockServerClient.when(v3Request).respond(responseNotFound());
|
||||
mockServerClient.when(v4Request).respond(responseOk());
|
||||
api.getCurrentUser();
|
||||
assertApiImpl(api, V4GitLabApiProxy.class);
|
||||
mockServerClient.verify(v3Request, v4Request, v4Request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildClient_success_switching_apis() throws Exception {
|
||||
mockServerClient.when(v3Request, once()).respond(responseNotFound());
|
||||
mockServerClient.when(v4Request, exactly(2)).respond(responseOk());
|
||||
api.getCurrentUser();
|
||||
assertApiImpl(api, V4GitLabApiProxy.class);
|
||||
|
||||
mockServerClient.when(v4Request, once()).respond(responseNotFound());
|
||||
mockServerClient.when(v3Request, exactly(2)).respond(responseOk());
|
||||
api.getCurrentUser();
|
||||
assertApiImpl(api, V3GitLabApiProxy.class);
|
||||
|
||||
mockServerClient.verify(v3Request, v4Request, v4Request, v3Request, v3Request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildClient_no_match() {
|
||||
mockServerClient.when(v3Request).respond(responseNotFound());
|
||||
mockServerClient.when(v4Request).respond(responseNotFound());
|
||||
try {
|
||||
api.getCurrentUser();
|
||||
fail("endpoint should throw exception when no matching delegate is found");
|
||||
} catch (NoSuchElementException e) {
|
||||
mockServerClient.verify(v3Request, v4Request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import hudson.ProxyConfiguration;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.mockserver.junit.MockServerRule;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.impl.TestUtility.assertApiImpl;
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.impl.TestUtility.buildClientWithDefaults;
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
|
||||
|
||||
public class ResteasyGitLabClientBuilderTest {
|
||||
@Rule
|
||||
public MockServerRule mockServer = new MockServerRule(this);
|
||||
@Rule
|
||||
public JenkinsRule jenkins = new JenkinsRule();
|
||||
|
||||
@Test
|
||||
public void buildClient() throws Exception {
|
||||
GitLabClientBuilder clientBuilder = new ResteasyGitLabClientBuilder("test", 0, V3GitLabApiProxy.class, null);
|
||||
assertApiImpl(buildClientWithDefaults(clientBuilder, "http://localhost/"), V3GitLabApiProxy.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildClientWithProxy() throws Exception {
|
||||
jenkins.getInstance().proxy = new ProxyConfiguration("example.com", 8080, "test", "test", "*localhost*");
|
||||
GitLabClientBuilder clientBuilder = new ResteasyGitLabClientBuilder("test", 0, V3GitLabApiProxy.class, null);
|
||||
assertNotNull(buildClientWithDefaults(clientBuilder, "http://localhost"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.dabsquared.gitlabjenkins.gitlab.api.impl;
|
||||
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
||||
import org.mockserver.model.HttpRequest;
|
||||
import org.mockserver.model.HttpResponse;
|
||||
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import static javax.ws.rs.HttpMethod.GET;
|
||||
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
|
||||
import static javax.ws.rs.core.Response.Status.OK;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.mockserver.model.HttpRequest.request;
|
||||
import static org.mockserver.model.HttpResponse.response;
|
||||
|
||||
|
||||
class TestUtility {
|
||||
static final String API_TOKEN = "secret";
|
||||
private static final String API_TOKEN_ID = "apiTokenId";
|
||||
private static final boolean IGNORE_CERTIFICATE_ERRORS = true;
|
||||
private static final int CONNECTION_TIMEOUT = 10;
|
||||
private static final int READ_TIMEOUT = 10;
|
||||
|
||||
static void addGitLabApiToken() throws IOException {
|
||||
for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) {
|
||||
if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) {
|
||||
List<Domain> domains = credentialsStore.getDomains();
|
||||
credentialsStore.addCredentials(domains.get(0),
|
||||
new StringCredentialsImpl(CredentialsScope.SYSTEM, API_TOKEN_ID, "GitLab API Token", Secret.fromString(API_TOKEN)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HttpRequest versionRequest(String id) {
|
||||
return request().withMethod(GET).withPath("/gitlab/api/" + id + "/.*").withHeader("PRIVATE-TOKEN", API_TOKEN);
|
||||
}
|
||||
|
||||
static HttpResponse responseOk() {
|
||||
return responseWithStatus(OK);
|
||||
}
|
||||
|
||||
static HttpResponse responseNotFound() {
|
||||
return responseWithStatus(NOT_FOUND);
|
||||
}
|
||||
|
||||
private static HttpResponse responseWithStatus(Status status) {
|
||||
return response().withStatusCode(status.getStatusCode());
|
||||
}
|
||||
|
||||
static GitLabClient buildClientWithDefaults(GitLabClientBuilder clientBuilder, String url) {
|
||||
return clientBuilder.buildClient(url, API_TOKEN, IGNORE_CERTIFICATE_ERRORS, CONNECTION_TIMEOUT, READ_TIMEOUT);
|
||||
}
|
||||
|
||||
static void assertApiImpl(GitLabClient client, Class<? extends GitLabApiProxy> apiImplClass) throws Exception {
|
||||
Field apiField = ((ResteasyGitLabClient) client).getClass().getDeclaredField("api");
|
||||
apiField.setAccessible(true);
|
||||
assertThat(apiField.get(client), instanceOf(apiImplClass));
|
||||
}
|
||||
|
||||
static void assertApiImpl(AutodetectingGitLabClient api, Class<? extends GitLabApiProxy> apiImplClass) throws Exception {
|
||||
Field delegate = api.getClass().getDeclaredField("delegate");
|
||||
delegate.setAccessible(true);
|
||||
assertApiImpl((GitLabClient) delegate.get(api), apiImplClass);
|
||||
}
|
||||
|
||||
private TestUtility() { /* utility class */ }
|
||||
}
|
|
@ -1,22 +1,10 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionConfig;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.Result;
|
||||
import hudson.model.StreamBuildListener;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -30,14 +18,8 @@ import org.mockserver.model.HttpRequest;
|
|||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.*;
|
||||
import static org.mockserver.model.HttpRequest.request;
|
||||
import static org.mockserver.model.HttpResponse.response;
|
||||
|
||||
|
@ -45,10 +27,6 @@ import static org.mockserver.model.HttpResponse.response;
|
|||
* @author Nikolay Ustinov
|
||||
*/
|
||||
public class GitLabAcceptMergeRequestPublisherTest {
|
||||
|
||||
private static final String GIT_LAB_CONNECTION = "GitLab";
|
||||
private static final String API_TOKEN = "secret";
|
||||
|
||||
@ClassRule
|
||||
public static MockServerRule mockServer = new MockServerRule(new Object());
|
||||
|
||||
|
@ -59,17 +37,8 @@ public class GitLabAcceptMergeRequestPublisherTest {
|
|||
private BuildListener listener;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupConnection() throws IOException {
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
String apiTokenId = "apiTokenId";
|
||||
for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) {
|
||||
if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) {
|
||||
List<Domain> domains = credentialsStore.getDomains();
|
||||
credentialsStore.addCredentials(domains.get(0),
|
||||
new StringCredentialsImpl(CredentialsScope.SYSTEM, apiTokenId, "GitLab API Token", Secret.fromString(API_TOKEN)));
|
||||
}
|
||||
}
|
||||
connectionConfig.addConnection(new GitLabConnection(GIT_LAB_CONNECTION, "http://localhost:" + mockServer.getPort() + "/gitlab", apiTokenId, false, 10, 10));
|
||||
public static void setupClass() throws IOException {
|
||||
setupGitLabConnections(jenkins, mockServer);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -83,68 +52,45 @@ public class GitLabAcceptMergeRequestPublisherTest {
|
|||
mockServerClient.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matrixAggregatable() throws InterruptedException, IOException {
|
||||
verifyMatrixAggregatable(GitLabAcceptMergeRequestPublisher.class, listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void success() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.SUCCESS, buildNumber);
|
||||
publish(mockSimpleBuild(GITLAB_CONNECTION_V3, Result.SUCCESS));
|
||||
publish(mockSimpleBuild(GITLAB_CONNECTION_V4, Result.SUCCESS));
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareAcceptMergeRequestWithSuccessResponse(projectId, mergeRequestId)
|
||||
};
|
||||
|
||||
GitLabAcceptMergeRequestPublisher publisher = spy(new GitLabAcceptMergeRequestPublisher());
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
mockServerClient.verify(
|
||||
prepareAcceptMergeRequestWithSuccessResponse("v3", MERGE_REQUEST_ID),
|
||||
prepareAcceptMergeRequestWithSuccessResponse("v4", MERGE_REQUEST_IID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.FAILURE, buildNumber);
|
||||
|
||||
GitLabAcceptMergeRequestPublisher publisher = spy(new GitLabAcceptMergeRequestPublisher());
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
publish(mockSimpleBuild(GITLAB_CONNECTION_V3, Result.FAILURE));
|
||||
publish(mockSimpleBuild(GITLAB_CONNECTION_V4, Result.FAILURE));
|
||||
|
||||
mockServerClient.verifyZeroInteractions();
|
||||
}
|
||||
|
||||
private HttpRequest prepareAcceptMergeRequestWithSuccessResponse(Integer projectId, Integer mergeRequestId) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareAcceptMergeRequest(projectId, mergeRequestId);
|
||||
private void publish(AbstractBuild build) throws InterruptedException, IOException {
|
||||
GitLabAcceptMergeRequestPublisher publisher = preparePublisher(new GitLabAcceptMergeRequestPublisher(), build);
|
||||
publisher.perform(build, null, listener);
|
||||
}
|
||||
|
||||
private HttpRequest prepareAcceptMergeRequestWithSuccessResponse(String apiLevel, int mergeRequestId) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareAcceptMergeRequest(apiLevel, mergeRequestId);
|
||||
mockServerClient.when(updateCommitStatus).respond(response().withStatusCode(200));
|
||||
return updateCommitStatus;
|
||||
}
|
||||
|
||||
private HttpRequest prepareAcceptMergeRequest(Integer projectId, Integer mergeRequestId) throws UnsupportedEncodingException {
|
||||
private HttpRequest prepareAcceptMergeRequest(String apiLevel, int mergeRequestId) throws UnsupportedEncodingException {
|
||||
return request()
|
||||
.withPath("/gitlab/api/v3/projects/" + projectId + "/merge_requests/" + mergeRequestId + "/merge")
|
||||
.withPath("/gitlab/api/" + apiLevel + "/projects/" + PROJECT_ID + "/merge_requests/" + mergeRequestId + "/merge")
|
||||
.withMethod("PUT")
|
||||
.withHeader("PRIVATE-TOKEN", "secret")
|
||||
.withBody("merge_commit_message=Merge+Request+accepted+by+jenkins+build+success&should_remove_source_branch=false");
|
||||
}
|
||||
|
||||
private AbstractBuild mockBuild(String buildUrl, String gitLabConnection, Result result, Integer buildNumber, String... remoteUrls) {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
BuildData buildData = mock(BuildData.class);
|
||||
when(buildData.getRemoteUrls()).thenReturn(new HashSet<>(Arrays.asList(remoteUrls)));
|
||||
when(build.getAction(BuildData.class)).thenReturn(buildData);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(buildUrl);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(buildUrl);
|
||||
when(build.getNumber()).thenReturn(buildNumber);
|
||||
|
||||
AbstractProject<?, ?> project = mock(AbstractProject.class);
|
||||
when(project.getProperty(GitLabConnectionProperty.class)).thenReturn(new GitLabConnectionProperty(gitLabConnection));
|
||||
when(build.getProject()).thenReturn(project);
|
||||
return build;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionConfig;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState;
|
||||
import hudson.EnvVars;
|
||||
|
@ -14,17 +8,18 @@ import hudson.model.AbstractBuild;
|
|||
import hudson.model.AbstractProject;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.Result;
|
||||
import hudson.model.Run;
|
||||
import hudson.model.StreamBuildListener;
|
||||
import hudson.model.TaskListener;
|
||||
import hudson.plugins.git.Revision;
|
||||
import hudson.plugins.git.util.Build;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import jenkins.plugins.git.AbstractGitSCMSource;
|
||||
import jenkins.scm.api.SCMRevisionAction;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
||||
import org.jenkinsci.plugins.displayurlapi.DisplayURLProvider;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -45,10 +40,19 @@ import java.io.PrintStream;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.BUILD_URL;
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.GITLAB_CONNECTION_V3;
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.GITLAB_CONNECTION_V4;
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.PROJECT_ID;
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.setupGitLabConnections;
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.verifyMatrixAggregatable;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
|
@ -61,9 +65,7 @@ import static org.mockserver.model.HttpResponse.response;
|
|||
* @author Robin Müller
|
||||
*/
|
||||
public class GitLabCommitStatusPublisherTest {
|
||||
|
||||
private static final String GIT_LAB_CONNECTION = "GitLab";
|
||||
private static final String API_TOKEN = "secret";
|
||||
private static final String SHA1 = "0616d12a3a24068691027a1e113147e3c1cfa2f4";
|
||||
|
||||
@ClassRule
|
||||
public static MockServerRule mockServer = new MockServerRule(new Object());
|
||||
|
@ -75,17 +77,8 @@ public class GitLabCommitStatusPublisherTest {
|
|||
private BuildListener listener;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupConnection() throws IOException {
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
String apiTokenId = "apiTokenId";
|
||||
for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) {
|
||||
if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) {
|
||||
List<Domain> domains = credentialsStore.getDomains();
|
||||
credentialsStore.addCredentials(domains.get(0),
|
||||
new StringCredentialsImpl(CredentialsScope.SYSTEM, apiTokenId, "GitLab API Token", Secret.fromString(API_TOKEN)));
|
||||
}
|
||||
}
|
||||
connectionConfig.addConnection(new GitLabConnection(GIT_LAB_CONNECTION, "http://localhost:" + mockServer.getPort() + "/gitlab", apiTokenId, false, 10, 10));
|
||||
public static void setupClass() throws IOException {
|
||||
setupGitLabConnections(jenkins, mockServer);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -100,203 +93,257 @@ public class GitLabCommitStatusPublisherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void running() throws UnsupportedEncodingException {
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse("test/project", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.running)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, null, "test/project.git");
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.prebuild(build, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
public void matrixAggregatable() throws InterruptedException, IOException {
|
||||
verifyMatrixAggregatable(GitLabCommitStatusPublisher.class, listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void running_v3() throws UnsupportedEncodingException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, null, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v3", build, BuildState.running);
|
||||
|
||||
prebuildAndVerify(build, listener, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void running_v4() throws UnsupportedEncodingException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, null, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.running);
|
||||
|
||||
prebuildAndVerify(build, listener, requests);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void runningWithLibrary() throws UnsupportedEncodingException {
|
||||
AbstractBuild build = mockBuildWithLibrary(GITLAB_CONNECTION_V4, null, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.running);
|
||||
|
||||
prebuildAndVerify(build, listener, requests);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void runningWithDotInProjectId() throws IOException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, null, "test/project.test.git");
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareGetProjectResponse("test/project.test",1),
|
||||
prepareExistsCommitWithSuccessResponse("1", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("1", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.running)
|
||||
prepareGetProjectResponse("test/project.test"),
|
||||
prepareExistsCommitWithSuccessResponse("v4", String.valueOf(PROJECT_ID)),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("v4", String.valueOf(PROJECT_ID), build, BuildState.running)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, null, "test/project.test.git");
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.prebuild(build, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
prebuildAndVerify(build, listener, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canceled() throws IOException, InterruptedException {
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse("test/project", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.canceled)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, Result.ABORTED, "test/project.git");
|
||||
public void canceled_v3() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, Result.ABORTED, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v3", build, BuildState.canceled);
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void success() throws IOException, InterruptedException {
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse("test/project", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.success)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, Result.SUCCESS, "test/project.git");
|
||||
public void canceled_v4() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.ABORTED, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.canceled);
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed() throws IOException, InterruptedException {
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse("test/project", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.failed)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, Result.FAILURE, "test/project.git");
|
||||
public void canceledWithLibrary() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuildWithLibrary(GITLAB_CONNECTION_V4, Result.ABORTED, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.canceled);
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void success_v3() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, Result.SUCCESS, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v3", build, BuildState.success);
|
||||
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void success_v4() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.SUCCESS, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.success);
|
||||
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successWithLibrary() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuildWithLibrary(GITLAB_CONNECTION_V4, Result.SUCCESS, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.success);
|
||||
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed_v3() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, Result.FAILURE, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v3", build, BuildState.failed);
|
||||
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed_v4() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, Result.FAILURE, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v3", build, BuildState.failed);
|
||||
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failedWithLibrary() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuildWithLibrary(GITLAB_CONNECTION_V4, Result.FAILURE, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.failed);
|
||||
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unstable() throws IOException, InterruptedException {
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse("test/project", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.failed)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, Result.UNSTABLE, "test/project.git");
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.UNSTABLE, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.failed);
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unstableWithLibrary() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuildWithLibrary(GITLAB_CONNECTION_V4, Result.UNSTABLE, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.failed);
|
||||
|
||||
performAndVerify(build, false, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unstableAsSuccess() throws IOException, InterruptedException {
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse("test/project", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.success)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, Result.UNSTABLE, "test/project.git");
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.UNSTABLE, "test/project.git");
|
||||
HttpRequest[] requests = prepareCheckCommitAndUpdateStatusRequests("v4", build, BuildState.success);
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", true);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(build, true, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void running_multipleRepos() throws UnsupportedEncodingException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, null, "test/project-1.git", "test/project-2.git");
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse("test/project-1", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project-1", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.running),
|
||||
prepareExistsCommitWithSuccessResponse("test/project-2", "123abc"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("test/project-2", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.running)
|
||||
prepareExistsCommitWithSuccessResponse("v4", "test/project-1"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("v4", "test/project-1", build, BuildState.running),
|
||||
prepareExistsCommitWithSuccessResponse("v4", "test/project-2"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse("v4", "test/project-2", build, BuildState.running)
|
||||
};
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, null, "test/project-1.git", "test/project-2.git");
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.prebuild(build, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
prebuildAndVerify(build, listener, requests);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void running_commitNotExists() throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareUpdateCommitStatusWithSuccessResponse("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.running);
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, null, "test/project.git");
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.prebuild(build, listener);
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, null, "test/project.git");
|
||||
HttpRequest updateCommitStatus = prepareUpdateCommitStatusWithSuccessResponse("v4", "test/project", build, BuildState.running);
|
||||
|
||||
new GitLabCommitStatusPublisher("jenkins", false).prebuild(build, listener);
|
||||
mockServerClient.verify(updateCommitStatus, VerificationTimes.exactly(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void running_failToUpdate() throws UnsupportedEncodingException {
|
||||
prepareExistsCommitWithSuccessResponse("test/project", "123abc");
|
||||
HttpRequest updateCommitStatus = prepareUpdateCommitStatus("test/project", "123abc", jenkins.getInstance().getRootUrl() + "/build/123", BuildState.running);
|
||||
mockServerClient.when(updateCommitStatus).respond(response().withStatusCode(403));
|
||||
AbstractBuild build = mockBuild("123abc", "/build/123", GIT_LAB_CONNECTION, null, "test/project.git");
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, null, "test/project.git");
|
||||
BuildListener buildListener = mock(BuildListener.class);
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
when(buildListener.getLogger()).thenReturn(new PrintStream(outputStream));
|
||||
|
||||
GitLabCommitStatusPublisher publisher = new GitLabCommitStatusPublisher("jenkins", false);
|
||||
publisher.prebuild(build, buildListener);
|
||||
prepareExistsCommitWithSuccessResponse("v4", "test/project");
|
||||
HttpRequest updateCommitStatus = prepareUpdateCommitStatus("v4", "test/project", build, BuildState.running);
|
||||
mockServerClient.when(updateCommitStatus).respond(response().withStatusCode(403));
|
||||
|
||||
prebuildAndVerify(build, buildListener, updateCommitStatus);
|
||||
assertThat(outputStream.toString(), CoreMatchers.containsString("Failed to update Gitlab commit status for project 'test/project': HTTP 403 Forbidden"));
|
||||
mockServerClient.verify(updateCommitStatus);
|
||||
}
|
||||
|
||||
private void prebuildAndVerify(AbstractBuild build, BuildListener listener, HttpRequest... requests) {
|
||||
new GitLabCommitStatusPublisher("jenkins", false).prebuild(build, listener);
|
||||
mockServerClient.verify(requests);
|
||||
}
|
||||
|
||||
private HttpRequest prepareUpdateCommitStatusWithSuccessResponse(String projectId, String sha, String targetUrl, BuildState state) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareUpdateCommitStatus(projectId, sha, targetUrl, state);
|
||||
private void performAndVerify(AbstractBuild build, boolean markUnstableAsSuccess, HttpRequest... requests) throws InterruptedException, IOException {
|
||||
new GitLabCommitStatusPublisher("jenkins", markUnstableAsSuccess).perform(build, null, listener);
|
||||
mockServerClient.verify(requests);
|
||||
}
|
||||
|
||||
private HttpRequest[] prepareCheckCommitAndUpdateStatusRequests(String apiLevel, Run<?, ?> build, BuildState buildState) throws UnsupportedEncodingException {
|
||||
return new HttpRequest[] {
|
||||
prepareExistsCommitWithSuccessResponse(apiLevel, "test/project"),
|
||||
prepareUpdateCommitStatusWithSuccessResponse(apiLevel, "test/project", build, buildState)
|
||||
};
|
||||
}
|
||||
|
||||
private HttpRequest prepareUpdateCommitStatusWithSuccessResponse(String apiLevel, String projectName, Run<?, ?> build, BuildState state) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareUpdateCommitStatus(apiLevel, projectName, build, state);
|
||||
mockServerClient.when(updateCommitStatus).respond(response().withStatusCode(200));
|
||||
return updateCommitStatus;
|
||||
}
|
||||
|
||||
|
||||
private HttpRequest prepareUpdateCommitStatus(String projectId, String sha, String targetUrl, BuildState state) throws UnsupportedEncodingException {
|
||||
private HttpRequest prepareUpdateCommitStatus(final String apiLevel, String projectName, Run<?, ?> build, BuildState state) throws UnsupportedEncodingException {
|
||||
return request()
|
||||
.withPath("/gitlab/api/v3/projects/" + URLEncoder.encode(projectId, "UTF-8") + "/statuses/" + sha)
|
||||
.withPath("/gitlab/api/" + apiLevel + "/projects/" + URLEncoder.encode(projectName, "UTF-8") + "/statuses/" + SHA1)
|
||||
.withMethod("POST")
|
||||
.withHeader("PRIVATE-TOKEN", "secret")
|
||||
.withBody("state=" + URLEncoder.encode(state.name(), "UTF-8") + "&context=jenkins&" + "target_url=" + URLEncoder.encode(targetUrl, "UTF-8"));
|
||||
.withBody("state=" + URLEncoder.encode(state.name(), "UTF-8") + "&context=jenkins&" + "target_url=" + URLEncoder.encode(DisplayURLProvider.get().getRunURL(build), "UTF-8") + "&description=" + URLEncoder.encode(state.name(), "UTF-8"));
|
||||
}
|
||||
|
||||
private HttpRequest prepareExistsCommitWithSuccessResponse(String projectId, String sha) throws UnsupportedEncodingException {
|
||||
HttpRequest existsCommit = prepareExistsCommit(projectId, sha);
|
||||
private HttpRequest prepareExistsCommitWithSuccessResponse(String apiLevel, String projectName) throws UnsupportedEncodingException {
|
||||
HttpRequest existsCommit = prepareExistsCommit(apiLevel, projectName);
|
||||
mockServerClient.when(existsCommit).respond(response().withStatusCode(200));
|
||||
return existsCommit;
|
||||
}
|
||||
|
||||
private HttpRequest prepareExistsCommit(String projectId, String sha) throws UnsupportedEncodingException {
|
||||
private HttpRequest prepareExistsCommit(String apiLevel, String projectName) throws UnsupportedEncodingException {
|
||||
return request()
|
||||
.withPath("/gitlab/api/v3/projects/" + URLEncoder.encode(projectId, "UTF-8") + "/repository/commits/" + sha)
|
||||
.withPath("/gitlab/api/" + apiLevel + "/projects/" + URLEncoder.encode(projectName, "UTF-8") + "/repository/commits/" + SHA1)
|
||||
.withMethod("GET")
|
||||
.withHeader("PRIVATE-TOKEN", "secret");
|
||||
}
|
||||
|
||||
private HttpRequest prepareGetProjectResponse(String projectName, int projectId) throws IOException {
|
||||
private HttpRequest prepareGetProjectResponse(String projectName) throws IOException {
|
||||
HttpRequest request= request()
|
||||
.withPath("/gitlab/api/v3/projects/" + URLEncoder.encode(projectName, "UTF-8"))
|
||||
.withPath("/gitlab/api/v4/projects/" + URLEncoder.encode(projectName, "UTF-8"))
|
||||
.withMethod("GET")
|
||||
. withHeader("PRIVATE-TOKEN", "secret");
|
||||
|
||||
HttpResponse response = response().withBody(getSingleProjectJson("GetSingleProject.json",projectName,projectId));
|
||||
HttpResponse response = response().withBody(getSingleProjectJson("GetSingleProject.json", projectName, PROJECT_ID));
|
||||
|
||||
response.withHeader("Content-Type", "application/json");
|
||||
mockServerClient.when(request).respond(response.withStatusCode(200));
|
||||
return request;
|
||||
}
|
||||
|
||||
private AbstractBuild mockBuild(String sha, String buildUrl, String gitLabConnection, Result result, String... remoteUrls) {
|
||||
private AbstractBuild mockBuild(String gitLabConnection, Result result, String... remoteUrls) {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
List<BuildData> buildDatas = new ArrayList<>();
|
||||
BuildData buildData = mock(BuildData.class);
|
||||
Revision revision = mock(Revision.class);
|
||||
when(revision.getSha1String()).thenReturn(sha);
|
||||
when(revision.getSha1String()).thenReturn(SHA1);
|
||||
when(buildData.getLastBuiltRevision()).thenReturn(revision);
|
||||
when(buildData.getRemoteUrls()).thenReturn(new HashSet<>(Arrays.asList(remoteUrls)));
|
||||
Build gitBuild = mock(Build.class);
|
||||
when(gitBuild.getMarked()).thenReturn(revision);
|
||||
when(buildData.getLastBuild(any(ObjectId.class))).thenReturn(gitBuild);
|
||||
buildDatas.add(buildData);
|
||||
when(build.getActions(BuildData.class)).thenReturn(buildDatas);
|
||||
when(build.getAction(BuildData.class)).thenReturn(buildData);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(buildUrl);
|
||||
when(build.getUrl()).thenReturn(BUILD_URL);
|
||||
AbstractProject<?, ?> project = mock(AbstractProject.class);
|
||||
when(project.getProperty(GitLabConnectionProperty.class)).thenReturn(new GitLabConnectionProperty(gitLabConnection));
|
||||
when(build.getProject()).thenReturn(project);
|
||||
|
@ -314,11 +361,70 @@ public class GitLabCommitStatusPublisherTest {
|
|||
}
|
||||
return build;
|
||||
}
|
||||
private String getSingleProjectJson(String name,String projectNameWithNamespace, int porjectId) throws IOException {
|
||||
|
||||
private AbstractBuild mockBuildWithLibrary(String gitLabConnection, Result result, String... remoteUrls) {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
List<BuildData> buildDatas = new ArrayList<>();
|
||||
BuildData buildData = mock(BuildData.class);
|
||||
SCMRevisionAction scmRevisionAction = mock(SCMRevisionAction.class);
|
||||
AbstractGitSCMSource.SCMRevisionImpl revisionImpl = mock(AbstractGitSCMSource.SCMRevisionImpl.class);
|
||||
|
||||
when(build.getAction(SCMRevisionAction.class)).thenReturn(scmRevisionAction);
|
||||
when(scmRevisionAction.getRevision()).thenReturn(revisionImpl);
|
||||
when(revisionImpl.getHash()).thenReturn(SHA1);
|
||||
|
||||
Revision revision = mock(Revision.class);
|
||||
when(revision.getSha1String()).thenReturn(SHA1);
|
||||
when(buildData.getLastBuiltRevision()).thenReturn(revision);
|
||||
when(buildData.getRemoteUrls()).thenReturn(new HashSet<>(Arrays.asList(remoteUrls)));
|
||||
|
||||
Build gitBuild = mock(Build.class);
|
||||
|
||||
when(gitBuild.getMarked()).thenReturn(revision);
|
||||
when(gitBuild.getSHA1()).thenReturn(ObjectId.fromString(SHA1));
|
||||
when(buildData.getLastBuild(any(ObjectId.class))).thenReturn(gitBuild);
|
||||
Map<String, Build> buildsByBranchName = new HashMap<>();
|
||||
buildsByBranchName.put("develop", gitBuild);
|
||||
when(buildData.getBuildsByBranchName()).thenReturn(buildsByBranchName);
|
||||
buildDatas.add(buildData);
|
||||
|
||||
//Second build data (@librabry)
|
||||
BuildData buildDataLib = mock(BuildData.class);
|
||||
Revision revisionLib = mock(Revision.class);
|
||||
when(revisionLib.getSha1String()).thenReturn("SHALIB");
|
||||
when(buildDataLib.getLastBuiltRevision()).thenReturn(revisionLib);
|
||||
Build gitBuildLib = mock(Build.class);
|
||||
when(gitBuildLib.getMarked()).thenReturn(revisionLib);
|
||||
when(buildDataLib.getLastBuild(any(ObjectId.class))).thenReturn(gitBuildLib);
|
||||
buildDatas.add(buildDataLib);
|
||||
|
||||
when(build.getActions(BuildData.class)).thenReturn(buildDatas);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(BUILD_URL);
|
||||
|
||||
AbstractProject<?, ?> project = mock(AbstractProject.class);
|
||||
when(project.getProperty(GitLabConnectionProperty.class)).thenReturn(new GitLabConnectionProperty(gitLabConnection));
|
||||
when(build.getProject()).thenReturn(project);
|
||||
EnvVars environment = mock(EnvVars.class);
|
||||
when(environment.expand(anyString())).thenAnswer(new Answer<String>() {
|
||||
@Override
|
||||
public String answer(InvocationOnMock invocation) throws Throwable {
|
||||
return (String) invocation.getArguments()[0];
|
||||
}
|
||||
});
|
||||
try {
|
||||
when(build.getEnvironment(any(TaskListener.class))).thenReturn(environment);
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return build;
|
||||
}
|
||||
|
||||
private String getSingleProjectJson(String name,String projectNameWithNamespace, int projectId) throws IOException {
|
||||
String nameSpace = projectNameWithNamespace.split("/")[0];
|
||||
String projectName = projectNameWithNamespace.split("/")[1];
|
||||
return IOUtils.toString(getClass().getResourceAsStream(name))
|
||||
.replace("${projectId}", porjectId + "")
|
||||
.replace("${projectId}", projectId + "")
|
||||
.replace("${nameSpace}", nameSpace)
|
||||
.replace("${projectName}", projectName);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionConfig;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import hudson.EnvVars;
|
||||
import hudson.model.AbstractBuild;
|
||||
|
@ -16,9 +10,6 @@ import hudson.model.Result;
|
|||
import hudson.model.StreamBuildListener;
|
||||
import hudson.model.TaskListener;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -35,16 +26,13 @@ import java.io.IOException;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockserver.model.HttpRequest.request;
|
||||
import static org.mockserver.model.HttpResponse.response;
|
||||
|
@ -53,10 +41,6 @@ import static org.mockserver.model.HttpResponse.response;
|
|||
* @author Nikolay Ustinov
|
||||
*/
|
||||
public class GitLabMessagePublisherTest {
|
||||
|
||||
private static final String GIT_LAB_CONNECTION = "GitLab";
|
||||
private static final String API_TOKEN = "secret";
|
||||
|
||||
@ClassRule
|
||||
public static MockServerRule mockServer = new MockServerRule(new Object());
|
||||
|
||||
|
@ -67,17 +51,8 @@ public class GitLabMessagePublisherTest {
|
|||
private BuildListener listener;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupConnection() throws IOException {
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
String apiTokenId = "apiTokenId";
|
||||
for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) {
|
||||
if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) {
|
||||
List<Domain> domains = credentialsStore.getDomains();
|
||||
credentialsStore.addCredentials(domains.get(0),
|
||||
new StringCredentialsImpl(CredentialsScope.SYSTEM, apiTokenId, "GitLab API Token", Secret.fromString(API_TOKEN)));
|
||||
}
|
||||
}
|
||||
connectionConfig.addConnection(new GitLabConnection(GIT_LAB_CONNECTION, "http://localhost:" + mockServer.getPort() + "/gitlab", apiTokenId, false, 10, 10));
|
||||
public static void setupClass() throws IOException {
|
||||
setupGitLabConnections(jenkins, mockServer);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -92,192 +67,168 @@ public class GitLabMessagePublisherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void canceled() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.ABORTED, buildNumber);
|
||||
String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
String defaultNote = MessageFormat.format(":point_up: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})",
|
||||
Result.ABORTED, build.getParent().getDisplayName(), buildNumber, buildUrl);
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(false, false, false, false, null, null, null));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
public void matrixAggregatable() throws InterruptedException, IOException {
|
||||
verifyMatrixAggregatable(GitLabMessagePublisher.class, listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void success() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.SUCCESS, buildNumber);
|
||||
String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
String defaultNote = MessageFormat.format(":white_check_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})",
|
||||
Result.SUCCESS, build.getParent().getDisplayName(), buildNumber, buildUrl);
|
||||
public void canceled_v3() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, Result.ABORTED);
|
||||
String defaultNote = formatNote(build, ":point_up: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})");
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v3", MERGE_REQUEST_ID, defaultNote));
|
||||
}
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(false, false, false, false, null, null, null));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
@Test
|
||||
public void canceled_v4() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.ABORTED);
|
||||
String defaultNote = formatNote(build, ":point_up: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})");
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void success_v3() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, Result.SUCCESS);
|
||||
String defaultNote = formatNote(build, ":white_check_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})");
|
||||
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v3", MERGE_REQUEST_ID, defaultNote));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void success_v4() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.SUCCESS);
|
||||
String defaultNote = formatNote(build, ":white_check_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})");
|
||||
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void success_withOnlyForFailure() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.SUCCESS, buildNumber);
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.SUCCESS);
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(true, false, false, false, null, null, null));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verifyZeroInteractions();
|
||||
performAndVerify(build, "test", true, false, false, false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.FAILURE, buildNumber);
|
||||
String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
String defaultNote = MessageFormat.format(":negative_squared_cross_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})",
|
||||
Result.FAILURE, build.getParent().getDisplayName(), buildNumber, buildUrl);
|
||||
public void failed_v3() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V3, Result.FAILURE);
|
||||
String defaultNote = formatNote(build, ":negative_squared_cross_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})");
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(false, false, false, false, null, null, null));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v3", MERGE_REQUEST_ID, defaultNote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed_v4() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.FAILURE);
|
||||
String defaultNote = formatNote(build, ":negative_squared_cross_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})");
|
||||
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void failed_withOnlyForFailed() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.FAILURE, buildNumber);
|
||||
String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
String defaultNote = MessageFormat.format(":negative_squared_cross_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})",
|
||||
Result.FAILURE, build.getParent().getDisplayName(), buildNumber, buildUrl);
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.FAILURE);
|
||||
String defaultNote = formatNote(build, ":negative_squared_cross_mark: Jenkins Build {0}\n\nResults available at: [Jenkins [{1} #{2}]]({3})");
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(true, false, false, false, null, null, null));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(
|
||||
build, defaultNote, true, false, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canceledWithCustomNote() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.ABORTED, buildNumber);
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.ABORTED);
|
||||
String defaultNote = "abort";
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(false, false, false, true, null, null, defaultNote));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, true, false,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successWithCustomNote() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.SUCCESS, buildNumber);
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.SUCCESS);
|
||||
String defaultNote = "success";
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(false, true, false, false, defaultNote, null, null));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(
|
||||
build, defaultNote, false, true, false, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failedWithCustomNote() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.FAILURE, buildNumber);
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.FAILURE);
|
||||
String defaultNote = "failure";
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabMessagePublisher publisher = spy(new GitLabMessagePublisher(false, false, true, false, null, defaultNote, null));
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, true, false, false,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
private HttpRequest prepareSendMessageWithSuccessResponse(Integer projectId, Integer mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareSendMessageStatus(projectId, mergeRequestId, body);
|
||||
@Test
|
||||
public void unstableWithCustomNote() throws IOException, InterruptedException {
|
||||
AbstractBuild build = mockBuild(GITLAB_CONNECTION_V4, Result.UNSTABLE);
|
||||
String defaultNote = "unstable";
|
||||
|
||||
performAndVerify(
|
||||
build, defaultNote, false, false, false, false, true,
|
||||
prepareSendMessageWithSuccessResponse("v4", MERGE_REQUEST_IID, defaultNote));
|
||||
}
|
||||
|
||||
private void performAndVerify(AbstractBuild build, String note, boolean onlyForFailure, boolean replaceSuccessNote, boolean replaceFailureNote, boolean replaceAbortNote, boolean replaceUnstableNote, HttpRequest... requests) throws InterruptedException, IOException {
|
||||
String successNoteText = replaceSuccessNote ? note : null;
|
||||
String failureNoteText = replaceFailureNote ? note : null;
|
||||
String abortNoteText = replaceAbortNote ? note : null;
|
||||
String unstableNoteText = replaceUnstableNote ? note : null;
|
||||
GitLabMessagePublisher publisher = preparePublisher(new GitLabMessagePublisher(onlyForFailure, replaceSuccessNote, replaceFailureNote, replaceAbortNote, replaceUnstableNote, successNoteText, failureNoteText, abortNoteText, unstableNoteText), build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
if (requests.length > 0) {
|
||||
mockServerClient.verify(requests);
|
||||
} else {
|
||||
mockServerClient.verifyZeroInteractions();
|
||||
}
|
||||
}
|
||||
|
||||
private HttpRequest prepareSendMessageWithSuccessResponse(String apiLevel, int mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareSendMessageStatus(apiLevel, mergeRequestId, body);
|
||||
mockServerClient.when(updateCommitStatus).respond(response().withStatusCode(200));
|
||||
return updateCommitStatus;
|
||||
}
|
||||
|
||||
private HttpRequest prepareSendMessageStatus(Integer projectId, Integer mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
private HttpRequest prepareSendMessageStatus(final String apiLevel, int mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
return request()
|
||||
.withPath("/gitlab/api/v3/projects/" + projectId + "/merge_requests/" + mergeRequestId + "/notes")
|
||||
.withPath("/gitlab/api/" + apiLevel + "/projects/" + PROJECT_ID + "/merge_requests/" + mergeRequestId + "/notes")
|
||||
.withMethod("POST")
|
||||
.withHeader("PRIVATE-TOKEN", "secret")
|
||||
.withBody("body=" + URLEncoder.encode(body, "UTF-8"));
|
||||
}
|
||||
|
||||
private AbstractBuild mockBuild(String buildUrl, String gitLabConnection, Result result, Integer buildNumber, String... remoteUrls) {
|
||||
private AbstractBuild mockBuild(String gitLabConnection, Result result, String... remoteUrls) {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
BuildData buildData = mock(BuildData.class);
|
||||
when(buildData.getRemoteUrls()).thenReturn(new HashSet<>(Arrays.asList(remoteUrls)));
|
||||
when(build.getAction(BuildData.class)).thenReturn(buildData);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(buildUrl);
|
||||
when(build.getUrl()).thenReturn(BUILD_URL);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(buildUrl);
|
||||
when(build.getNumber()).thenReturn(buildNumber);
|
||||
when(build.getNumber()).thenReturn(BUILD_NUMBER);
|
||||
|
||||
AbstractProject<?, ?> project = mock(AbstractProject.class);
|
||||
when(project.getProperty(GitLabConnectionProperty.class)).thenReturn(new GitLabConnectionProperty(gitLabConnection));
|
||||
|
|
|
@ -1,22 +1,10 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionConfig;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.Result;
|
||||
import hudson.model.StreamBuildListener;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -31,15 +19,8 @@ import java.io.IOException;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static com.dabsquared.gitlabjenkins.publisher.TestUtility.*;
|
||||
import static org.mockserver.model.HttpRequest.request;
|
||||
import static org.mockserver.model.HttpResponse.response;
|
||||
|
||||
|
@ -47,10 +28,6 @@ import static org.mockserver.model.HttpResponse.response;
|
|||
* @author Nikolay Ustinov
|
||||
*/
|
||||
public class GitLabVotePublisherTest {
|
||||
|
||||
private static final String GIT_LAB_CONNECTION = "GitLab";
|
||||
private static final String API_TOKEN = "secret";
|
||||
|
||||
@ClassRule
|
||||
public static MockServerRule mockServer = new MockServerRule(new Object());
|
||||
|
||||
|
@ -61,17 +38,8 @@ public class GitLabVotePublisherTest {
|
|||
private BuildListener listener;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupConnection() throws IOException {
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
String apiTokenId = "apiTokenId";
|
||||
for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) {
|
||||
if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) {
|
||||
List<Domain> domains = credentialsStore.getDomains();
|
||||
credentialsStore.addCredentials(domains.get(0),
|
||||
new StringCredentialsImpl(CredentialsScope.SYSTEM, apiTokenId, "GitLab API Token", Secret.fromString(API_TOKEN)));
|
||||
}
|
||||
}
|
||||
connectionConfig.addConnection(new GitLabConnection(GIT_LAB_CONNECTION, "http://localhost:" + mockServer.getPort() + "/gitlab", apiTokenId, false, 10, 10));
|
||||
public static void setupClass() throws IOException {
|
||||
setupGitLabConnections(jenkins, mockServer);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -86,77 +54,49 @@ public class GitLabVotePublisherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void success() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.SUCCESS, buildNumber);
|
||||
String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
String defaultNote = MessageFormat.format(":+1:",
|
||||
Result.SUCCESS, build.getParent().getDisplayName(), buildNumber, buildUrl);
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabVotePublisher publisher = spy(new GitLabVotePublisher());
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
public void matrixAggregatable() throws InterruptedException, IOException {
|
||||
verifyMatrixAggregatable(GitLabVotePublisher.class, listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed() throws IOException, InterruptedException {
|
||||
Integer buildNumber = 1;
|
||||
Integer projectId = 3;
|
||||
Integer mergeRequestId = 1;
|
||||
AbstractBuild build = mockBuild("/build/123", GIT_LAB_CONNECTION, Result.FAILURE, buildNumber);
|
||||
String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
String defaultNote = MessageFormat.format(":-1:",
|
||||
Result.FAILURE, build.getParent().getDisplayName(), buildNumber, buildUrl);
|
||||
|
||||
HttpRequest[] requests = new HttpRequest[] {
|
||||
prepareSendMessageWithSuccessResponse(projectId, mergeRequestId, defaultNote)
|
||||
};
|
||||
|
||||
GitLabVotePublisher publisher = spy(new GitLabVotePublisher());
|
||||
doReturn(projectId).when(publisher).getProjectId(build);
|
||||
doReturn(mergeRequestId).when(publisher).getMergeRequestId(build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(requests);
|
||||
public void success_v3() throws IOException, InterruptedException {
|
||||
performAndVerify(mockSimpleBuild(GITLAB_CONNECTION_V3, Result.SUCCESS), "v3", MERGE_REQUEST_ID, ":+1:");
|
||||
}
|
||||
|
||||
private HttpRequest prepareSendMessageWithSuccessResponse(Integer projectId, Integer mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareSendMessageStatus(projectId, mergeRequestId, body);
|
||||
@Test
|
||||
public void success_v4() throws IOException, InterruptedException {
|
||||
performAndVerify(mockSimpleBuild(GITLAB_CONNECTION_V4, Result.SUCCESS), "v4", MERGE_REQUEST_IID, ":+1:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed_v3() throws IOException, InterruptedException {
|
||||
performAndVerify(mockSimpleBuild(GITLAB_CONNECTION_V3, Result.FAILURE), "v3", MERGE_REQUEST_ID, ":-1:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failed_v4() throws IOException, InterruptedException {
|
||||
performAndVerify(mockSimpleBuild(GITLAB_CONNECTION_V4, Result.FAILURE), "v4", MERGE_REQUEST_IID, ":-1:");
|
||||
}
|
||||
|
||||
|
||||
private void performAndVerify(AbstractBuild build, String apiLevel, int mergeRequestId, String defaultNote) throws InterruptedException, IOException {
|
||||
GitLabVotePublisher publisher = preparePublisher(new GitLabVotePublisher(), build);
|
||||
publisher.perform(build, null, listener);
|
||||
|
||||
mockServerClient.verify(prepareSendMessageWithSuccessResponse(build, apiLevel, mergeRequestId, defaultNote));
|
||||
}
|
||||
|
||||
private HttpRequest prepareSendMessageWithSuccessResponse(AbstractBuild build, String apiLevel, int mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
HttpRequest updateCommitStatus = prepareSendMessageStatus(apiLevel, mergeRequestId, formatNote(build, body));
|
||||
mockServerClient.when(updateCommitStatus).respond(response().withStatusCode(200));
|
||||
return updateCommitStatus;
|
||||
}
|
||||
|
||||
private HttpRequest prepareSendMessageStatus(Integer projectId, Integer mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
private HttpRequest prepareSendMessageStatus(final String apiLevel, int mergeRequestId, String body) throws UnsupportedEncodingException {
|
||||
return request()
|
||||
.withPath("/gitlab/api/v3/projects/" + projectId + "/merge_requests/" + mergeRequestId + "/notes")
|
||||
.withPath("/gitlab/api/" + apiLevel + "/projects/" + PROJECT_ID + "/merge_requests/" + mergeRequestId + "/notes")
|
||||
.withMethod("POST")
|
||||
.withHeader("PRIVATE-TOKEN", "secret")
|
||||
.withBody("body=" + URLEncoder.encode(body, "UTF-8"));
|
||||
}
|
||||
|
||||
private AbstractBuild mockBuild(String buildUrl, String gitLabConnection, Result result, Integer buildNumber, String... remoteUrls) {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
BuildData buildData = mock(BuildData.class);
|
||||
when(buildData.getRemoteUrls()).thenReturn(new HashSet<>(Arrays.asList(remoteUrls)));
|
||||
when(build.getAction(BuildData.class)).thenReturn(buildData);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(buildUrl);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(buildUrl);
|
||||
when(build.getNumber()).thenReturn(buildNumber);
|
||||
|
||||
AbstractProject<?, ?> project = mock(AbstractProject.class);
|
||||
when(project.getProperty(GitLabConnectionProperty.class)).thenReturn(new GitLabConnectionProperty(gitLabConnection));
|
||||
when(build.getProject()).thenReturn(project);
|
||||
return build;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package com.dabsquared.gitlabjenkins.publisher;
|
||||
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionConfig;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.V3GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.V4GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import hudson.Launcher;
|
||||
import hudson.matrix.MatrixAggregatable;
|
||||
import hudson.matrix.MatrixAggregator;
|
||||
import hudson.matrix.MatrixBuild;
|
||||
import hudson.matrix.MatrixConfiguration;
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.Result;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import hudson.tasks.Notifier;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.mockserver.junit.MockServerRule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
|
||||
final class TestUtility {
|
||||
static final String GITLAB_CONNECTION_V3 = "GitLabV3";
|
||||
static final String GITLAB_CONNECTION_V4 = "GitLabV4";
|
||||
static final String BUILD_URL = "/build/123";
|
||||
static final int BUILD_NUMBER = 1;
|
||||
static final int PROJECT_ID = 3;
|
||||
static final int MERGE_REQUEST_ID = 1;
|
||||
static final int MERGE_REQUEST_IID = 2;
|
||||
|
||||
private static final String API_TOKEN = "secret";
|
||||
|
||||
static void setupGitLabConnections(JenkinsRule jenkins, MockServerRule mockServer) throws IOException {
|
||||
GitLabConnectionConfig connectionConfig = jenkins.get(GitLabConnectionConfig.class);
|
||||
String apiTokenId = "apiTokenId";
|
||||
for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) {
|
||||
if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) {
|
||||
List<Domain> domains = credentialsStore.getDomains();
|
||||
credentialsStore.addCredentials(domains.get(0),
|
||||
new StringCredentialsImpl(CredentialsScope.SYSTEM, apiTokenId, "GitLab API Token", Secret.fromString(TestUtility.API_TOKEN)));
|
||||
}
|
||||
}
|
||||
connectionConfig.addConnection(new GitLabConnection(TestUtility.GITLAB_CONNECTION_V3, "http://localhost:" + mockServer.getPort() + "/gitlab", apiTokenId, new V3GitLabClientBuilder(), false, 10, 10));
|
||||
connectionConfig.addConnection(new GitLabConnection(TestUtility.GITLAB_CONNECTION_V4, "http://localhost:" + mockServer.getPort() + "/gitlab", apiTokenId, new V4GitLabClientBuilder(), false, 10, 10));
|
||||
|
||||
}
|
||||
|
||||
static <T extends Notifier & MatrixAggregatable> void verifyMatrixAggregatable(Class<T> publisherClass, BuildListener listener) throws InterruptedException, IOException {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
AbstractProject project = mock(MatrixConfiguration.class);
|
||||
Notifier publisher = mock(publisherClass);
|
||||
MatrixBuild parentBuild = mock(MatrixBuild.class);
|
||||
|
||||
when(build.getParent()).thenReturn(project);
|
||||
when(((MatrixAggregatable) publisher).createAggregator(any(MatrixBuild.class), any(Launcher.class), any(BuildListener.class))).thenCallRealMethod();
|
||||
when(publisher.perform(any(AbstractBuild.class), any(Launcher.class), any(BuildListener.class))).thenReturn(true);
|
||||
|
||||
MatrixAggregator aggregator = ((MatrixAggregatable) publisher).createAggregator(parentBuild, null, listener);
|
||||
aggregator.startBuild();
|
||||
aggregator.endBuild();
|
||||
verify(publisher).perform(parentBuild, null, listener);
|
||||
}
|
||||
|
||||
static AbstractBuild mockSimpleBuild(String gitLabConnection, Result result, String... remoteUrls) {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
BuildData buildData = mock(BuildData.class);
|
||||
when(buildData.getRemoteUrls()).thenReturn(new HashSet<>(Arrays.asList(remoteUrls)));
|
||||
when(build.getAction(BuildData.class)).thenReturn(buildData);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getUrl()).thenReturn(BUILD_URL);
|
||||
when(build.getResult()).thenReturn(result);
|
||||
when(build.getNumber()).thenReturn(BUILD_NUMBER);
|
||||
|
||||
AbstractProject<?, ?> project = mock(AbstractProject.class);
|
||||
when(project.getProperty(GitLabConnectionProperty.class)).thenReturn(new GitLabConnectionProperty(gitLabConnection));
|
||||
when(build.getProject()).thenReturn(project);
|
||||
return build;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
static String formatNote(AbstractBuild build, String note) {
|
||||
String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl();
|
||||
return MessageFormat.format(note, build.getResult(), build.getParent().getDisplayName(), BUILD_NUMBER, buildUrl);
|
||||
}
|
||||
|
||||
static <P extends MergeRequestNotifier> P preparePublisher(P publisher, AbstractBuild build) {
|
||||
P spyPublisher = spy(publisher);
|
||||
MergeRequest mergeRequest = new MergeRequest(MERGE_REQUEST_ID, MERGE_REQUEST_IID, "", "", "", PROJECT_ID, PROJECT_ID, "", "");
|
||||
doReturn(mergeRequest).when(spyPublisher).getMergeRequest(build);
|
||||
return spyPublisher;
|
||||
}
|
||||
|
||||
private TestUtility() { /* contains only static utility-methods */ }
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package com.dabsquared.gitlabjenkins.service;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
|
||||
class GitLabClientStub implements GitLabClient {
|
||||
private final Map<Pair<String, Class>, List<?>> data;
|
||||
private final Map<Pair<String, Class>, Integer> calls;
|
||||
|
||||
GitLabClientStub() {
|
||||
data = new HashMap<>();
|
||||
calls = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostUrl() {
|
||||
return "";
|
||||
}
|
||||
|
||||
void addBranches(String project, List<Branch> branches) {
|
||||
addData(project, Branch.class, branches);
|
||||
}
|
||||
|
||||
void addLabels(String project, List<Label> labels) {
|
||||
addData(project, Label.class, labels);
|
||||
}
|
||||
|
||||
int calls(String projectId, Class dataClass) {
|
||||
Pair<String, Class> key = createKey(projectId, dataClass);
|
||||
return calls.containsKey(key) ? calls.get(key) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Branch> getBranches(String projectId) {
|
||||
return getData(projectId, Branch.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Label> getLabels(String projectId) {
|
||||
return getData(projectId, Label.class);
|
||||
}
|
||||
|
||||
private void addData(String projectId, Class dataClass, List<?> datas) {
|
||||
data.put(createKey(projectId, dataClass), datas);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<T> getData(String projectId, Class dataClass) {
|
||||
Pair<String, Class> key = createKey(projectId, dataClass);
|
||||
if (!calls.containsKey(key)) {
|
||||
calls.put(key, 0);
|
||||
}
|
||||
|
||||
calls.put(key, calls.get(key) + 1);
|
||||
|
||||
return (List<T>) data.get(key);
|
||||
}
|
||||
|
||||
private Pair<String, Class> createKey(String projectId, Class dataClass) {
|
||||
return new ImmutablePair<>(projectId, dataClass);
|
||||
}
|
||||
|
||||
|
||||
/************** no implementation below ********************************/
|
||||
|
||||
@Override
|
||||
public Project createProject(String projectName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergeRequest createMergeRequest(Integer projectId, String sourceBranch, String targetBranch, String title) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project getProject(String projectName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project updateProject(String projectId, String name, String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProject(String projectId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProjectHook(String projectId, String url, Boolean pushEvents, Boolean mergeRequestEvents, Boolean noteEvents) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(String projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(Integer projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCommit(String projectId, String sha) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptMergeRequest(MergeRequest mr, String mergeCommitMessage, boolean shouldRemoveSourceBranch) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMergeRequestNote(MergeRequest mr, String body) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MergeRequest> getMergeRequests(String projectId, State state, int page, int perPage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Branch getBranch(String projectId, String branch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getCurrentUser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User addUser(String email, String username, String name, String password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User updateUser(String userId, String email, String username, String name, String password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pipeline> getPipelines(String projectName) {
|
||||
return emptyList();
|
||||
}
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
package com.dabsquared.gitlabjenkins.service;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Branch;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -14,29 +11,24 @@ import java.util.List;
|
|||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.model.builder.generated.BranchBuilder.branch;
|
||||
import static java.util.Arrays.asList;
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
|
||||
public class GitLabProjectBranchesServiceTest {
|
||||
|
||||
private final static List<String> BRANCH_NAMES_PROJECT_B = asList("master", "B-branch-1", "B-branch-2");
|
||||
|
||||
private GitLabProjectBranchesService branchesService;
|
||||
|
||||
@Mock
|
||||
private GitLabApi gitlabApi;
|
||||
private GitLabClientStub clientStub;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
List<Branch> branchNamesProjectA = convert(asList("master", "A-branch-1"));
|
||||
clientStub = new GitLabClientStub();
|
||||
clientStub.addBranches("groupOne/A", convert(asList("master", "A-branch-1")));
|
||||
clientStub.addBranches("groupOne/B", convert(BRANCH_NAMES_PROJECT_B));
|
||||
|
||||
// mock the gitlab factory
|
||||
when(gitlabApi.getBranches("groupOne/A")).thenReturn(branchNamesProjectA);
|
||||
when(gitlabApi.getBranches("groupOne/B")).thenReturn(convert(BRANCH_NAMES_PROJECT_B));
|
||||
|
||||
// never expire cache for tests
|
||||
branchesService = new GitLabProjectBranchesService();
|
||||
|
@ -45,7 +37,7 @@ public class GitLabProjectBranchesServiceTest {
|
|||
@Test
|
||||
public void shouldReturnBranchNamesFromGitlabApi() {
|
||||
// when
|
||||
List<String> actualBranchNames = branchesService.getBranches(gitlabApi, "git@git.example.com:groupOne/B.git");
|
||||
List<String> actualBranchNames = branchesService.getBranches(clientStub, "git@git.example.com:groupOne/B.git");
|
||||
|
||||
// then
|
||||
assertThat(actualBranchNames, is(BRANCH_NAMES_PROJECT_B));
|
||||
|
@ -54,11 +46,11 @@ public class GitLabProjectBranchesServiceTest {
|
|||
@Test
|
||||
public void shouldNotMakeUnnecessaryCallsToGitlabApiGetBranches() {
|
||||
// when
|
||||
branchesService.getBranches(gitlabApi, "git@git.example.com:groupOne/A.git");
|
||||
branchesService.getBranches(clientStub, "git@git.example.com:groupOne/A.git");
|
||||
|
||||
// then
|
||||
verify(gitlabApi, times(1)).getBranches("groupOne/A");
|
||||
verify(gitlabApi, times(0)).getBranches("groupOne/B");
|
||||
assertEquals(1, clientStub.calls("groupOne/A", Branch.class));
|
||||
assertEquals(0, clientStub.calls("groupOne/B", Branch.class));
|
||||
}
|
||||
|
||||
private List<Branch> convert(List<String> branchNames) {
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package com.dabsquared.gitlabjenkins.service;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Label;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -14,29 +11,24 @@ import java.util.List;
|
|||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.api.model.builder.generated.LabelBuilder.label;
|
||||
import static java.util.Arrays.asList;
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
|
||||
public class GitLabProjectLabelsServiceTest {
|
||||
|
||||
private final static List<String> LABELS_PROJECT_B = asList("label1", "label2", "label3");
|
||||
|
||||
private GitLabProjectLabelsService labelsService;
|
||||
|
||||
@Mock
|
||||
private GitLabApi gitlabApi;
|
||||
private GitLabClientStub clientStub;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
List<Label> labelsProjectA = convert(asList("label1", "label2"));
|
||||
|
||||
// mock the gitlab factory
|
||||
when(gitlabApi.getLabels("groupOne/A")).thenReturn(labelsProjectA);
|
||||
when(gitlabApi.getLabels("groupOne/B")).thenReturn(convert(LABELS_PROJECT_B));
|
||||
clientStub = new GitLabClientStub();
|
||||
clientStub.addLabels("groupOne/A", convert(asList("label1", "label2")));
|
||||
clientStub.addLabels("groupOne/B", convert(LABELS_PROJECT_B));
|
||||
|
||||
// never expire cache for tests
|
||||
labelsService = new GitLabProjectLabelsService();
|
||||
|
@ -45,7 +37,7 @@ public class GitLabProjectLabelsServiceTest {
|
|||
@Test
|
||||
public void shouldReturnLabelsFromGitlabApi() {
|
||||
// when
|
||||
List<String> actualLabels = labelsService.getLabels(gitlabApi, "git@git.example.com:groupOne/B.git");
|
||||
List<String> actualLabels = labelsService.getLabels(clientStub, "git@git.example.com:groupOne/B.git");
|
||||
|
||||
// then
|
||||
assertThat(actualLabels, is(LABELS_PROJECT_B));
|
||||
|
@ -54,11 +46,11 @@ public class GitLabProjectLabelsServiceTest {
|
|||
@Test
|
||||
public void shouldNotMakeUnnecessaryCallsToGitlabApiGetLabels() {
|
||||
// when
|
||||
labelsService.getLabels(gitlabApi, "git@git.example.com:groupOne/A.git");
|
||||
labelsService.getLabels(clientStub, "git@git.example.com:groupOne/A.git");
|
||||
|
||||
// then
|
||||
verify(gitlabApi, times(1)).getLabels("groupOne/A");
|
||||
verify(gitlabApi, times(0)).getLabels("groupOne/B");
|
||||
assertEquals(1, clientStub.calls("groupOne/A", Label.class));
|
||||
assertEquals(0, clientStub.calls("groupOne/B", Label.class));
|
||||
}
|
||||
|
||||
private List<Label> convert(List<String> labels) {
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
package com.dabsquared.gitlabjenkins.testing.gitlab.rule;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.JacksonConfig;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
|
||||
|
||||
import com.cloudbees.plugins.credentials.CredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.CredentialsScope;
|
||||
import com.cloudbees.plugins.credentials.CredentialsStore;
|
||||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
|
||||
import com.cloudbees.plugins.credentials.domains.Domain;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionConfig;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.impl.V3GitLabClientBuilder;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Pipeline;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Project;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.User;
|
||||
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
|
||||
import hudson.util.Secret;
|
||||
import jenkins.model.Jenkins;
|
||||
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
@ -26,25 +37,19 @@ import java.util.UUID;
|
|||
* @author Robin Müller
|
||||
*/
|
||||
public class GitLabRule implements TestRule {
|
||||
private static final String API_TOKEN_ID = "apiTokenId";
|
||||
private static final String PASSWORD = "integration-test";
|
||||
|
||||
private final GitLabApi client;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final String url;
|
||||
private final int postgresPort;
|
||||
|
||||
private GitLabClient clientCache;
|
||||
|
||||
private List<String> projectIds = new ArrayList<>();
|
||||
|
||||
public GitLabRule(String url, int postgresPort) {
|
||||
client = new ResteasyClientBuilder()
|
||||
.httpEngine(new ApacheHttpClient4Engine())
|
||||
.register(new JacksonJsonProvider())
|
||||
.register(new JacksonConfig())
|
||||
.register(new ApiHeaderTokenFilter(getApiToken(postgresPort))).build().target(url)
|
||||
.proxyBuilder(GitLabApi.class)
|
||||
.build();
|
||||
User user = client.getCurrentUser();
|
||||
username = user.getUsername();
|
||||
password = "integration-test";
|
||||
client.updateUser(user.getId().toString(), user.getEmail(), user.getUsername(), user.getName(), password);
|
||||
this.url = url;
|
||||
this.postgresPort = postgresPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,7 +58,11 @@ public class GitLabRule implements TestRule {
|
|||
}
|
||||
|
||||
public Project getProject(final String projectName) {
|
||||
return client.getProject(projectName);
|
||||
return client().getProject(projectName);
|
||||
}
|
||||
|
||||
public List<Pipeline> getPipelines(int projectId) {
|
||||
return client().getPipelines(String.valueOf(projectId));
|
||||
}
|
||||
|
||||
public List<String> getProjectIds() {
|
||||
|
@ -61,39 +70,59 @@ public class GitLabRule implements TestRule {
|
|||
}
|
||||
|
||||
public String createProject(ProjectRequest request) {
|
||||
Project project = client.createProject(request.getName());
|
||||
Project project = client().createProject(request.getName());
|
||||
projectIds.add(project.getId().toString());
|
||||
if (request.getWebHookUrl() != null && (request.isPushHook() || request.isMergeRequestHook() || request.isNoteHook())) {
|
||||
client.addProjectHook(project.getId().toString(), request.getWebHookUrl(), request.isPushHook(), request.isMergeRequestHook(), request.isNoteHook());
|
||||
client().addProjectHook(project.getId().toString(), request.getWebHookUrl(), request.isPushHook(), request.isMergeRequestHook(), request.isNoteHook());
|
||||
}
|
||||
return project.getHttpUrlToRepo();
|
||||
}
|
||||
|
||||
public void createMergeRequest(final Integer projectId,
|
||||
final String sourceBranch,
|
||||
final String targetBranch,
|
||||
final String title) {
|
||||
client.createMergeRequest(projectId, sourceBranch, targetBranch, title);
|
||||
public GitLabConnectionProperty createGitLabConnectionProperty() throws IOException {
|
||||
for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) {
|
||||
if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) {
|
||||
List<Domain> domains = credentialsStore.getDomains();
|
||||
credentialsStore.addCredentials(domains.get(0),
|
||||
new StringCredentialsImpl(CredentialsScope.SYSTEM, API_TOKEN_ID, "GitLab API Token", Secret.fromString(getApiToken())));
|
||||
}
|
||||
}
|
||||
|
||||
GitLabConnectionConfig config = Jenkins.getInstance().getDescriptorByType(GitLabConnectionConfig.class);
|
||||
GitLabConnection connection = new GitLabConnection("test", url, API_TOKEN_ID, new V3GitLabClientBuilder(), true,10, 10);
|
||||
config.addConnection(connection);
|
||||
config.save();
|
||||
return new GitLabConnectionProperty(connection.getName());
|
||||
}
|
||||
|
||||
public MergeRequest createMergeRequest(final Integer projectId,
|
||||
final String sourceBranch,
|
||||
final String targetBranch,
|
||||
final String title) {
|
||||
return client().createMergeRequest(projectId, sourceBranch, targetBranch, title);
|
||||
}
|
||||
|
||||
public void createMergeRequestNote(MergeRequest mr, String body) {
|
||||
client().createMergeRequestNote(mr, body);
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
return client().getCurrentUser().getUsername();
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
return PASSWORD;
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
for (String projectId : projectIds) {
|
||||
String randomProjectName = UUID.randomUUID().toString();
|
||||
// rename the project before deleting as the deletion will take a while
|
||||
client.updateProject(projectId, randomProjectName, randomProjectName);
|
||||
client.deleteProject(projectId);
|
||||
client().updateProject(projectId, randomProjectName, randomProjectName);
|
||||
client().deleteProject(projectId);
|
||||
}
|
||||
}
|
||||
|
||||
private String getApiToken(int postgresPort) {
|
||||
private String getApiToken() {
|
||||
try {
|
||||
Class.forName("org.postgresql.Driver");
|
||||
try (Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:" + postgresPort + "/gitlabhq_production", "gitlab", "password")) {
|
||||
|
@ -106,6 +135,15 @@ public class GitLabRule implements TestRule {
|
|||
}
|
||||
}
|
||||
|
||||
private GitLabClient client() {
|
||||
if (clientCache == null) {
|
||||
clientCache = new V3GitLabClientBuilder().buildClient(url, getApiToken(), false, -1, -1);
|
||||
User user = clientCache.getCurrentUser();
|
||||
client().updateUser(user.getId().toString(), user.getEmail(), user.getUsername(), user.getName(), PASSWORD);
|
||||
}
|
||||
return clientCache;
|
||||
}
|
||||
|
||||
private class GitlabStatement extends Statement {
|
||||
private final Statement next;
|
||||
|
||||
|
@ -122,16 +160,4 @@ public class GitLabRule implements TestRule {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ApiHeaderTokenFilter implements ClientRequestFilter {
|
||||
private final String gitlabApiToken;
|
||||
|
||||
ApiHeaderTokenFilter(String gitlabApiToken) {
|
||||
this.gitlabApiToken = gitlabApiToken;
|
||||
}
|
||||
|
||||
public void filter(ClientRequestContext requestContext) throws IOException {
|
||||
requestContext.getHeaders().putSingle("PRIVATE-TOKEN", gitlabApiToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,17 @@ public class ProjectRequest {
|
|||
private final boolean pushHook;
|
||||
private final boolean mergeRequestHook;
|
||||
private final boolean noteHook;
|
||||
private final boolean pipelineHook;
|
||||
|
||||
@GeneratePojoBuilder(intoPackage = "*.builder.generated", withFactoryMethod = "*")
|
||||
public ProjectRequest(String name, String webHookUrl, boolean pushHook, boolean mergeRequestHook, boolean noteHook) {
|
||||
public ProjectRequest(String name, String webHookUrl, boolean pushHook, boolean mergeRequestHook, boolean noteHook,
|
||||
boolean pipelineHook) {
|
||||
this.name = name;
|
||||
this.webHookUrl = webHookUrl;
|
||||
this.pushHook = pushHook;
|
||||
this.mergeRequestHook = mergeRequestHook;
|
||||
this.noteHook = noteHook;
|
||||
this.pipelineHook = pipelineHook;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -41,4 +44,8 @@ public class ProjectRequest {
|
|||
public boolean isNoteHook() {
|
||||
return noteHook;
|
||||
}
|
||||
|
||||
public boolean isPipelineHook() {
|
||||
return pipelineHook;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,34 @@
|
|||
package com.dabsquared.gitlabjenkins.testing.integration;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.GitLabPushTrigger;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.Pipeline;
|
||||
import com.dabsquared.gitlabjenkins.publisher.GitLabCommitStatusPublisher;
|
||||
import com.dabsquared.gitlabjenkins.testing.gitlab.rule.GitLabRule;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterType;
|
||||
import hudson.Launcher;
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.Descriptor;
|
||||
import hudson.model.FreeStyleProject;
|
||||
import hudson.tasks.Publisher;
|
||||
import hudson.util.DescribableList;
|
||||
import hudson.util.OneShotEvent;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.StoredConfig;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.jvnet.hudson.test.SleepBuilder;
|
||||
import org.jvnet.hudson.test.TestBuilder;
|
||||
import org.jvnet.hudson.test.TestNotifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
|
@ -28,7 +40,11 @@ import java.util.List;
|
|||
|
||||
import static com.dabsquared.gitlabjenkins.builder.generated.GitLabPushTriggerBuilder.gitLabPushTrigger;
|
||||
import static com.dabsquared.gitlabjenkins.testing.gitlab.rule.builder.generated.ProjectRequestBuilder.projectRequest;
|
||||
import static java.lang.Integer.parseInt;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
|
||||
import static org.hamcrest.collection.IsEmptyCollection.empty;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -37,10 +53,10 @@ import static org.junit.Assert.assertTrue;
|
|||
* @author Robin Müller
|
||||
*/
|
||||
public class GitLabIT {
|
||||
private static final String GITLAB_URL = "http://localhost:" + System.getProperty("gitlab.http.port", "10080");
|
||||
|
||||
@Rule
|
||||
public GitLabRule gitlab = new GitLabRule("http://localhost:" + System.getProperty("gitlab.http.port", "10080"),
|
||||
Integer.parseInt(System.getProperty("postgres.port", "5432")));
|
||||
public GitLabRule gitlab = new GitLabRule(GITLAB_URL, parseInt(System.getProperty("postgres.port", "5432")));
|
||||
|
||||
@Rule
|
||||
public JenkinsRule jenkins = new JenkinsRule();
|
||||
|
@ -50,12 +66,6 @@ public class GitLabIT {
|
|||
|
||||
@Test
|
||||
public void buildOnPush() throws IOException, InterruptedException, GitAPIException {
|
||||
final String httpUrl = gitlab.createProject(projectRequest()
|
||||
.withName("test")
|
||||
.withWebHookUrl("http://" + getDocker0Ip() + ":" + jenkins.getURL().getPort() + "/jenkins/project/test")
|
||||
.withPushHook(true)
|
||||
.build());
|
||||
|
||||
final OneShotEvent buildTriggered = new OneShotEvent();
|
||||
FreeStyleProject project = jenkins.createFreeStyleProject("test");
|
||||
GitLabPushTrigger trigger = gitLabPushTrigger().withTriggerOnPush(true).withBranchFilterType(BranchFilterType.All).build();
|
||||
|
@ -70,45 +80,15 @@ public class GitLabIT {
|
|||
});
|
||||
project.setQuietPeriod(0);
|
||||
|
||||
Git.init().setDirectory(tmp.getRoot()).call();
|
||||
tmp.newFile("test");
|
||||
Git git = Git.open(tmp.getRoot());
|
||||
git.add().addFilepattern("test");
|
||||
git.commit().setMessage("test").call();
|
||||
StoredConfig config = git.getRepository().getConfig();
|
||||
config.setString("remote", "origin", "url", httpUrl);
|
||||
config.save();
|
||||
git.push()
|
||||
.setRemote("origin").add("master")
|
||||
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitlab.getUsername(), gitlab.getPassword()))
|
||||
.call();
|
||||
createGitLabProject(false,true, true, false);
|
||||
|
||||
buildTriggered.block(10000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void buildOnMergeRequest() throws IOException, InterruptedException, GitAPIException {
|
||||
|
||||
// check for clean slate
|
||||
assertTrue(gitlab.getProjectIds().isEmpty());
|
||||
|
||||
final String httpUrl = gitlab.createProject(projectRequest()
|
||||
.withName("test")
|
||||
.withWebHookUrl("http://" + getDocker0Ip() + ":" + jenkins.getURL().getPort() + "/jenkins/project/test")
|
||||
.withMergeRequestHook(true)
|
||||
.build());
|
||||
|
||||
// Fix: Hack to get the project id
|
||||
// A preferable approach would be here to get the target project by name using getProject function of the
|
||||
// GitLabRule and to use the id from the project instance. However, due to a bug in GitLab (tested on 8.6.1)
|
||||
// retrieving the project by name is not properly working.
|
||||
// (see issue https://github.com/gitlabhq/gitlabhq/issues/4921).
|
||||
// Once the issue is resolved, replace this implementation.
|
||||
final List<String> projectIds = gitlab.getProjectIds();
|
||||
assertSame(projectIds.size(), 1);
|
||||
final Integer projectId = Integer.parseInt(projectIds.get(0));
|
||||
|
||||
final OneShotEvent buildTriggered = new OneShotEvent();
|
||||
FreeStyleProject project = jenkins.createFreeStyleProject("test");
|
||||
GitLabPushTrigger trigger = gitLabPushTrigger().withTriggerOnMergeRequest(true).withBranchFilterType(BranchFilterType.All).build();
|
||||
|
@ -123,30 +103,9 @@ public class GitLabIT {
|
|||
});
|
||||
project.setQuietPeriod(0);
|
||||
|
||||
// Setup git repository
|
||||
Git.init().setDirectory(tmp.getRoot()).call();
|
||||
Git git = Git.open(tmp.getRoot());
|
||||
StoredConfig config = git.getRepository().getConfig();
|
||||
config.setString("remote", "origin", "url", httpUrl);
|
||||
config.save();
|
||||
Pair<Integer, String> gitlabData = createGitLabProject(true,false, false, true);
|
||||
|
||||
// Setup remote master branch
|
||||
tmp.newFile("test");
|
||||
git.add().addFilepattern("test");
|
||||
git.commit().setMessage("test").call();
|
||||
git.push()
|
||||
.setRemote("origin").add("master")
|
||||
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitlab.getUsername(), gitlab.getPassword()))
|
||||
.call();
|
||||
|
||||
// Setup remote feature branch
|
||||
git.checkout().setName("feature").setCreateBranch(true).call();
|
||||
tmp.newFile("feature");
|
||||
git.commit().setMessage("feature").call();
|
||||
git.push().setRemote("origin").add("feature").setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitlab.getUsername(), gitlab.getPassword()))
|
||||
.call();
|
||||
|
||||
gitlab.createMergeRequest(projectId, "feature", "master", "Merge feature branch to master.");
|
||||
gitlab.createMergeRequest(gitlabData.getLeft(), "feature", "master", "Merge feature branch to master.");
|
||||
|
||||
buildTriggered.block(10000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
|
@ -154,31 +113,12 @@ public class GitLabIT {
|
|||
|
||||
@Test
|
||||
public void buildOnNote() throws IOException, InterruptedException, GitAPIException {
|
||||
|
||||
// check for clean slate
|
||||
assertTrue(gitlab.getProjectIds().isEmpty());
|
||||
|
||||
final String httpUrl = gitlab.createProject(projectRequest()
|
||||
.withName("test")
|
||||
.withWebHookUrl("http://" + getDocker0Ip() + ":" + jenkins.getURL().getPort() + "/jenkins/project/test")
|
||||
.withNoteHook(true)
|
||||
.build());
|
||||
|
||||
// Fix: Hack to get the project id
|
||||
// A preferable approach would be here to get the target project by name using getProject function of the
|
||||
// GitLabRule and to use the id from the project instance. However, due to a bug in GitLab (tested on 8.6.1)
|
||||
// retrieving the project by name is not properly working.
|
||||
// (see issue https://github.com/gitlabhq/gitlabhq/issues/4921).
|
||||
// Once the issue is resolved, replace this implementation.
|
||||
final List<String> projectIds = gitlab.getProjectIds();
|
||||
assertSame(projectIds.size(), 1);
|
||||
final Integer projectId = Integer.parseInt(projectIds.get(0));
|
||||
|
||||
final OneShotEvent buildTriggered = new OneShotEvent();
|
||||
FreeStyleProject project = jenkins.createFreeStyleProject("test");
|
||||
GitLabPushTrigger trigger = gitLabPushTrigger().withTriggerOnNoteRequest(true).withBranchFilterType(BranchFilterType.All).build();
|
||||
project.addTrigger(trigger);
|
||||
trigger.start(project, true);
|
||||
GitLabPushTrigger trigger = gitLabPushTrigger()
|
||||
.withTriggerOnNoteRequest(true)
|
||||
.withNoteRegex(".*test.*")
|
||||
.withBranchFilterType(BranchFilterType.All).build();
|
||||
project.getBuildersList().add(new TestBuilder() {
|
||||
@Override
|
||||
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
|
||||
|
@ -188,33 +128,132 @@ public class GitLabIT {
|
|||
});
|
||||
project.setQuietPeriod(0);
|
||||
|
||||
Pair<Integer, String> gitlabData = createGitLabProject(true, false, true, false);
|
||||
|
||||
// create merge-request
|
||||
MergeRequest mr = gitlab.createMergeRequest(gitlabData.getLeft(), "feature", "master", "Merge feature branch to master.");
|
||||
|
||||
// add trigger after push/merge-request so it may only receive the note-hook
|
||||
project.addTrigger(trigger);
|
||||
trigger.start(project, true);
|
||||
|
||||
gitlab.createMergeRequestNote(mr, "this is a test note");
|
||||
|
||||
buildTriggered.block(20000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reportBuildStatus() throws IOException, InterruptedException, GitAPIException {
|
||||
final OneShotEvent buildTriggered = new OneShotEvent();
|
||||
final OneShotEvent buildReported = new OneShotEvent();
|
||||
|
||||
GitLabPushTrigger trigger = gitLabPushTrigger()
|
||||
.withTriggerOnPush(true)
|
||||
.withBranchFilterType(BranchFilterType.All)
|
||||
.build();
|
||||
|
||||
FreeStyleProject project = jenkins.createFreeStyleProject("test");
|
||||
project.addProperty(gitlab.createGitLabConnectionProperty());
|
||||
project.addTrigger(trigger);
|
||||
|
||||
project.getBuildersList().add(new TestBuilder() {
|
||||
@Override
|
||||
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
|
||||
buildTriggered.signal();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
project.getBuildersList().add(new SleepBuilder(20000));
|
||||
|
||||
DescribableList<Publisher, Descriptor<Publisher>> publishers = project.getPublishersList();
|
||||
publishers.add(new GitLabCommitStatusPublisher("integration-test", false));
|
||||
publishers.add(new TestNotifier() {
|
||||
@Override
|
||||
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
|
||||
buildReported.signal();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
trigger.start(project, true);
|
||||
project.setQuietPeriod(0);
|
||||
|
||||
|
||||
Pair<Integer, String> gitlabData = createGitLabProject(false,true, true, false);
|
||||
assertThat(gitlab.getPipelines(gitlabData.getLeft()), empty());
|
||||
|
||||
buildTriggered.block(20000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
assertPipelineStatus(gitlabData, "running");
|
||||
|
||||
buildReported.block(40000);
|
||||
assertThat(buildReported.isSignaled(), is(true));
|
||||
|
||||
Thread.sleep(5000); // wait for gitlab to update
|
||||
assertPipelineStatus(gitlabData, "success");
|
||||
}
|
||||
|
||||
private void assertPipelineStatus(Pair<Integer, String> gitlabData, String status) {
|
||||
List<Pipeline> pipelines = gitlab.getPipelines(gitlabData.getLeft());
|
||||
assertThat(pipelines, hasSize(1));
|
||||
|
||||
Pipeline pipeline = pipelines.get(0);
|
||||
assertEquals(gitlabData.getRight(), pipeline.getSha());
|
||||
assertEquals(status, pipeline.getStatus());
|
||||
}
|
||||
|
||||
private Pair<Integer, String> createGitLabProject(boolean addFeatureBranch, boolean withPushHook, boolean withNoteHook, boolean withMergeRequestHook) throws IOException, GitAPIException {
|
||||
// check for clean slate
|
||||
assertTrue(gitlab.getProjectIds().isEmpty());
|
||||
|
||||
String url = gitlab.createProject(projectRequest()
|
||||
.withName("test")
|
||||
.withWebHookUrl("http://" + getDocker0Ip() + ":" + jenkins.getURL().getPort() + "/jenkins/project/test")
|
||||
.withPushHook(withPushHook)
|
||||
.withNoteHook(withNoteHook)
|
||||
.withMergeRequestHook(withMergeRequestHook)
|
||||
.build());
|
||||
|
||||
String sha = initGitLabProject(url, addFeatureBranch);
|
||||
|
||||
// Fix: Hack to get the project id
|
||||
// A preferable approach would be here to get the target project by name using getProject function of the
|
||||
// GitLabRule and to use the id from the project instance. However, due to a bug in GitLab (tested on 8.6.1)
|
||||
// retrieving the project by name is not properly working.
|
||||
// (see issue https://github.com/gitlabhq/gitlabhq/issues/4921).
|
||||
// Once the issue is resolved, replace this implementation.
|
||||
List<String> projectIds = gitlab.getProjectIds();
|
||||
assertSame(projectIds.size(), 1);
|
||||
return new ImmutablePair<>(parseInt(projectIds.get(0)), sha);
|
||||
}
|
||||
|
||||
private String initGitLabProject(String url, boolean addFeatureBranch) throws GitAPIException, IOException {
|
||||
// Setup git repository
|
||||
Git.init().setDirectory(tmp.getRoot()).call();
|
||||
Git git = Git.open(tmp.getRoot());
|
||||
StoredConfig config = git.getRepository().getConfig();
|
||||
config.setString("remote", "origin", "url", httpUrl);
|
||||
config.setString("remote", "origin", "url", url);
|
||||
config.save();
|
||||
|
||||
// Setup remote master branch
|
||||
tmp.newFile("test");
|
||||
git.add().addFilepattern("test");
|
||||
git.commit().setMessage("test").call();
|
||||
RevCommit commit = git.commit().setMessage("test").call();
|
||||
git.push()
|
||||
.setRemote("origin").add("master")
|
||||
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitlab.getUsername(), gitlab.getPassword()))
|
||||
.call();
|
||||
|
||||
// Setup remote feature branch
|
||||
git.checkout().setName("feature").setCreateBranch(true).call();
|
||||
tmp.newFile("feature");
|
||||
git.commit().setMessage("feature").call();
|
||||
git.push().setRemote("origin").add("feature").setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitlab.getUsername(), gitlab.getPassword()))
|
||||
.call();
|
||||
if (addFeatureBranch) {
|
||||
// Setup remote feature branch
|
||||
git.checkout().setName("feature").setCreateBranch(true).call();
|
||||
tmp.newFile("feature");
|
||||
commit = git.commit().setMessage("feature").call();
|
||||
git.push().setRemote("origin").add("feature").setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitlab.getUsername(), gitlab.getPassword()))
|
||||
.call();
|
||||
}
|
||||
|
||||
gitlab.createMergeRequest(projectId, "feature", "master", "Merge feature branch to master.");
|
||||
|
||||
buildTriggered.block(10000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
return commit.getName();
|
||||
}
|
||||
|
||||
private String getDocker0Ip() {
|
||||
|
|
|
@ -16,6 +16,7 @@ public class NameBasedFilterTest {
|
|||
|
||||
assertThat(nameBasedFilter.isBranchAllowed("master"), is(true));
|
||||
assertThat(nameBasedFilter.isBranchAllowed("develop"), is(true));
|
||||
assertThat(nameBasedFilter.isBranchAllowed("not-included-branch"), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -35,4 +36,29 @@ public class NameBasedFilterTest {
|
|||
assertThat(nameBasedFilter.isBranchAllowed("develop"), is(false));
|
||||
assertThat(nameBasedFilter.isBranchAllowed("not-excluded-and-not-included-branch"), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowIncludeAndExcludeToBeNull() {
|
||||
NameBasedFilter nameBasedFilter = new NameBasedFilter(null, null);
|
||||
|
||||
assertThat(nameBasedFilter.isBranchAllowed("master"), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowIncludeToBeNull() {
|
||||
NameBasedFilter nameBasedFilter = new NameBasedFilter(null, "master, develop");
|
||||
|
||||
assertThat(nameBasedFilter.isBranchAllowed("master"), is(false));
|
||||
assertThat(nameBasedFilter.isBranchAllowed("develop"), is(false));
|
||||
assertThat(nameBasedFilter.isBranchAllowed("not-excluded-branch"), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowExcludeToBeNull() {
|
||||
NameBasedFilter nameBasedFilter = new NameBasedFilter("master, develop", null);
|
||||
|
||||
assertThat(nameBasedFilter.isBranchAllowed("master"), is(true));
|
||||
assertThat(nameBasedFilter.isBranchAllowed("develop"), is(true));
|
||||
assertThat(nameBasedFilter.isBranchAllowed("not-included-branch"), is(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.merge;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.Action;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.builder.generated.MergeRequestObjectAttributesBuilder;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterFactory;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterType;
|
||||
import hudson.Launcher;
|
||||
|
@ -10,11 +12,18 @@ import hudson.model.FreeStyleProject;
|
|||
import hudson.plugins.git.GitSCM;
|
||||
import hudson.util.OneShotEvent;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.NoHeadException;
|
||||
import org.eclipse.jgit.api.errors.NoMessageException;
|
||||
import org.eclipse.jgit.api.errors.UnmergedPathsException;
|
||||
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
||||
import org.eclipse.jgit.errors.AmbiguousObjectException;
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -24,6 +33,7 @@ import org.jvnet.hudson.test.TestBuilder;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.hook.model.builder.generated.CommitBuilder.commit;
|
||||
|
@ -47,13 +57,6 @@ public class MergeRequestHookTriggerHandlerImplTest {
|
|||
@Rule
|
||||
public TemporaryFolder tmp = new TemporaryFolder();
|
||||
|
||||
private MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(Arrays.asList(State.opened, State.reopened), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_ciSkip() throws IOException, InterruptedException {
|
||||
final OneShotEvent buildTriggered = new OneShotEvent();
|
||||
|
@ -66,6 +69,7 @@ public class MergeRequestHookTriggerHandlerImplTest {
|
|||
}
|
||||
});
|
||||
project.setQuietPeriod(0);
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(Arrays.asList(State.opened, State.reopened), false);
|
||||
mergeRequestHookTriggerHandler.handle(project, mergeRequestHook()
|
||||
.withObjectAttributes(mergeRequestObjectAttributes().withDescription("[ci-skip]").build())
|
||||
.build(), true, BranchFilterFactory.newBranchFilter(branchFilterConfig().build(BranchFilterType.All)),
|
||||
|
@ -77,7 +81,84 @@ public class MergeRequestHookTriggerHandlerImplTest {
|
|||
|
||||
@Test
|
||||
public void mergeRequest_build() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
Git.init().setDirectory(tmp.getRoot()).call();
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(Arrays.asList(State.opened, State.reopened), false);
|
||||
OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, State.opened);
|
||||
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_build_when_accepted() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(Arrays.asList(State.merged), false);
|
||||
OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, State.merged);
|
||||
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_build_when_closed() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(Arrays.asList(State.closed), false);
|
||||
OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, State.closed);
|
||||
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_do_not_build_when_accepted() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(Arrays.asList(State.opened, State.updated), false);
|
||||
OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, State.merged);
|
||||
|
||||
assertThat(buildTriggered.isSignaled(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_do_not_build_when_closed() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(Arrays.asList(State.opened, State.updated), false);
|
||||
OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, State.closed);
|
||||
|
||||
assertThat(buildTriggered.isSignaled(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_build_when_approved() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(EnumSet.noneOf(State.class), EnumSet.of(Action.approved), false);
|
||||
OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, Action.approved);
|
||||
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_build_only_when_approved_and_not_when_opened() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
mergeRequest_build_only_when_approved(Action.open);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRequest_build_only_when_approved_and_not_when_updated() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
mergeRequest_build_only_when_approved(Action.update);
|
||||
}
|
||||
|
||||
|
||||
private void mergeRequest_build_only_when_approved(Action action)
|
||||
throws GitAPIException, IOException, InterruptedException {
|
||||
MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = new MergeRequestHookTriggerHandlerImpl(EnumSet.noneOf(State.class), EnumSet.of(Action.approved), false);
|
||||
OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, action);
|
||||
|
||||
assertThat(buildTriggered.isSignaled(), is(false));
|
||||
}
|
||||
|
||||
private OneShotEvent doHandle(MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler, Action action) throws GitAPIException, IOException, InterruptedException {
|
||||
return doHandle(mergeRequestHookTriggerHandler, defaultMergeRequestObjectAttributes().withState(State.opened).withAction(action));
|
||||
}
|
||||
|
||||
private OneShotEvent doHandle(MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler, State state) throws GitAPIException, IOException, InterruptedException {
|
||||
return doHandle(mergeRequestHookTriggerHandler, defaultMergeRequestObjectAttributes().withState(state));
|
||||
}
|
||||
|
||||
private OneShotEvent doHandle(MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler,
|
||||
MergeRequestObjectAttributesBuilder objectAttributes) throws GitAPIException, IOException, NoHeadException,
|
||||
NoMessageException, UnmergedPathsException, ConcurrentRefUpdateException, WrongRepositoryStateException,
|
||||
AmbiguousObjectException, IncorrectObjectTypeException, MissingObjectException, InterruptedException {
|
||||
Git.init().setDirectory(tmp.getRoot()).call();
|
||||
tmp.newFile("test");
|
||||
Git git = Git.open(tmp.getRoot());
|
||||
git.add().addFilepattern("test");
|
||||
|
@ -96,42 +177,46 @@ public class MergeRequestHookTriggerHandlerImplTest {
|
|||
}
|
||||
});
|
||||
project.setQuietPeriod(0);
|
||||
mergeRequestHookTriggerHandler.handle(project, mergeRequestHook()
|
||||
.withObjectAttributes(mergeRequestObjectAttributes()
|
||||
.withTargetBranch("refs/heads/" + git.nameRev().add(head).call().get(head))
|
||||
.withState(State.opened)
|
||||
.withIid(1)
|
||||
.withTitle("test")
|
||||
.withTargetProjectId(1)
|
||||
.withSourceProjectId(1)
|
||||
.withSourceBranch("feature")
|
||||
.withTargetBranch("master")
|
||||
.withLastCommit(commit().withAuthor(user().withName("test").build()).withId(commit.getName()).build())
|
||||
.withSource(project()
|
||||
.withName("test")
|
||||
.withNamespace("test-namespace")
|
||||
.withHomepage("https://gitlab.org/test")
|
||||
.withUrl("git@gitlab.org:test.git")
|
||||
.withSshUrl("git@gitlab.org:test.git")
|
||||
.withHttpUrl("https://gitlab.org/test.git")
|
||||
.build())
|
||||
.withTarget(project()
|
||||
.withName("test")
|
||||
.withNamespace("test-namespace")
|
||||
.withHomepage("https://gitlab.org/test")
|
||||
.withUrl("git@gitlab.org:test.git")
|
||||
.withSshUrl("git@gitlab.org:test.git")
|
||||
.withHttpUrl("https://gitlab.org/test.git")
|
||||
.build())
|
||||
.build())
|
||||
mergeRequestHookTriggerHandler.handle(project, mergeRequestHook()
|
||||
.withObjectAttributes(objectAttributes
|
||||
.withTargetBranch("refs/heads/" + git.nameRev().add(head).call().get(head))
|
||||
.withLastCommit(commit().withAuthor(user().withName("test").build()).withId(commit.getName()).build())
|
||||
.build())
|
||||
.withProject(project()
|
||||
.withWebUrl("https://gitlab.org/test.git")
|
||||
.build()
|
||||
)
|
||||
.build(), true, BranchFilterFactory.newBranchFilter(branchFilterConfig().build(BranchFilterType.All)),
|
||||
newMergeRequestLabelFilter(null));
|
||||
newMergeRequestLabelFilter(null));
|
||||
|
||||
buildTriggered.block(10000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
return buildTriggered;
|
||||
}
|
||||
|
||||
private MergeRequestObjectAttributesBuilder defaultMergeRequestObjectAttributes() {
|
||||
return mergeRequestObjectAttributes()
|
||||
.withIid(1)
|
||||
.withTitle("test")
|
||||
.withTargetProjectId(1)
|
||||
.withSourceProjectId(1)
|
||||
.withSourceBranch("feature")
|
||||
.withTargetBranch("master")
|
||||
.withSource(project()
|
||||
.withName("test")
|
||||
.withNamespace("test-namespace")
|
||||
.withHomepage("https://gitlab.org/test")
|
||||
.withUrl("git@gitlab.org:test.git")
|
||||
.withSshUrl("git@gitlab.org:test.git")
|
||||
.withHttpUrl("https://gitlab.org/test.git")
|
||||
.build())
|
||||
.withTarget(project()
|
||||
.withName("test")
|
||||
.withNamespace("test-namespace")
|
||||
.withHomepage("https://gitlab.org/test")
|
||||
.withUrl("git@gitlab.org:test.git")
|
||||
.withSshUrl("git@gitlab.org:test.git")
|
||||
.withHttpUrl("https://gitlab.org/test.git")
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
package com.dabsquared.gitlabjenkins.trigger.handler.pipeline;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PipelineHook;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.User;
|
||||
import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterType;
|
||||
import hudson.Launcher;
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.FreeStyleProject;
|
||||
import hudson.util.OneShotEvent;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.jvnet.hudson.test.TestBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.hook.model.builder.generated.PipelineEventObjectAttributesBuilder.pipelineEventObjectAttributes;
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.hook.model.builder.generated.PipelineHookBuilder.pipelineHook;
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.hook.model.builder.generated.ProjectBuilder.project;
|
||||
import static com.dabsquared.gitlabjenkins.gitlab.hook.model.builder.generated.RepositoryBuilder.repository;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterConfig.BranchFilterConfigBuilder.branchFilterConfig;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterFactory.newBranchFilter;
|
||||
import static com.dabsquared.gitlabjenkins.trigger.filter.MergeRequestLabelFilterFactory.newMergeRequestLabelFilter;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
public class PipelineHookTriggerHandlerImplTest {
|
||||
|
||||
@ClassRule
|
||||
public static JenkinsRule jenkins = new JenkinsRule();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmp = new TemporaryFolder();
|
||||
|
||||
private PipelineHookTriggerHandler pipelineHookTriggerHandler;
|
||||
private PipelineHook pipelineHook;
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException, GitAPIException {
|
||||
|
||||
List<String> allowedStates = new ArrayList<>();
|
||||
allowedStates.add("success");
|
||||
|
||||
User user = new User();
|
||||
user.setName("test");
|
||||
user.setId(1);
|
||||
|
||||
Git.init().setDirectory(tmp.getRoot()).call();
|
||||
tmp.newFile("test");
|
||||
Git git = Git.open(tmp.getRoot());
|
||||
git.add().addFilepattern("test");
|
||||
git.commit().setMessage("test").call();
|
||||
ObjectId head = git.getRepository().resolve(Constants.HEAD);
|
||||
|
||||
pipelineHookTriggerHandler = new PipelineHookTriggerHandlerImpl(allowedStates);
|
||||
pipelineHook = pipelineHook()
|
||||
.withProjectId(1)
|
||||
.withUser(user)
|
||||
.withRepository(repository()
|
||||
.withName("test")
|
||||
.withHomepage("https://gitlab.org/test")
|
||||
.withUrl("git@gitlab.org:test.git")
|
||||
.withGitSshUrl("git@gitlab.org:test.git")
|
||||
.withGitHttpUrl("https://gitlab.org/test.git")
|
||||
.build())
|
||||
.withProject(project()
|
||||
.withNamespace("test-namespace")
|
||||
.withWebUrl("https://gitlab.org/test")
|
||||
.withId(1)
|
||||
.build())
|
||||
.withObjectAttributes(pipelineEventObjectAttributes()
|
||||
.withId(1)
|
||||
.withStatus("success")
|
||||
.withSha("bcbb5ec396a2c0f828686f14fac9b80b780504f2")
|
||||
.withStages(new ArrayList<String>())
|
||||
.withRef("refs/heads/" + git.nameRev().add(head).call().get(head))
|
||||
.build())
|
||||
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* always triggers since pipeline events do not contain ci skip message
|
||||
*/
|
||||
public void pipeline_ciSkip() throws IOException, InterruptedException {
|
||||
final OneShotEvent buildTriggered = new OneShotEvent();
|
||||
FreeStyleProject project = jenkins.createFreeStyleProject();
|
||||
project.getBuildersList().add(new TestBuilder() {
|
||||
@Override
|
||||
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
|
||||
buildTriggered.signal();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
project.setQuietPeriod(0);
|
||||
pipelineHookTriggerHandler.handle(project, pipelineHook , true, newBranchFilter(branchFilterConfig().build(BranchFilterType.All)),
|
||||
newMergeRequestLabelFilter(null));
|
||||
|
||||
buildTriggered.block(10000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pipeline_build() throws IOException, InterruptedException, GitAPIException, ExecutionException {
|
||||
|
||||
final OneShotEvent buildTriggered = new OneShotEvent();
|
||||
FreeStyleProject project = jenkins.createFreeStyleProject();
|
||||
project.getBuildersList().add(new TestBuilder() {
|
||||
@Override
|
||||
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
|
||||
buildTriggered.signal();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
project.setQuietPeriod(0);
|
||||
|
||||
pipelineHookTriggerHandler.handle(project, pipelineHook, false, newBranchFilter(branchFilterConfig().build(BranchFilterType.All)),
|
||||
newMergeRequestLabelFilter(null));
|
||||
|
||||
buildTriggered.block(10000);
|
||||
assertThat(buildTriggered.isSignaled(), is(true));
|
||||
}
|
||||
}
|
|
@ -101,6 +101,7 @@ public class PushHookTriggerHandlerImplTest {
|
|||
.withBefore("0000000000000000000000000000000000000000")
|
||||
.withProjectId(1)
|
||||
.withUserName("test")
|
||||
.withObjectKind("tag_push")
|
||||
.withRepository(repository()
|
||||
.withName("test")
|
||||
.withHomepage("https://gitlab.org/test")
|
||||
|
@ -151,6 +152,7 @@ public class PushHookTriggerHandlerImplTest {
|
|||
.withBefore("0000000000000000000000000000000000000000")
|
||||
.withProjectId(1)
|
||||
.withUserName("test")
|
||||
.withObjectKind("push")
|
||||
.withRepository(repository()
|
||||
.withName("test")
|
||||
.withHomepage("https://gitlab.org/test")
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
package com.dabsquared.gitlabjenkins.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import hudson.model.Job;
|
||||
import hudson.model.Run;
|
||||
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.AbstractProject;
|
||||
import hudson.plugins.git.Revision;
|
||||
import hudson.plugins.git.util.Build;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import hudson.util.RunList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* @author Joshua Barker
|
||||
*/
|
||||
|
||||
public class BuildUtilTest {
|
||||
|
||||
private static final String SHA1 = "0616d12a3a24068691027a1e113147e3c1cfa2f4";
|
||||
private static final String SHALIB = "a53131154f6dfc0d1642451679fb977c5ecf31c0";
|
||||
private static final String WRONGSHA = "5f106d47c2ce17dd65774c12c0826785d16b26f7";
|
||||
|
||||
public void getBuildBySHA1WithoutMergeBuilds_sha_found(){
|
||||
Job<?,?> project = createProject(SHA1);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1WithoutMergeBuilds(project, SHA1);
|
||||
assertThat(build, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBuildBySHA1WithoutMergeBuilds_sha_missing(){
|
||||
Job<?,?> project = createProject(SHA1);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1WithoutMergeBuilds(project, WRONGSHA);
|
||||
assertThat(build, is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBuildBySHA1WithoutMergeBuilds_libraryFirst(){
|
||||
Job<?,?> project = createProject(SHA1, SHALIB);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1WithoutMergeBuilds(project, SHA1);
|
||||
assertThat(build, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBuildBySHA1WithoutMergeBuilds_libraryLast(){
|
||||
Job<?,?> project = createProject(SHA1, SHALIB);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1WithoutMergeBuilds(project, SHA1);
|
||||
assertThat(build, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBuildBySHA1IncludingMergeBuilds_sha_found(){
|
||||
Job<?,?> project = createProject(SHA1);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1IncludingMergeBuilds(project, SHA1);
|
||||
assertThat(build, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBuildBySHA1IncludingMergeBuilds_sha_missing(){
|
||||
Job<?,?> project = createProject(SHA1);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1IncludingMergeBuilds(project, WRONGSHA);
|
||||
assertThat(build, is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBuildBySHA1IncludingMergeBuilds_libraryFirst(){
|
||||
Job<?,?> project = createProject(SHA1, SHALIB);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1IncludingMergeBuilds(project, SHA1);
|
||||
assertThat(build, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBuildBySHA1IncludingMergeBuilds_libraryLast(){
|
||||
Job<?,?> project = createProject(SHA1, SHALIB);
|
||||
|
||||
Run<?, ?> build = BuildUtil.getBuildBySHA1IncludingMergeBuilds(project, SHA1);
|
||||
assertThat(build, is(notNullValue()));
|
||||
}
|
||||
|
||||
private AbstractProject<?,?> createProject(String... shas) {
|
||||
AbstractBuild build = mock(AbstractBuild.class);
|
||||
List<BuildData> buildDatas = new ArrayList<BuildData>();
|
||||
for(String sha : shas) {
|
||||
BuildData buildData = createBuildData(sha);
|
||||
buildDatas.add(buildData);
|
||||
}
|
||||
|
||||
when(build.getAction(BuildData.class)).thenReturn(buildDatas.get(0));
|
||||
when(build.getActions(BuildData.class)).thenReturn(buildDatas);
|
||||
|
||||
AbstractProject<?, ?> project = mock(AbstractProject.class);
|
||||
when(build.getProject()).thenReturn(project);
|
||||
|
||||
RunList list = mock(RunList.class);
|
||||
when(list.iterator()).thenReturn(Arrays.asList(build).iterator());
|
||||
when(project.getBuilds()).thenReturn(list);
|
||||
|
||||
return project;
|
||||
}
|
||||
|
||||
private BuildData createBuildData(String sha) {
|
||||
|
||||
BuildData buildData = mock(BuildData.class);
|
||||
Revision revision = mock(Revision.class);
|
||||
when(revision.getSha1String()).thenReturn(sha);
|
||||
when(buildData.getLastBuiltRevision()).thenReturn(revision);
|
||||
|
||||
Build gitBuild = mock(Build.class);
|
||||
when(gitBuild.getMarked()).thenReturn(revision);
|
||||
when(buildData.getLastBuild(any(ObjectId.class))).thenReturn(gitBuild);
|
||||
when(gitBuild.getRevision()).thenReturn(revision);
|
||||
when(gitBuild.isFor(sha)).thenReturn(true);
|
||||
buildData.lastBuild = gitBuild;
|
||||
|
||||
return buildData;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package com.dabsquared.gitlabjenkins.util;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.cause.CauseDataBuilder.causeData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.jenkinsci.plugins.displayurlapi.DisplayURLProvider;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.cause.CauseData;
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState;
|
||||
|
||||
import hudson.EnvVars;
|
||||
import hudson.model.Cause;
|
||||
import hudson.model.Run;
|
||||
import hudson.model.TaskListener;
|
||||
import hudson.model.Cause.UpstreamCause;
|
||||
import hudson.plugins.git.Revision;
|
||||
import hudson.plugins.git.util.Build;
|
||||
import hudson.plugins.git.util.BuildData;
|
||||
import jenkins.model.Jenkins;
|
||||
|
||||
/**
|
||||
* @author Daumantas Stulgis
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({GitLabConnectionProperty.class, Jenkins.class})
|
||||
public class CommitStatusUpdaterTest {
|
||||
|
||||
private static final int PROJECT_ID = 1;
|
||||
private static final String BUILD_URL = "job/Test-Job";
|
||||
private static final String STAGE = "test";
|
||||
private static final String REVISION = "1111111";
|
||||
private static final String JENKINS_URL = "https://gitlab.org/jenkins/";
|
||||
|
||||
@Mock Run<?, ?> build;
|
||||
@Mock TaskListener taskListener;
|
||||
@Mock GitLabClient client;
|
||||
@Mock GitLabWebHookCause gitlabCause;
|
||||
@Mock BuildData action;
|
||||
@Mock Revision lastBuiltRevision;
|
||||
@Mock Build lastBuild;
|
||||
@Mock Revision revision;
|
||||
@Mock EnvVars environment;
|
||||
@Mock UpstreamCause upCauseLevel1;
|
||||
@Mock UpstreamCause upCauseLevel2;
|
||||
@Mock Jenkins jenkins;
|
||||
|
||||
CauseData causeData;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
PowerMockito.mockStatic(GitLabConnectionProperty.class);
|
||||
PowerMockito.mockStatic(Jenkins.class);
|
||||
when(Jenkins.getInstance()).thenReturn(jenkins);
|
||||
when(jenkins.getRootUrl()).thenReturn(JENKINS_URL);
|
||||
when(GitLabConnectionProperty.getClient(any(Run.class))).thenReturn(client);
|
||||
when(build.getAction(BuildData.class)).thenReturn(action);
|
||||
when(action.getLastBuiltRevision()).thenReturn(lastBuiltRevision);
|
||||
when(action.getLastBuild(any(ObjectId.class))).thenReturn(lastBuild);
|
||||
when(lastBuild.getMarked()).thenReturn(revision);
|
||||
when(revision.getSha1String()).thenReturn(REVISION);
|
||||
when(build.getUrl()).thenReturn(BUILD_URL);
|
||||
when(build.getEnvironment(any(TaskListener.class))).thenReturn(environment);
|
||||
when(build.getCauses()).thenReturn(new ArrayList<Cause>(Collections.singletonList(upCauseLevel1)));
|
||||
when(upCauseLevel1.getUpstreamCauses()).thenReturn(new ArrayList<Cause>(Collections.singletonList(upCauseLevel2)));
|
||||
when(upCauseLevel2.getUpstreamCauses()).thenReturn(new ArrayList<Cause>(Collections.singletonList(gitlabCause)));
|
||||
|
||||
causeData = causeData()
|
||||
.withActionType(CauseData.ActionType.NOTE)
|
||||
.withSourceProjectId(PROJECT_ID)
|
||||
.withTargetProjectId(PROJECT_ID)
|
||||
.withBranch("feature")
|
||||
.withSourceBranch("feature")
|
||||
.withUserName("")
|
||||
.withSourceRepoHomepage("https://gitlab.org/test")
|
||||
.withSourceRepoName("test")
|
||||
.withSourceNamespace("test-namespace")
|
||||
.withSourceRepoUrl("git@gitlab.org:test.git")
|
||||
.withSourceRepoSshUrl("git@gitlab.org:test.git")
|
||||
.withSourceRepoHttpUrl("https://gitlab.org/test.git")
|
||||
.withMergeRequestTitle("Test")
|
||||
.withMergeRequestId(1)
|
||||
.withMergeRequestIid(1)
|
||||
.withTargetBranch("master")
|
||||
.withTargetRepoName("test")
|
||||
.withTargetNamespace("test-namespace")
|
||||
.withTargetRepoSshUrl("git@gitlab.org:test.git")
|
||||
.withTargetRepoHttpUrl("https://gitlab.org/test.git")
|
||||
.withTriggeredByUser("test")
|
||||
.withLastCommit(REVISION)
|
||||
.withTargetProjectUrl("https://gitlab.org/test")
|
||||
.build();
|
||||
|
||||
when(gitlabCause.getData()).thenReturn(causeData);
|
||||
PowerMockito.spy(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
CommitStatusUpdater.updateCommitStatus(build, taskListener, BuildState.success, STAGE);
|
||||
|
||||
verify(client).changeBuildStatus(Integer.toString(PROJECT_ID), REVISION, BuildState.success, null, STAGE, DisplayURLProvider.get().getRunURL(build), BuildState.success.name());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package com.dabsquared.gitlabjenkins.util;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.model.*;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.State;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class GitLabClientStub implements GitLabClient {
|
||||
private final String url;
|
||||
|
||||
GitLabClientStub(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project createProject(String projectName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergeRequest createMergeRequest(Integer projectId, String sourceBranch, String targetBranch, String title) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project getProject(String projectName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project updateProject(String projectId, String name, String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProject(String projectId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProjectHook(String projectId, String url, Boolean pushEvents, Boolean mergeRequestEvents, Boolean noteEvents) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(String projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeBuildStatus(Integer projectId, String sha, BuildState state, String ref, String context, String targetUrl, String description) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCommit(String projectId, String sha) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptMergeRequest(MergeRequest mr, String mergeCommitMessage, boolean shouldRemoveSourceBranch) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMergeRequestNote(MergeRequest mr, String body) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MergeRequest> getMergeRequests(String projectId, State state, int page, int perPage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Branch> getBranches(String projectId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Branch getBranch(String projectId, String branch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getCurrentUser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User addUser(String email, String username, String name, String password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User updateUser(String userId, String email, String username, String name, String password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Label> getLabels(String projectId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pipeline> getPipelines(String projectName) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.dabsquared.gitlabjenkins.util;
|
||||
|
||||
|
||||
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient;
|
||||
import org.junit.experimental.theories.DataPoints;
|
||||
import org.junit.experimental.theories.Theories;
|
||||
import org.junit.experimental.theories.Theory;
|
||||
|
@ -9,6 +11,7 @@ import static com.dabsquared.gitlabjenkins.util.ProjectIdUtilTest.TestData.forRe
|
|||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* @author Robin Müller
|
||||
*/
|
||||
|
@ -17,14 +20,21 @@ public class ProjectIdUtilTest {
|
|||
|
||||
@DataPoints
|
||||
public static TestData[] testData = {
|
||||
forRemoteUrl("git@gitlab.com:test/project.git").expectProjectId("test/project"),
|
||||
forRemoteUrl("https://gitlab.com/test/project.git").expectProjectId("test/project"),
|
||||
forRemoteUrl("https://myurl.com/gitlab/group/project.git").expectProjectId("group/project")
|
||||
forRemoteUrl("git@gitlab.com", "git@gitlab.com:test/project.git").expectProjectId("test/project"),
|
||||
forRemoteUrl("https://gitlab.com", "https://gitlab.com/test/project.git").expectProjectId("test/project"),
|
||||
forRemoteUrl("https://myurl.com/gitlab", "https://myurl.com/gitlab/group/project.git").expectProjectId("group/project"),
|
||||
forRemoteUrl("git@gitlab.com", "git@gitlab.com:group/subgroup/project.git").expectProjectId("group/subgroup/project"),
|
||||
forRemoteUrl("https://myurl.com/gitlab", "https://myurl.com/gitlab/group/subgroup/project.git").expectProjectId("group/subgroup/project"),
|
||||
forRemoteUrl("https://myurl.com", "https://myurl.com/group/subgroup/project.git").expectProjectId("group/subgroup/project"),
|
||||
forRemoteUrl("https://myurl.com", "https://myurl.com/group/subgroup/subsubgroup/project.git").expectProjectId("group/subgroup/subsubgroup/project"),
|
||||
forRemoteUrl("git@gitlab.com", "git@gitlab.com:group/subgroup/subsubgroup/project.git").expectProjectId("group/subgroup/subsubgroup/project"),
|
||||
};
|
||||
|
||||
@Theory
|
||||
public void retrieveProjectId(TestData testData) throws ProjectIdUtil.ProjectIdResolutionException {
|
||||
String projectId = ProjectIdUtil.retrieveProjectId(testData.remoteUrl);
|
||||
GitLabClient client = new GitLabClientStub(testData.hostUrl);
|
||||
|
||||
String projectId = ProjectIdUtil.retrieveProjectId(client, testData.remoteUrl);
|
||||
|
||||
assertThat(projectId, is(testData.expectedProjectId));
|
||||
}
|
||||
|
@ -32,10 +42,12 @@ public class ProjectIdUtilTest {
|
|||
|
||||
static final class TestData {
|
||||
|
||||
private final String hostUrl;
|
||||
private final String remoteUrl;
|
||||
private String expectedProjectId;
|
||||
|
||||
private TestData(String remoteUrl) {
|
||||
private TestData(String hostUrl, String remoteUrl) {
|
||||
this.hostUrl = hostUrl;
|
||||
this.remoteUrl = remoteUrl;
|
||||
}
|
||||
|
||||
|
@ -49,8 +61,8 @@ public class ProjectIdUtilTest {
|
|||
return remoteUrl;
|
||||
}
|
||||
|
||||
static TestData forRemoteUrl(String remoteUrl) {
|
||||
return new TestData(remoteUrl);
|
||||
static TestData forRemoteUrl(String baseUrl, String remoteUrl) {
|
||||
return new TestData(baseUrl, remoteUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package com.dabsquared.gitlabjenkins.webhook.build;
|
||||
|
||||
import com.dabsquared.gitlabjenkins.GitLabPushTrigger;
|
||||
import com.dabsquared.gitlabjenkins.cause.CauseData;
|
||||
import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.NoteHook;
|
||||
import com.dabsquared.gitlabjenkins.gitlab.hook.model.PipelineHook;
|
||||
import hudson.model.FreeStyleProject;
|
||||
import hudson.model.ParametersAction;
|
||||
import hudson.model.StringParameterValue;
|
||||
import hudson.model.queue.QueueTaskFuture;
|
||||
import hudson.plugins.git.GitSCM;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.jvnet.hudson.test.JenkinsRule;
|
||||
import org.kohsuke.stapler.HttpResponses;
|
||||
import org.kohsuke.stapler.StaplerResponse;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.dabsquared.gitlabjenkins.cause.CauseDataBuilder.causeData;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Milena Zachow
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PipelineBuildActionTest {
|
||||
|
||||
@ClassRule
|
||||
public static JenkinsRule jenkins = new JenkinsRule();
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private StaplerResponse response;
|
||||
|
||||
@Mock
|
||||
private GitLabPushTrigger trigger;
|
||||
|
||||
FreeStyleProject testProject;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException{
|
||||
testProject = jenkins.createFreeStyleProject();
|
||||
testProject.addTrigger(trigger);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildOnSuccess () throws IOException {
|
||||
exception.expect(HttpResponses.HttpResponseException.class);
|
||||
new PipelineBuildAction(testProject, getJson("PipelineEvent.json"), null).execute(response);
|
||||
|
||||
verify(trigger).onPost(any(PipelineHook.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doNotBuildOnFailure() throws IOException {
|
||||
exception.expect(HttpResponses.HttpResponseException.class);
|
||||
new PipelineBuildAction(testProject, getJson("PipelineFailureEvent.json"), null).execute(response);
|
||||
|
||||
verify(trigger, never()).onPost(any(PipelineHook.class));
|
||||
}
|
||||
|
||||
private String getJson(String name) throws IOException {
|
||||
return IOUtils.toString(getClass().getResourceAsStream(name));
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ public abstract class BuildPageRedirectActionTest {
|
|||
testProject.setScm(new GitSCM(gitRepoUrl));
|
||||
testProject.setQuietPeriod(0);
|
||||
QueueTaskFuture<FreeStyleBuild> future = testProject.scheduleBuild2(0);
|
||||
FreeStyleBuild build = future.get(5, TimeUnit.SECONDS);
|
||||
FreeStyleBuild build = future.get(15, TimeUnit.SECONDS);
|
||||
|
||||
getBuildPageRedirectAction(testProject).execute(response);
|
||||
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
{ "object_kind": "pipeline",
|
||||
"object_attributes": {
|
||||
"id": 31,
|
||||
"ref": "master",
|
||||
"tag": false,
|
||||
"sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"status": "success",
|
||||
"stages": [
|
||||
"build",
|
||||
"test",
|
||||
"deploy"
|
||||
],
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"finished_at": "2016-08-12 15:26:29 UTC",
|
||||
"duration": 63
|
||||
},
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"project": {
|
||||
"name": "Gitlab Test",
|
||||
"description": "Atque in sunt eos similique dolores voluptatem.",
|
||||
"web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
|
||||
"avatar_url": null,
|
||||
"git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
|
||||
"git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
|
||||
"namespace": "Gitlab Org",
|
||||
"visibility_level": 20,
|
||||
"path_with_namespace": "gitlab-org/gitlab-test",
|
||||
"default_branch": "master"
|
||||
},
|
||||
"commit": {
|
||||
"id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"message": "test\n",
|
||||
"timestamp": "2016-08-12T17:23:21+02:00",
|
||||
"url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"author": {
|
||||
"name": "User",
|
||||
"email": "user@gitlab.com"
|
||||
}
|
||||
},
|
||||
"builds": [
|
||||
{
|
||||
"id": 380,
|
||||
"stage": "deploy",
|
||||
"name": "production",
|
||||
"status": "skipped",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": null,
|
||||
"finished_at": null,
|
||||
"when": "manual",
|
||||
"manual": true,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 377,
|
||||
"stage": "test",
|
||||
"name": "test-image",
|
||||
"status": "success",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": "2016-08-12 15:26:12 UTC",
|
||||
"finished_at": null,
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 378,
|
||||
"stage": "test",
|
||||
"name": "test-build",
|
||||
"status": "success",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": "2016-08-12 15:26:12 UTC",
|
||||
"finished_at": "2016-08-12 15:26:29 UTC",
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 376,
|
||||
"stage": "build",
|
||||
"name": "build-image",
|
||||
"status": "success",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": "2016-08-12 15:24:56 UTC",
|
||||
"finished_at": "2016-08-12 15:25:26 UTC",
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 379,
|
||||
"stage": "deploy",
|
||||
"name": "staging",
|
||||
"status": "created",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": null,
|
||||
"finished_at": null,
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
{ "object_kind": "pipeline",
|
||||
"object_attributes": {
|
||||
"id": 31,
|
||||
"ref": "master",
|
||||
"tag": false,
|
||||
"sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"status": "failure",
|
||||
"stages": [
|
||||
"build",
|
||||
"test",
|
||||
"deploy"
|
||||
],
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"finished_at": "2016-08-12 15:26:29 UTC",
|
||||
"duration": 63
|
||||
},
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"project": {
|
||||
"name": "Gitlab Test",
|
||||
"description": "Atque in sunt eos similique dolores voluptatem.",
|
||||
"web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
|
||||
"avatar_url": null,
|
||||
"git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
|
||||
"git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
|
||||
"namespace": "Gitlab Org",
|
||||
"visibility_level": 20,
|
||||
"path_with_namespace": "gitlab-org/gitlab-test",
|
||||
"default_branch": "master"
|
||||
},
|
||||
"commit": {
|
||||
"id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"message": "test\n",
|
||||
"timestamp": "2016-08-12T17:23:21+02:00",
|
||||
"url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2",
|
||||
"author": {
|
||||
"name": "User",
|
||||
"email": "user@gitlab.com"
|
||||
}
|
||||
},
|
||||
"builds": [
|
||||
{
|
||||
"id": 380,
|
||||
"stage": "deploy",
|
||||
"name": "production",
|
||||
"status": "skipped",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": null,
|
||||
"finished_at": null,
|
||||
"when": "manual",
|
||||
"manual": true,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 377,
|
||||
"stage": "test",
|
||||
"name": "test-image",
|
||||
"status": "success",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": "2016-08-12 15:26:12 UTC",
|
||||
"finished_at": null,
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 378,
|
||||
"stage": "test",
|
||||
"name": "test-build",
|
||||
"status": "success",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": "2016-08-12 15:26:12 UTC",
|
||||
"finished_at": "2016-08-12 15:26:29 UTC",
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 376,
|
||||
"stage": "build",
|
||||
"name": "build-image",
|
||||
"status": "success",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": "2016-08-12 15:24:56 UTC",
|
||||
"finished_at": "2016-08-12 15:25:26 UTC",
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 379,
|
||||
"stage": "deploy",
|
||||
"name": "staging",
|
||||
"status": "created",
|
||||
"created_at": "2016-08-12 15:23:28 UTC",
|
||||
"started_at": null,
|
||||
"finished_at": null,
|
||||
"when": "on_success",
|
||||
"manual": false,
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"username": "root",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
|
||||
},
|
||||
"runner": null,
|
||||
"artifacts_file": {
|
||||
"filename": null,
|
||||
"size": null
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
rm -rf $HOME/.m2/repository/com/dabsquared/gitlabjenkins
|
||||
mkdir -p $DOCKER_CACHE_DIR
|
||||
docker images -a --filter='dangling=false' --format '{{.Repository}}:{{.Tag}} {{.ID}}' | xargs -n 2 -t sh -c 'test -e $DOCKER_CACHE_DIR/$1.tar.gz || docker save $0 | gzip -2 > $DOCKER_CACHE_DIR/$1.tar.gz'
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
if [[ -d $DOCKER_CACHE_DIR ]]; then
|
||||
echo "Loading cached images into docker..."
|
||||
ls $DOCKER_CACHE_DIR/*.tar.gz | xargs -I {file} sh -c "zcat {file} | docker load";
|
||||
fi
|
||||
|
||||
./mvnw integration-test -B -Pintegration-test -Dgitlab.version=$GITLAB_VERSION -Dfindbugs.skip=true -Dmaven.javadoc.skip=true
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
./mvnw verify -B -Pall-tests,skip-javadoc-with-tests -Dmaven.javadoc.skip=true
|
Loading…
Reference in New Issue