Giter Club home page Giter Club logo

pull-request-notifier-for-bitbucket's Introduction

Pull Request Notifier for Bitbucket Server Build Status

This project is sort of deprecated. See: https://community.developer.atlassian.com/t/eula-and-data-center-for-free-apps/26062


This is a Bitbucket Server plugin that can invoke custom URL:s, supporting variables, when configured events occur on pull requests in Bitbucket Server. It can notify Jenkins, Bamboo, TeamCity, HipChat and many more!

The original use case was to trigger Jenkins jobs to build and verify pull requests but it can trigger any system. The plugin can notify any system that can be notified with a URL.

Here is a screenshot of the admin GUI on global level. And here is a screenshot of the admin GUI on repository level.

Here is a blog post that includes the plugin.

Features

The Pull Request Notifier for Bitbucket Server can:

  • Invoke any URL, or set of URL:s, when a pull request event happens.
    • With variables available to add necessary parameters.
    • HTTP POST, PUT, GET and DELETE. POST and PUT also supports rendered post content.
  • Be configured to trigger on any pull request event. Including extended events:
    • RESCOPED_FROM, when source branch change
    • RESCOPED_TO, when target branch change
    • BUTTON_TRIGGER, when trigger button in pull request view is pressed
  • Can invoke CSRF protected systems, using the ${INJECTION_URL_VALUE} variable. How to to that with Jenkins is described below.
  • Be configured to only trigger if the pull request matches a filter. A filter text is constructed with any combination of the variables and then a regexp is constructed to match that text.
  • Add buttons to pull request view in Bitbucket Server. And map those buttons to URL invocations. This can be done by setting the filter string to ${BUTTON_TRIGGER_TITLE} and the filter regexp to title of button.
    • Buttons can have forms associated with them, and then submit the form data using the ${BUTTON_FORM_DATA} variable.
  • Authenticate with HTTP basic authentication.
  • Optionally allow any SSL certificate.
  • Use custom SSL key store, type and password.
  • Send custom HTTP headers
  • Can optionally use proxy to connect
  • Can let users and/or admins do configuration. Or restrict configuration to just system admins. A user will have to browse to the configuration page at http://domain/bitbucket/plugins/servlet/prnfb/admin.
  • Can enable trigger
    • If PR has, or has no, conflicts
    • Only if PR has conflicts
    • Only if PR has no conflicts
  • Nice configuration GUI.
    • Global at /bitbucket/plugins/servlet/prnfb/admin
    • Project level at /bitbucket/plugins/servlet/prnfb/admin/PROJECT_1
    • Repo level at /bitbucket/plugins/servlet/prnfb/admin/PROJECT_1/rep_1

The plugin has its own implementation to create the RESCOPED_FROM and RESCOPED_TO events. RESCOPED is transformed to RESCOPED_TO if target branch changed, RESCOPED_FROM if source branch, or both, changed.

The filter text as well as the URL support variables. These are:

