Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Stash merge-check hook for deploying changed code

Benjamin Bergman September 6, 2013

I am trying to write a merge-check hook that will take the list of changed files from a pull request and run a system command on them, effectively for deployment. I only want to deal with the changed files as the repositories I will be dealing with have thousands of files in a single directory. I would just write a bash script, but need the configurability the Stash UI provides.

I've got a demo hook running with atlas-run, so I've got the very basics going. I know that, were I on the command line, I could run 'git diff --name-only master..pullrequest_branch' for a list of changed files, which I can copy into a temp directory with 'git cat-file', 'git show', etc. Right now my bottle neck is just getting access to the repository.

First of all, should I be using system calls for the above actions, or can I get this information using the built in git libraries?

Second, how do I get that information from my repository? Using the git library, I can probably use the hook's context directly, but if I am running the system calls, how do I get the directory from which I need to run these commands?

7 answers

1 accepted

1 vote
Answer accepted
cofarrell
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 6, 2013

Hi Benjamin,

If you're writing a merge-check my advice would be to stick to the Stash API where possible. For normal operations like comparing revisions and getting the file contents we have already handled all the plumbing for you.

Jason has got some useful advice here. You will probably be interested in the HistoryService.getChanges() method, which is basically your 'git diff' command.

https://answers.atlassian.com/questions/171295/stash-pre-receive-hook-plugin-accessing-committed-contents

And I link to my plugin which does some/most of what you want here:

https://bitbucket.org/atlassianlabs/stash-filesize-hook-plugin/src/master/src/main/java/com/atlassian/stash/plugin/filesize/FilesizeHook.java?at=master

I know there's a fair amount of Java noise in there. :( I use cat-file to get the file size, but we have a ContentService.streamFile if you're just looking to do a 'git show'.

If you just want the repository directory you can get it from:

https://developer.atlassian.com/static/javadoc/stash/latest/api/reference/com/atlassian/stash/server/ApplicationPropertiesService.html#getRepositoryDir(com.atlassian.stash.repository.Repository)

You'll then need to fork out to Git and parse the results yourself. As mentioned above, if you can navigate our Java API I would recommend sticking with what we have as it should (hopefully) make your life a little easier.

Let me know if you have any more specific questions or need help with your plugin/hook.

Cheers,

Charles

Benjamin Bergman September 8, 2013

Right now I'm thinking the simplest solution is to get the repository directory and then fork to a script to do the actual heavy lifting. There is just too much Java noise to sift through for what I need, and I know exactly what git commands I need to run to get what I want.

I'm trying to call the getRepositoryDir() function you linked above, but get an error:

cannot find symbol
symbol  : method getRepositoryDir(com.atlassian.stash.repository.Repository)

I have added

import com.atlassian.stash.server.*

to the top of my java file and I am just calling the function like so:

System.out.println("repo " + getRepositoryDir(context.getRepository()));

Any idea why I am getting that error?

Benjamin Bergman September 8, 2013

I just realized that getRepositoryDir is a class function, so that is problem one. I tried creating an ApplicationPropertiesService, but get an error saying that the class is abstract and cannot be instantiated, and if I try to call ApplicationPropertiesService.getRepositoryDir(), I get an error saying that it cannot be referenced from a static context.

Is there an ApplicationPropertiesService object somewhere else that I should be calling this function on?

Benjamin Bergman September 8, 2013

I added an ApplicationPropertiesService argument to my plugin constructor and it is now magically working. I'm not totally sure how it know to pass things into the constructor, but I'll just accept it and move on for now.

Benjamin Bergman September 9, 2013

I decided to try a bit harder to use the API and made some progress, but it seems that the version of HistoryService's getChangesetBetween() that you are using is deprecated. I'm trying to update it to use a newer version, but am getting errors in my import lines. I made a new question for this problem here: https://answers.atlassian.com/questions/209860/cannot-find-symbol-class-changesetsbetweenrequest

cofarrell
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 9, 2013

Putting exported Stash services in the constructor will autowire them using Spring. Not sure that necessarily helps explain how it works, but it's a long story. That's how all the Atlassian plugins work though.

Charles

0 votes
Benjamin Bergman September 6, 2013

I think what you have provided will get me going. It has been a few years since I've done anything in Java, so I'm still just trying to wade through all this stuff. Thanks for the pointers. I'll let you know if I have more questions.

0 votes
cofarrell
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 6, 2013

One last thing - I'm just wondering if this could be done as part of a normal build operation? Normally the Stash team (and Atlassian in general) would do deployments from a Bamboo plan when a branch (ie master) has changed. Bamboo 5.0 even has a new deployments feature.

This may not be possible in your scenario, depending on what configuration in Stash you're providing and how critical it is to the build scripts to know what changed in any given merge (that may be available to the plan, I'm not 100% sure).

</sales-pitch> :)

Charles

0 votes
cofarrell
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 6, 2013

Hi Ben,

Was your last comment "how do I access files in the current repository" answered in some part from my response below? Specifically you can use the ContentService to get access to the file stream and HistoryService to do the diff.

Charles

0 votes
cofarrell
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 6, 2013

Hi again,

If you're deploying something I _definitely_ wouldn't do this as part of a merge check. They fire every time a user views a pull request page.

You should be able to do the deploy as part of post-receive hook and/or just listen specfiically for PullRequestMergedEvent which has a list of RefChange objects which you can then diff as you would in the merge-check. Does that make sense?

Cheers,

Charles

0 votes
Benjamin Bergman September 6, 2013

For my purposes, I can log the last successful deployment in a file outside of stash and use that as a reference to get the changed files, so that problem is solved. Now I just need the original question solved: how do I access files in the current repository?

0 votes
Benjamin Bergman September 6, 2013

Just realized that merge-check might not be the best choice. This deployment hook could potentially fire before other possibly blocking checks. The problem of doing a post-receive hook is that finding the list of changed files might be more challenging. If anyone has a solution to that, I'm all ears.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events