Variable Description
${EVERYTHING_URL} This variable is resolved to all available variables. The name of each parameter is the name of that variable. Example: PULL_REQUEST_ID=1&PULL_REQUEST_TITLE=some%20thing...
${PULL_REQUEST_ID} Example: 1
${PULL_REQUEST_TITLE} Example: Anything
${PULL_REQUEST_DESCRIPTION} The ${EVERYTHING_URL} does not include this because it makes the URL very big. Example: Anything
${PULL_REQUEST_VERSION} Example: 1
${PULL_REQUEST_COMMENT_TEXT} Example: A comment
${PULL_REQUEST_COMMENT_ACTION} Example: ADDED, DELETED, EDITED, REPLIED
${PULL_REQUEST_COMMENT_ID} Example: 1234
${PULL_REQUEST_ACTION} Example: OPENED
${PULL_REQUEST_STATE} Example: DECLINED, MERGED, OPEN
${BUTTON_TRIGGER_TITLE} Example: Trigger Notification
${BUTTON_FORM_DATA} The form data that was submitted
${INJECTION_URL_VALUE} Value retrieved from any URL
${VARIABLE_REGEX_MATCH} The result of custom regex applied to a variable
${PULL_REQUEST_URL} Example: http://localhost:7990/projects/PROJECT_1/repos/rep_1/pull-requests/1
${PULL_REQUEST_USER_DISPLAY_NAME} Example: Some User
${PULL_REQUEST_USER_EMAIL_ADDRESS} Example: [email protected]
${PULL_REQUEST_USER_ID} Example: 1
${PULL_REQUEST_USER_NAME} Example: user.name
${PULL_REQUEST_USER_SLUG} Example: user.name
${PULL_REQUEST_USER_GROUPS} Example: ADMIN,DEV
${PULL_REQUEST_AUTHOR_DISPLAY_NAME} Example: Administrator
${PULL_REQUEST_AUTHOR_EMAIL} Example: [email protected]
${PULL_REQUEST_AUTHOR_ID} Example: 1
${PULL_REQUEST_AUTHOR_NAME} Example: admin
${PULL_REQUEST_AUTHOR_SLUG} Example: admin
${PULL_REQUEST_REVIEWERS} Example: Administrator,User
${PULL_REQUEST_REVIEWERS_ID} Example: 1,2
${PULL_REQUEST_REVIEWERS_SLUG} Example: admin,user
${PULL_REQUEST_REVIEWERS_EMAIL} Example: [email protected],[email protected]
${PULL_REQUEST_REVIEWERS_APPROVED_COUNT} Number of reviewers that approved the PR.
${PULL_REQUEST_REVIEWERS_APPROVED_SLUG} Example: admin,user.
${PULL_REQUEST_REVIEWERS_APPROVED_EMAIL} Example: [email protected],[email protected].
${PULL_REQUEST_REVIEWERS_APPROVED_NAME} Example: Admin,User.
${PULL_REQUEST_REVIEWERS_APPROVED_DISPLAY_NAME} Example: Admin Adminson,User Userson.
${PULL_REQUEST_REVIEWERS_UNAPPROVED_COUNT} Number of reviewers that unapproved the PR.
${PULL_REQUEST_REVIEWERS_UNAPPROVED_SLUG} Example: admin,user.
${PULL_REQUEST_REVIEWERS_UNAPPROVED_EMAIL} Example: [email protected],[email protected].
${PULL_REQUEST_REVIEWERS_UNAPPROVED_NAME} Example: Admin,User.
${PULL_REQUEST_REVIEWERS_UNAPPROVED_DISPLAY_NAME} Example: Admin Adminson,User Userson.
${PULL_REQUEST_REVIEWERS_NEEDS_WORK_COUNT} Number of reviewers that says the PR needs work.
${PULL_REQUEST_REVIEWERS_NEEDS_WORK_SLUG} Example: admin,user.
${PULL_REQUEST_REVIEWERS_NEEDS_WORK_EMAIL} Example: [email protected],[email protected].
${PULL_REQUEST_REVIEWERS_NEEDS_WORK_NAME} Example: Admin,User.
${PULL_REQUEST_REVIEWERS_NEEDS_WORK_DISPLAY_NAME} Example: Admin Adminson,User Userson.
${PULL_REQUEST_PARTICIPANTS_APPROVED_COUNT} Number of participants that approved the PR.
${PULL_REQUEST_PARTICIPANTS_EMAIL} Example: [email protected],[email protected]
${PULL_REQUEST_MERGE_COMMIT} Hash of merged commit (only available for merged-event).
${PULL_REQUEST_FROM_SSH_CLONE_URL} Example: ssh://git@localhost:7999/project_1/rep_1
${PULL_REQUEST_FROM_HTTP_CLONE_URL} Example: http://localhost:7990/bitbucket/scm/project_1/rep_1.git
${PULL_REQUEST_FROM_HASH} Example: 6053a1eaa1c009dd11092d09a72f3c41af1b59ad
${PULL_REQUEST_PREVIOUS_FROM_HASH} Example: 6053a1eaa1c009dd11092d09a72f3c41af1b59ad
${PULL_REQUEST_FROM_ID} Example: refs/heads/branchmodmerge
${PULL_REQUEST_FROM_BRANCH} Example: branchmodmerge
${PULL_REQUEST_FROM_REPO_ID} Example: 1
${PULL_REQUEST_FROM_REPO_NAME} Example: rep_1
${PULL_REQUEST_FROM_REPO_PROJECT_ID} Example: 1
${PULL_REQUEST_FROM_REPO_PROJECT_KEY} Example: PROJECT_1
${PULL_REQUEST_FROM_REPO_SLUG} Example: rep_1
${PULL_REQUEST_TO_SSH_CLONE_URL} Example: ssh://git@localhost:7999/project_1/rep_1
${PULL_REQUEST_TO_HTTP_CLONE_URL} Example: http://localhost:7990/bitbucket/scm/project_1/rep_1.git
${PULL_REQUEST_TO_HASH} Example: 6053a1eaa1c009dd11092d09a72f3c41af1b59ad
${PULL_REQUEST_PREVIOUS_TO_HASH} Example: 6053a1eaa1c009dd11092d09a72f3c41af1b59ad
${PULL_REQUEST_TO_ID} Example: refs/heads/branchmodmerge
${PULL_REQUEST_TO_BRANCH} Example: branchmodmerge
${PULL_REQUEST_TO_REPO_ID} Example: 1
${PULL_REQUEST_TO_REPO_NAME} Example: rep_1
${PULL_REQUEST_TO_REPO_PROJECT_ID} Example: 1
${PULL_REQUEST_TO_REPO_PROJECT_KEY} Example: PROJECT_1
${PULL_REQUEST_TO_REPO_SLUG} Example: rep_1

The ${PULL_REQUEST_USER...} contains information about the user who issued the event. Who commented it, who rejected it, who approved it...

You may want to use these Jenkins plugins if you are notifying Jenkins:

Integration guides

Generally, when fiddling with this plugin, you may want to use something like RequestBin. Let the notification URL point to it and you can inspect what the invoked URL looks like.

Here are some guides on how to use the plugin with different systems. Feel free to add guides through pull requests to this repo!

Button Forms

For each button you can specify a form that will show up when the button is pressed. That form data will then be submitted and will be available in the ${BUTTON_FORM_DATA} variable. Additionally, the form itself can reference other variables (with the exception of the ${BUTTON_...} ones) and will have those resolved prior to rendering.

A form is defined as a JSON array. Here is an example that shows all possibilities:

[
        {   "name": "var1",
            "label": "var1 label",
            "defaultValue": "you can put a variable like this: ${PULL_REQUEST_AUTHOR_NAME}",
            "type": "input", 
            "required": false,
            "description": "var1 description"
        },
        {   "name": "var2",
            "label": "var2 label",
            "defaultValue": "any string can go here",
            "type": "textarea", 
            "required": false,
            "description": "var2 description"
        },
        {   "name": "var3",
            "label": "var3 label",
            "defaultValue": "option2_name",
            "buttonFormElementOptionList": [
                {"label": "option1 label", "name": "option1_name"},
                {"label": "option2 label", "name": "option2_name"},
                {"label": "option3 label", "name": "option3_name"}
            ],
            "type": "radio", 
            "required": true,
            "description": "var3 description"
        },
        {   "name": "var4",
            "label": "var4 label",
            "type": "checkbox", 
            "required": true,
            "buttonFormElementOptionList": [
                {"label": "option1 label", "name": "option1_name", "defaultValue": true}, 
                {"label": "option2 label", "name": "option2_name", "defaultValue": true}
            ],
            "description": "var4 description"
        }
]

You can see a screenshot here when rendered.

When submitted with the default values, it will look like this:

{
   "var1":"you can put a variable like this: admin",
   "var2":"any string can go here",
   "var3":"option2_name",
   "var4":[
      "option1_name",
      "option2_name"
   ]
}

REST API

Some rest resources are available. You can figure out the JSON structure by looking at the DTO:s.

  • /bitbucket/rest/prnfb-admin/1.0/settings

    • GET Get all global settings.
    • POST Store all global settings.
  • /bitbucket/rest/prnfb-admin/1.0/settings/notifications

    • DELETE /{uuid} Deletes notification with uuid.
    • GET Get all notifications.
    • GET /{uuid} Get notification with uuid.
    • GET /projectKey/{projectKey} Get all notifications for the project.
    • GET /projectKey/{projectKey}/repositorySlug/{repositorySlug} Get all notifications for the project and repository.
    • POST Save a notification.
  • /bitbucket/rest/prnfb-admin/1.0/settings/buttons

    • DELETE /{uuid} Deletes button with uuid.
    • GET Get all buttons that the current user is allowed to use.
    • GET /{uuid} Get button with uuid.
    • GET /repository/{repositoryId}/pullrequest/{pullRequestId} Get all buttons for repository that the current user is allowed to use.
    • GET /projectKey/{projectKey} Get all buttons for the project.
    • GET /projectKey/{projectKey}/repositorySlug/{repositorySlug} Get all buttons for the project and repository.
    • POST Save a button.
    • POST {uuid}/press/repository/{repositoryId}/pullrequest/{pullRequestId} Press the button.

A new notification to trigger on COMMENTED can be added like this.

curl -u admin:admin 'http://localhost:7990/bitbucket/rest/prnfb-admin/1.0/settings/notifications' -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript, */*; q=0.01' --data-binary '{"uuid":"","name":"","projectKey":"","repositorySlug":"","filterString":"","filterRegexp":"","triggers":["COMMENTED"],"injectionUrl":"","injectionUrlRegexp":"","user":"","password":"","proxyUser":"","proxyPassword":"","proxyServer":"","proxyPort":"","url":"http://localhost:80/?abc","method":"GET","postContent":"","headers":[{"name":"","value":""}]}'

It will respond with something like this.

{"headers":[],"method":"GET","name":"Notification","triggerIfCanMerge":"ALWAYS","triggerIgnoreStateList":[],"triggers":["COMMENTED"],"url":"http://localhost:80/?abc","uuid":"b1306a3a-5a87-4145-80b7-660bc986dd25"}

It can then be changed to trigger on RESCOPED_FROM and RESCOPED_TO like this.

curl -u admin:admin 'http://localhost:7990/bitbucket/rest/prnfb-admin/1.0/settings/notifications' -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript, */*; q=0.01' --data-binary '{"uuid":"b1306a3a-5a87-4145-80b7-660bc986dd25","name":"Notification","projectKey":"","repositorySlug":"","filterString":"","filterRegexp":"","triggerIfCanMerge":"ALWAYS","triggers":["RESCOPED_FROM","RESCOPED_TO"],"injectionUrl":"","injectionUrlRegexp":"","user":"","password":"","proxyUser":"","proxyPassword":"","proxyServer":"","proxyPort":"","url":"http://localhost:80/?abc","method":"GET","postContent":"","headers":[{"name":"","value":""}]}' --compressed

It will respond with something like this.

{"headers":[],"method":"GET","name":"Notification","triggerIfCanMerge":"ALWAYS","triggerIgnoreStateList":[],"triggers":["RESCOPED_FROM","RESCOPED_TO"],"url":"http://localhost:80/?abc","uuid":"b1306a3a-5a87-4145-80b7-660bc986dd25"}

You may use Chrome and Developer Tools (press F12) to view rest calls while editing in GUI to find more examples.

pull-request-notifier-for-bitbucket's People

Contributors

agentmerlin avatar antonkazakov avatar christiangalsterer avatar daveneeley avatar fwmechanic avatar garretruh avatar johntconklin avatar jwoolston avatar madsop avatar mhitchens avatar raimana avatar rbywater avatar rishabhtayal avatar rkw613 avatar sreer-pega avatar steelsojka avatar tomasbjerre avatar trentrand avatar zhang6464 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pull-request-notifier-for-bitbucket's Issues

Reply on Comment, doesn't trigger Commented event

Hey,

just noticed the above and wanted to check if that's intentional behaviour.

If "bug", possible solutions would be to trigger commented event also for replies or create a new event and fire that.

Greetings

file not found error

I'm getting this error in our stash logs when a pull request is being made:

java.io.FileNotFoundException: http://path/to/jenkins/buildWithParameters?token=someToken&BRANCH=refs/heads/testPR
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1625) ~[na:1.7.0_75]
    at se.bjurr.prnfs.listener.UrlInvoker.invoke(UrlInvoker.java:103) ~[plugin.9192568710360528632.pull-request-notifier-for-stash-1.12_1429545068000.jar:na]
    at se.bjurr.prnfs.listener.PrnfsPullRequestEventListener$1.invoke(PrnfsPullRequestEventListener.java:49) [plugin.9192568710360528632.pull-request-notifier-for-stash-1.12_1429545068000.jar:na]
    at se.bjurr.prnfs.listener.PrnfsPullRequestEventListener.handleEvent(PrnfsPullRequestEventListener.java:139) [plugin.9192568710360528632.pull-request-notifier-for-stash-1.12_1429545068000.jar:na]
    at se.bjurr.prnfs.listener.PrnfsPullRequestEventListener.onEvent(PrnfsPullRequestEventListener.java:90) [plugin.9192568710360528632.pull-request-notifier-for-stash-1.12_1429545068000.jar:na]
    at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:36) [atlassian-event-2.3.4.jar:na]
    at com.atlassian.stash.internal.event.AsyncBatchingInvokersTransformer$AsyncInvokerBatch.invoke(AsyncBatchingInvokersTransformer.java:100) [stash-platform-2.12.1.jar:na]
    at com.atlassian.event.internal.AsynchronousAbleEventDispatcher$1$1.run(AsynchronousAbleEventDispatcher.java:46) [atlassian-event-2.3.4.jar:na]
    at com.atlassian.sal.core.executor.ThreadLocalDelegateRunnable.run(ThreadLocalDelegateRunnable.java:38) [sal-core-2.10.15.jar:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_75]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_75]
    ... 5 frames trimmed

NOTE: I changed the url name and the name of the token in the URL.

MERGED event is not risen

I've subscribed on all events and my url is invoked for most of them successfully. But the url is not invoked for MERGE event at all. Version of my Stash installation is v3.11.1

Comments on closed/merged issues trigger Commented event

Hi Tomas,

One of our users just saw that we can trigger a commented event on a pull request that has already been merged. I was able to reproduce it.

When you get a chance, can you look into updating the hook to ignore commented events on a closed pull request?

Thanks,
Derek

NoClassDefFoundError JsonReader

I guess you hate me by now, sorry about that.

I tried the new injection URL. When I tried to get a crumb from Jenkins I got this exception:

2015-09-01 06:43:05,752 ERROR [http-nio-8443-exec-35] malu @PGJE6Zx403x259037x0 2xdsja 192.168.1.108 "POST /rest/prnfs-admin/1.0/manual/ HTTP/1.1" c.a.p.r.c.e.j.ThrowableExceptionMapper Uncaught exception thrown by REST service: Could not initialize class com.jayway.jsonpath.internal.JsonReader
java.lang.NoClassDefFoundError: Could not initialize class com.jayway.jsonpath.internal.JsonReader
at com.jayway.jsonpath.JsonPath.read(JsonPath.java:461) ~[plugin.6253462562142497142.pull-request-notifier-for-stash-1.23_1441086003000.jar:na]
at se.bjurr.prnfs.listener.PrnfsRenderer$PrnfsVariable$37.resolve(PrnfsRenderer.java:322) ~[plugin.6253462562142497142.pull-request-notifier-for-stash-1.23_1441086003000.jar:na]
at se.bjurr.prnfs.listener.PrnfsRenderer$PrnfsVariable.resolve(PrnfsRenderer.java:364) ~[plugin.6253462562142497142.pull-request-notifier-for-stash-1.23_1441086003000.jar:na]
at se.bjurr.prnfs.listener.PrnfsRenderer.render(PrnfsRenderer.java:415) ~[plugin.6253462562142497142.pull-request-notifier-for-stash-1.23_1441086003000.jar:na]
at se.bjurr.prnfs.listener.PrnfsPullRequestEventListener.notify(PrnfsPullRequestEventListener.java:159) ~[plugin.6253462562142497142.pull-request-notifier-for-stash-1.23_1441086003000.jar:na]
at se.bjurr.prnfs.ManualResource.post(ManualResource.java:138) ~[plugin.6253462562142497142.pull-request-notifier-for-stash-1.23_1441086003000.jar:na]
at com.atlassian.applinks.core.rest.context.ContextFilter.doFilter(ContextFilter.java:25) [applinks-plugin-4.3.5_1430735632000.jar:na]
at com.atlassian.stash.internal.spring.security.StashAuthenticationFilter.doFilter(StashAuthenticationFilter.java:83) [StashAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doInsideSpringSecurityChain(BeforeLoginPluginAuthenticationFilter.java:111) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:77) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.security.auth.trustedapps.filter.TrustedApplicationsFilter.doFilter(TrustedApplicationsFilter.java:100) [atlassian-trusted-apps-core-3.0.8.jar:na]
at com.atlassian.oauth.serviceprovider.internal.servlet.OAuthFilter.doFilter(OAuthFilter.java:79) [atlassian-oauth-service-provider-plugin-1.9.10_1430737736000.jar:na]
at com.atlassian.analytics.client.filter.DefaultAnalyticsFilter.doFilter(DefaultAnalyticsFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.analytics.client.filter.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doBeforeBeforeLoginFilters(BeforeLoginPluginAuthenticationFilter.java:89) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:75) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.request.DefaultRequestManager.doAsRequest(DefaultRequestManager.java:85) [stash-service-impl-3.8.1.jar:na]
at com.atlassian.stash.internal.hazelcast.ConfigurableWebFilter.doFilter(ConfigurableWebFilter.java:38) [ConfigurableWebFilter.class:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_20]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_20]
... 205 frames trimmed

"trigger build" button

is it me or pressing the "trigger build" button (available on a pull-request page, top-right corner) doesn't do anything?

i would've expected that with this plugin (and configured correctly), it would trigger an HTTP call (a Jenkins' notifyCommit to be specific)

new variable containing only name of branch

I really like this plugin, and would like to use it to integrate our Stash installation better with the CI services provided by Scrutinizer.

Unfortunately, their API only accepts simple branch names instead of refs like ${PULL_REQUEST_FROM_ID} provides.

Would it be possible to implement a new variable (something like ${PULL_REQUEST_FROM_BRANCH} perhaps) that contains only the name of the branch?

If the Stash API does not provide a convenient method and you have to resort to chopping off the first part of the string, please look out for those of us with slashes in their branch names.

Thanks in advance!

Add HTTP POST request support

When triggering my Jenkins build, i need to initiate a POST request. It looks like the current plugin only is sending a GET request. Can you add support for HTTP POST requests?

I'm not a JAVA guy but got this working with java.net.HttpURLConnection

In UrlInvoker.java, i replaced:
final URLConnection uc = url.openConnection();

With:
final HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.setRequestMethod("POST");

Seemed to work for me, but again not a JAVA guy and also some people may want "GET" requests as well.

Thanks,
Derek

Make PR Event available as a parameter

Make the PR event available as a parameter so that it can be used to further differentiate builds and/or use it in the trigger system to set the reason why the system was triggered.

Example 1: Set in the build description of a Jenkins job why the build was triggered.
Example 2: Triggered different build based on event type but only trigger one URL.

I think I can provide a PR in the next days.

Encrypt authentication credentials

Would it be possible to add encryption for the credentials? In the database lob_data, the credentials are stored as plain text. Thanks.

Who issued an action?

Hey,

great plugin! Thanks a lot.

I wonder is there a way currently to find out who issued an action, or can it be added in one of the next releases?

I'd like to notify about, who approved a pull request or added a comment - maybe something like ${PULL_REQUEST_ACTION_ISSUED_BY} Example: Bob (while Bob is not the creator of the pull request, he "only" approved / commented / declined the pull request)
Hope this makes sense ;)

Thanks again, keep up the great work.

Greetings,
Sascha

Add new variables for SSH and HTTP clone URL source and target branch

Please add new variables for the SSH and HTTP clone URL for the source and target branch e.g.
PULL_REQUEST_FROM_SSH_CLONE_URL
PULL_REQUEST_FROM_HTTP_CLONE_URL
PULL_REQUEST_TO_SSH_CLONE_URL
PULL_REQUEST_TO_HTTP_CLONE_URL

This would allow to directly call the Jenkins Git Plugin Notification feature from the plugin without an intermediate step, e.g. a Jenkins job which adds the SSH/HTTP URL respectively.

PS: Really great plugin. We use it since the first version and are building already +100 repositories and +300 Jenkins builds with it without a hazzle. Was waiting for a long time for this and also filed a request to Atlassian but no progress there.

[feature] trigger button: reply message

right now there is no "reply" message, anything to tell the user that the URL got called and all is ok

would be great if the HTTP reply (status, headers and body) would be shown in a dialog to the user

bug: no POST content

upgraded to 1.22 crash
upgraded to 1.23 to fix the crash

POST content is not being sent now..

Possibility to invoke more than one URL

Perhaps a bit to Jenkins specific but...
I have a number of projects that runs several jobs in Jenkins. It would be nice to be able to launch the jobs all in one go. Of course I can setup a triggered chain of jobs in Jenkins instead but this seems to be a nice addition to an already great plugin!

Perhaps make it possible to configure either like this:

base-URL: http://jenkins
params: token=TOKEN_NAME&another_parm=ANOTHER_PARM_VAL

  • job/job-1
  • job/job-2
  • job/job-3

OR even more extendable:

URL-setup 1:

base-URL: http://jenkins
params: token=TOKEN_NAME&another_parm=ANOTHER_PARM_VAL

  • job/job-1
  • job/job-2
  • job/job-3

URL-setup 2:

base-URL: http://jenkins2
params: token=TOKEN_NAME

  • job/job-1
  • job/job-2
  • job/job-3

ids of HTML elements need to be unique

e.g. right now "BUTTON_TRIGGER_1" seems to be assigned to all "BUTTON_TRIGGER" checkboxes, meaning there are weird consequences when clicking the label on the 3rd rule's "BUTTON_TRIGGER", but the browser things you're interacting with the 1st rule's "BUTTON_TRIGGER"

[feature] merge hash variable

currently it is possible to get the hash of the source and the target branch, meaning that if you want to "recreate" the result of the pull-request, you have to merge the source into the target (or rebase the source on top of the target)

BUT that process has already been done by Stash in refs/pull-requests/<ID>/merge

Would it be possible to export that into a variable e.g. PULL_REQUEST_MERGE_HASH? That way one can use the merge hash to communicate (logs, other systems) about the exact same commit rather than the tuple {FROM_HASH, TO_HASH}

Rescope of Target/To branch triggers 2 RESCOPE_TO events

When I update the target/to branch of an open pull request, 2 http requests are sent each with a different ${PULL_REQUEST_FROM_HASH}. One will contain the from commit of the source branch and the other will contain the previous commit of the target branch.

Is it possible to just trigger one http request with the PULL_REQUEST_FROM_HASH being the commit of the source branch?

Mark the plugin as supporting Stash DC

Currently the plugin is marked as not supporting Stash DC, but we run it in a Stash DC environment and it works fine. A quick audit of the code also makes me think it should work just fine as well.

Possible issue with isAdmin

There is an issue with the isAdmin check.

It should be changed so that the user knows that is is the reason for being redirected.

The login page is not a good page to redirect to. The user may be logged in, but not as admin.

ConfigResource and AdminServlet

Jenkins is trying to authenticate even when no user/pass set

Even when I leave the username and password blank, it seems to send something to Jenkins in the Authorization header. Here is the error from the Jenkins log:

org.acegisecurity.BadCredentialsException: Empty password

Additionally, the Stash log says that it got a 401. If I switch the log to debug I get:

2015-04-09 18:25:26,740 INFO  [AtlassianEvent::thread-1]  se.bjurr.prnfs.listener.UrlInvoker Url: "<our jenkins url>" user: "" password: ""

Pull Request Trigger Firing Twice

I am using this add on to trigger a build when a pull request is submitted, using this config:

screen shot 2015-06-19 at 12 23 11 pm

It looks like on Pull Request creation my build is being triggered twice, and since it's only triggered via this plugin I'm assuming the plugin is making the POST request twice. If it's user config issue let me know what I need to change

No valid crumb in POST request

Whenever I trigger a build from Stash I get the error:
WARNING: No valid crumb was included in request for XXX. Returning 403.
in Jenkins.

I have entered my username and password in the configuration so that shouldn't be the problem.

Finish GUI

Should probably implement it with AUI SOY

Filter regexp special escape characters not working?

Hopefully i didn't miss something but i'm trying to match my "keyword" in the pull request comment to trigger a job. I want to be able to match my "keyword" and ignore spaces before and after.

Filter string: ${PULL_REQUEST_TO_ID}:${PULL_REQUEST_COMMENT_TEXT}:
Filter regexp: ._:(\s_keyword\s*|):

It only seems to match if i enter in the exact "keyword" as a comment without any spaces before and after the "keyword". I also tried with \n in my regexp, but again no match unless it was just "keyword" entered as a comment. Maybe Stash is stripping these characters?

Enable configuration in per-repository hook screen

It's a bit odd that the configuration is done globally and you have to explicitly "filter" out your repository. It would be nice if you could also edit configuration in the per-repository hook setup screen, which would automatically be filtered out for that repository.

You would keep the global config too, in case someone wanted to define a global rule.

Add an event to fire only when the FROM_HASH changes

Currently the RESCOPED event covers either the TO_HASH or FROM_HASH changing. The former happens when somebody updates the target branch (e.g. merges something else in) and the latter when somebody updates the source branch (e.g. fixes some code review feedback).

We have a large dev team and our destination branches change frequently. This in turn means that we get RESCOPE events all the time even though the PR contents haven't changed in a meaningful way. While I understand that in theory we should "fire" a new Jenkins job, running our build and test is quite expensive so we want to limit it to only when the FROM_HASH changes.

This can be done by checking the events getPreviousFromHash() and getPreviousToHash() against the current values. If getPreviousFromHash() changed - invoke the URL, and if it hasn't, don't.

Add an Trigger Notification Button on Pull Request View

For some use cases the notification should be send again, even if there was no event happening. E.g. a Jenkins build was triggered but due to a configuration error or technical problem the job shall be triggered again for this particular pull request. Therefore it would nice to add a pull a button "Trigger Notification on the overview page for each pull request similar to the "Trigger Build" of the Stash Webhook to Jenkins plugin.

No notification/duplicate notification sent for changes in target branch and partially wrong PULL_REQUEST_FROM_HASH

I think I found two scenarios where no notification was sent or where two notifications were sent with PULL_REQUEST_FROM_HASH having an incorrect value:

Here the test setup.

Test 1:
RESCOPED_FROM activated
RESCOPED_TO activated
Change on source branch
Result: Correct trigger with PULL_REQUEST_FROM_HASH containing the correct SHA from the commit on the source branch

Test 2:
RESCOPED activated
Change on source branch
Result: Correct trigger with PULL_REQUEST_FROM_HASH containing the correct SHA from the commit on the source branch

Test 3:
RESCOPED activated
Change on target branch
Result: No trigger
Expected: Trigger with SHA for commit on target branch

Test 4:
RESCOPED_FROM activated
RESCOPED_TO activated
Change on target branch
Result: 2 triggers
Trigger 1: Correct trigger with PULL_REQUEST_FROM_HASH containing the correct SHA from the commit on the source branch
Trigger 2: Wrong trigger with PULL_REQUEST_FROM_HASH containing a SHA which is neither the SHA of the commit from the last commit on the source nor target branch
Expected: 1 Trigger with PULL_REQUEST_FROM_HASH containing the correct SHA from the last commit on the source branch

Would be nice if you can have a look.

We use Stash 3.8.0 and plugin version 1.13

remove width limit

is there a good reason for limiting the width of form.config-area?

filters, URLs (and POST content) can get really long

PS: similarly, the triggers can just be

<fieldset>
<label>...</label>
<label>...</label>
...
</fielset>

with CSS for label float: left

NullPointerException after upgrading

After upgrading to the latest version when I try to configure I get this exception:

Atlassian Stash v3.8.1

2015-08-31 06:33:49,538 ERROR [http-nio-8443-exec-6] malu @PGJE6Zx393x230245x0 mmcpz7 192.168.1.108 "GET /plugins/servlet/prnfs/admin HTTP/1.1" c.a.p.s.DefaultServletModuleManager Unable to create servlet
com.atlassian.util.concurrent.LazyReference$InitializationException: java.lang.NullPointerException
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:149) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.get(LazyReference.java:112) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.applinks.core.rest.context.ContextFilter.doFilter(ContextFilter.java:25) [applinks-plugin-4.3.5_1430735632000.jar:na]
at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:181) [sitemesh-2.5-atlassian-10.jar:na]
at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:85) [sitemesh-2.5-atlassian-10.jar:na]
at com.atlassian.stash.internal.spring.security.StashAuthenticationFilter.doFilter(StashAuthenticationFilter.java:83) [StashAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doInsideSpringSecurityChain(BeforeLoginPluginAuthenticationFilter.java:111) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:77) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.security.auth.trustedapps.filter.TrustedApplicationsFilter.doFilter(TrustedApplicationsFilter.java:100) [atlassian-trusted-apps-core-3.0.8.jar:na]
at com.atlassian.oauth.serviceprovider.internal.servlet.OAuthFilter.doFilter(OAuthFilter.java:79) [atlassian-oauth-service-provider-plugin-1.9.10_1430737736000.jar:na]
at com.atlassian.analytics.client.filter.DefaultAnalyticsFilter.doFilter(DefaultAnalyticsFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.analytics.client.filter.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doBeforeBeforeLoginFilters(BeforeLoginPluginAuthenticationFilter.java:89) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:75) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.request.DefaultRequestManager.doAsRequest(DefaultRequestManager.java:85) [stash-service-impl-3.8.1.jar:na]
at com.atlassian.stash.internal.hazelcast.ConfigurableWebFilter.doFilter(ConfigurableWebFilter.java:38) [ConfigurableWebFilter.class:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_20]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_20]
... 186 frames trimmed
Caused by: java.lang.NullPointerException: null
at com.atlassian.plugin.module.ClassPrefixModuleFactory.createModule(ClassPrefixModuleFactory.java:32) ~[atlassian-plugins-core-3.2.15.jar:na]
at com.atlassian.plugin.module.PrefixDelegatingModuleFactory.createModule(PrefixDelegatingModuleFactory.java:100) ~[atlassian-plugins-core-3.2.15.jar:na]
at com.atlassian.plugin.module.PrefixDelegatingModuleFactory$$FastClassBySpringCGLIB$$e05be356.invoke() ~[spring-core-4.1.4.RELEASE.jar:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at com.atlassian.stash.internal.plugin.OsgiSafeProxyProvider$1.invoke(OsgiSafeProxyProvider.java:93) ~[stash-platform-3.8.1.jar:na]
at com.atlassian.plugin.module.PrefixDelegatingModuleFactory$$EnhancerBySpringCGLIB$$884cef6f.createModule() ~[spring-core-4.1.4.RELEASE.jar:na]
at com.atlassian.util.concurrent.LazyReference$Sync.run(LazyReference.java:325) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:143) ~[atlassian-util-concurrent-2.6.2.jar:na]
... 18 common frames omitted
2015-08-31 06:34:10,583 ERROR [http-nio-8443-exec-12] mail @PGJE6Zx394x230310x1 3p5jne 192.168.1.105 "GET /rest/prnfs-admin/1.0/manual/ HTTP/1.1" c.a.p.s.DefaultServletModuleManager Unable to create filter
com.atlassian.util.concurrent.LazyReference$InitializationException: java.lang.IllegalStateException: Cannot create object because the plugin container is unavailable for bundle 'se.bjurr.prnfs.pull-request-notifier-for-stash'
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:149) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.get(LazyReference.java:112) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.applinks.core.rest.context.ContextFilter.doFilter(ContextFilter.java:25) [applinks-plugin-4.3.5_1430735632000.jar:na]
at com.atlassian.stash.internal.spring.security.StashAuthenticationFilter.doFilter(StashAuthenticationFilter.java:83) [StashAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doInsideSpringSecurityChain(BeforeLoginPluginAuthenticationFilter.java:111) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:77) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.security.auth.trustedapps.filter.TrustedApplicationsFilter.doFilter(TrustedApplicationsFilter.java:100) [atlassian-trusted-apps-core-3.0.8.jar:na]
at com.atlassian.oauth.serviceprovider.internal.servlet.OAuthFilter.doFilter(OAuthFilter.java:79) [atlassian-oauth-service-provider-plugin-1.9.10_1430737736000.jar:na]
at com.atlassian.analytics.client.filter.DefaultAnalyticsFilter.doFilter(DefaultAnalyticsFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.analytics.client.filter.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doBeforeBeforeLoginFilters(BeforeLoginPluginAuthenticationFilter.java:89) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:75) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.request.DefaultRequestManager.doAsRequest(DefaultRequestManager.java:85) [stash-service-impl-3.8.1.jar:na]
at com.atlassian.stash.internal.hazelcast.ConfigurableWebFilter.doFilter(ConfigurableWebFilter.java:38) [ConfigurableWebFilter.class:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_20]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_20]
... 181 frames trimmed
Caused by: java.lang.IllegalStateException: Cannot create object because the plugin container is unavailable for bundle 'se.bjurr.prnfs.pull-request-notifier-for-stash'
at com.atlassian.plugin.osgi.factory.OsgiPluginInstalledHelper.getRequiredContainerAccessor(OsgiPluginInstalledHelper.java:219) ~[atlassian-plugins-osgi-3.2.15.jar:na]
at com.atlassian.util.concurrent.LazyReference$Sync.run(LazyReference.java:325) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:143) ~[atlassian-util-concurrent-2.6.2.jar:na]
... 16 common frames omitted
2015-08-31 06:34:11,182 ERROR [http-nio-8443-exec-23] mail @PGJE6Zx394x230330x1 3p5jne 192.168.1.105 "GET /rest/prnfs-admin/1.0/manual/ HTTP/1.1" c.a.p.s.DefaultServletModuleManager Unable to create filter
com.atlassian.util.concurrent.LazyReference$InitializationException: java.lang.IllegalStateException: Cannot create object because the plugin container is unavailable for bundle 'se.bjurr.prnfs.pull-request-notifier-for-stash'
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:149) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.get(LazyReference.java:112) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.applinks.core.rest.context.ContextFilter.doFilter(ContextFilter.java:25) [applinks-plugin-4.3.5_1430735632000.jar:na]
at com.atlassian.stash.internal.spring.security.StashAuthenticationFilter.doFilter(StashAuthenticationFilter.java:83) [StashAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doInsideSpringSecurityChain(BeforeLoginPluginAuthenticationFilter.java:111) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:77) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.security.auth.trustedapps.filter.TrustedApplicationsFilter.doFilter(TrustedApplicationsFilter.java:100) [atlassian-trusted-apps-core-3.0.8.jar:na]
at com.atlassian.oauth.serviceprovider.internal.servlet.OAuthFilter.doFilter(OAuthFilter.java:79) [atlassian-oauth-service-provider-plugin-1.9.10_1430737736000.jar:na]
at com.atlassian.analytics.client.filter.DefaultAnalyticsFilter.doFilter(DefaultAnalyticsFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.analytics.client.filter.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doBeforeBeforeLoginFilters(BeforeLoginPluginAuthenticationFilter.java:89) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:75) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.request.DefaultRequestManager.doAsRequest(DefaultRequestManager.java:85) [stash-service-impl-3.8.1.jar:na]
at com.atlassian.stash.internal.hazelcast.ConfigurableWebFilter.doFilter(ConfigurableWebFilter.java:38) [ConfigurableWebFilter.class:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_20]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_20]
... 181 frames trimmed
Caused by: java.lang.IllegalStateException: Cannot create object because the plugin container is unavailable for bundle 'se.bjurr.prnfs.pull-request-notifier-for-stash'
at com.atlassian.plugin.osgi.factory.OsgiPluginInstalledHelper.getRequiredContainerAccessor(OsgiPluginInstalledHelper.java:219) ~[atlassian-plugins-osgi-3.2.15.jar:na]
at com.atlassian.util.concurrent.LazyReference$Sync.run(LazyReference.java:325) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:143) ~[atlassian-util-concurrent-2.6.2.jar:na]
... 16 common frames omitted
2015-08-31 06:34:26,370 ERROR [http-nio-8443-exec-31] mail @PGJE6Zx394x230360x2 3p5jne 192.168.1.105 "GET /rest/prnfs-admin/1.0/manual/ HTTP/1.1" c.a.p.s.DefaultServletModuleManager Unable to create filter
com.atlassian.util.concurrent.LazyReference$InitializationException: java.lang.IllegalStateException: Cannot create object because the plugin container is unavailable for bundle 'se.bjurr.prnfs.pull-request-notifier-for-stash'
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:149) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.get(LazyReference.java:112) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.applinks.core.rest.context.ContextFilter.doFilter(ContextFilter.java:25) [applinks-plugin-4.3.5_1430735632000.jar:na]
at com.atlassian.stash.internal.spring.security.StashAuthenticationFilter.doFilter(StashAuthenticationFilter.java:83) [StashAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doInsideSpringSecurityChain(BeforeLoginPluginAuthenticationFilter.java:111) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:77) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.security.auth.trustedapps.filter.TrustedApplicationsFilter.doFilter(TrustedApplicationsFilter.java:100) [atlassian-trusted-apps-core-3.0.8.jar:na]
at com.atlassian.oauth.serviceprovider.internal.servlet.OAuthFilter.doFilter(OAuthFilter.java:79) [atlassian-oauth-service-provider-plugin-1.9.10_1430737736000.jar:na]
at com.atlassian.analytics.client.filter.DefaultAnalyticsFilter.doFilter(DefaultAnalyticsFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.analytics.client.filter.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:32) [analytics-client-3.65_1430737738000.jar:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doBeforeBeforeLoginFilters(BeforeLoginPluginAuthenticationFilter.java:89) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.web.auth.BeforeLoginPluginAuthenticationFilter.doFilter(BeforeLoginPluginAuthenticationFilter.java:75) [BeforeLoginPluginAuthenticationFilter.class:na]
at com.atlassian.stash.internal.request.DefaultRequestManager.doAsRequest(DefaultRequestManager.java:85) [stash-service-impl-3.8.1.jar:na]
at com.atlassian.stash.internal.hazelcast.ConfigurableWebFilter.doFilter(ConfigurableWebFilter.java:38) [ConfigurableWebFilter.class:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_20]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_20]
... 181 frames trimmed
Caused by: java.lang.IllegalStateException: Cannot create object because the plugin container is unavailable for bundle 'se.bjurr.prnfs.pull-request-notifier-for-stash'
at com.atlassian.plugin.osgi.factory.OsgiPluginInstalledHelper.getRequiredContainerAccessor(OsgiPluginInstalledHelper.java:219) ~[atlassian-plugins-osgi-3.2.15.jar:na]
at com.atlassian.util.concurrent.LazyReference$Sync.run(LazyReference.java:325) ~[atlassian-util-concurrent-2.6.2.jar:na]
at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:143) ~[atlassian-util-concurrent-2.6.2.jar:na]
... 16 common frames omitted

Allow creating custom POST bodies and custom headers

It would be nice if when configured to be in POST mode, there could be a place to put in a template that would have the variables and would be "replaced".

For example, I might have the following POST body if you wanted to send JSON:

{
  "from_hash": ${FROM_HASH},
  "to_hash": ${TO_HASH},
  ...
}

or if you wanted to send form encoding:

from_hash=${FROM_HASH}&to_hash=${TO_HASH}&...

In addition, it would be nice to be able to specify custom headers, in case you are trying to send to an API that uses OAuth and not Basic Auth, for example.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.