Skip to content

Commit

Permalink
Adding settings file parsing validation. Improving the README.
Browse files Browse the repository at this point in the history
  • Loading branch information
rushmin committed Sep 20, 2015
1 parent a049d3c commit ffb716c
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 61 deletions.
110 changes: 59 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,28 @@
# ci-tools

####What ?
####What is 'ci-tools'?
Some CI utils for Git and Maven. Only supports merging GitHub pull requests as of now.

####Requirements
Python 2.7.5+

Python-requests **[1]**
[Python-requests](http://www.python-requests.org/en/latest/user/install/#install)
(In some environments this module is pre-installed)

####Usage

```
ci-tools.py [-h] [--settings SETTINGS] [-v] merge pr [-h] [-c CLONE_LOCATION] [-b BRANCH]
[--no-cleanup] [--no-strict-mode] [--no-update]
[-p]
pullRequestUrl
required arguments:
pullRequestUrl
URL of the pull request. e.g. https://github.com/john/ci-tools-test/pull/2
optional arguments:
-h, --help
show this help message and exit
-c CLONE_LOCATION, --clone-location CLONE_LOCATION
clone location of the base repo
-b BRANCH, --branch BRANCH
local base branch for the merge
####Installation

--no-cleanup
do not clean up intermediate artifacts
--no-strict-mode
switch off the strict mode
--no-update
update the clone before the merge
-p, --push
push the merge to the origin
#####1. Download the 'ci-tools.py' file from the latest release tag of the [GitHub repo](https://github.com/rushmin/ci-tools/releases).

#####2. Add an alias

```
alias ci-tools='python /path/to/ci-tools.py'
```

####Settings
#####3. Create the settings file

ci-tools needs a settings file which contains settings to access git providers like GitHub. (See the sample settings file below)

**NOTE :** You only have to change the username and the password in this settings file, unless the git providers has changed their HTTP resource URLs.


The settings file can be specified using the **_--settings_** argument.

If the file is not specified, ci-tools searches for a local settings file named **_ci-tools-settings.json_** in the **_current directory_**
Expand All @@ -63,6 +31,8 @@ If ci-tools can't find such file, it tries to load the default setting file loca

So make sure a settings file is located at least in of these locations.

**NOTE :** You only have to change the username and the password in this settings file, unless the git providers has changed their HTTP resource URLs.

#####Sample settings file

```json
Expand All @@ -89,42 +59,80 @@ So make sure a settings file is located at least in of these locations.
}
}
```

####Usage

```
ci-tools.py [-h] [--settings SETTINGS] [-v] merge pr [-h] [-c CLONE_LOCATION] [-b BRANCH]
[--no-cleanup] [--no-strict-mode] [--no-update]
[-p]
pullRequestUrl
required arguments:
pullRequestUrl
URL of the pull request. e.g. https://github.com/john/ci-tools-test/pull/2
optional arguments:
-h, --help
show this help message and exit
-c CLONE_LOCATION, --clone-location CLONE_LOCATION
clone location of the base repo
-b BRANCH, --branch BRANCH
local base branch for the merge
--no-cleanup
do not clean up intermediate artifacts
--no-strict-mode
switch off the strict mode
--no-update
update the clone before the merge
-p, --push
push the merge to the origin
```


####Recipes

#####Testing and closing a pull request
#####1.Testing and closing a pull request

* Clone the base repo
* Merge the pull request locally, using the following command

```
python ci-tools.py merge pr https://github.com/john/ci-tools-test/pull/8
ci-tools merge pr https://github.com/john/ci-tools-test/pull/8
```

* Build the repo and test it.
* Push the base branch to the origin. (This step will close the pull request)


**Tip:**
If the merge should be pushed to the base repo right after the merge, the following command can be used. But this exactly what we do using the GitHub UI

```
python ci-tools.py merge pr --push https://github.com/john/ci-tools-test/pull/8
ci-tools merge pr --push https://github.com/john/ci-tools-test/pull/8
```

#####Merging a pull request locally on to a branch other than the base branch of the pull request.
#####2.Merging a pull request locally on to a branch other than the base branch of the pull request.

```
python ci-tools.py merge pr -b new-branch https://github.com/john/ci-tools-test/pull/8
ci-tools merge pr -b new-branch https://github.com/john/ci-tools-test/pull/8
```

**NOTE** : If the target branch doesn't exist in the origin, **--no-update** switch should be used. This switch tells ci-tools not to pull the target branch from the origin.

#####Merging a pull request on to a local repo which is not a clone of the pull request base. e.g. a fork of the base
#####3.Merging a pull request on to a local repo which is not a clone of the pull request base. e.g. a fork of the base

```
python ci-tools.py merge pr --no-strict-mode https://github.com/john/ci-tools-test/pull/8
ci-tools merge pr --no-strict-mode https://github.com/john/ci-tools-test/pull/8
```

**--no-strict-mode** switch, disables the strict mode. This allows ci-tools to merge a pull request to a repo whose origin is not the base of the pull request.


[1] - http://www.python-requests.org/en/latest/user/install/#install
37 changes: 27 additions & 10 deletions ci-tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ def mergePullRequest(self, cloneLocation, pullRequestUrl, branch, shouldCleanup,
if self.isVerboseEnabled:
print '\n\tResponse Content\n\n<START>{}<END>'.format(response.text)

pullRequestInfo = response.json();
try:
pullRequestInfo = response.json();
except ValueError:
print "\nError ! Can't parse API response. Use verbose mode to see more details.\n"
exit(105)

if self.shouldContinue(pullRequestInfo) is False:
print '\nBye\n'
Expand All @@ -47,11 +51,9 @@ def mergePullRequest(self, cloneLocation, pullRequestUrl, branch, shouldCleanup,
validationResult = self.validatePullRequest(pullRequestInfo, isStrictMode)

if validationResult['status'] is False:
print '\nError : Cannot merge the pull requet. Reason : {} \n'.format(validationResult['reason'])
print '\nError ! Cannot merge the pull requet. Reason : {} \n'.format(validationResult['reason'])
exit(101)

print "\nMerging pull requeust. repo : '{}', repo-owner : '{}', pull-request-id : '{}'".format(repoName, repoOwner, pullRequestId)

# Fetch from the origin
if shouldUpdate:
self.git('fetch')
Expand Down Expand Up @@ -104,12 +106,15 @@ def shouldContinue(self, pullRequestInfo):

baseRepo = pullRequestInfo['base']['repo']['full_name']
baseBranch = pullRequestInfo['base']['ref']
creator = pullRequestInfo['user']['login']
creator = '{} ({})'.format(pullRequestInfo['user']['login'],pullRequestInfo['user']['html_url'])
title = pullRequestInfo['title']
number = pullRequestInfo['number']
updatedAt = pullRequestInfo['updated_at']
commits = pullRequestInfo['commits']
pullRequestBranch = pullRequestInfo['head']['ref']

message = message + '\n\tbase-repo = {}\n\tbase-branch = {}\n\tcreator = {}\n\ttitle = {}\n\tupdated-at = {}\n\tpull-request-branch = {}\n\n ==> [Yes/no] - '.format(baseRepo, baseBranch, creator, title, updatedAt, pullRequestBranch)
message = message + '\n\tbase-repo = {}\n\tbase-branch = {}\n\tcreator = {}\n\ttitle = {}\n\tnumber = {}\n\tupdated-at = {}\n\tcommits = {}\n\tpull-request-branch = {}\n\n ==> [Yes/no] - '\
.format(baseRepo, baseBranch, creator, title, number, updatedAt, commits, pullRequestBranch)

response = raw_input(message);

Expand All @@ -136,7 +141,7 @@ def validatePullRequest(self, pullRequestInfo, isStrictMode):

# Check whether the pull request is already merged
if pullRequestInfo['merged'] is True:
return {'status':False, 'reason':'Pull request is already merged.'}
return {'status':False, 'reason':'Pull request has already been merged.'}

return {'status':True, 'reason':''}

Expand Down Expand Up @@ -169,7 +174,7 @@ def invokeGitHubApi(self, url, params={}):

if response.status_code is not requests.codes.ok:
print '\n\tError ! Status code : {}'.format(response.status_code)
exit()
exit(104)

return response

Expand Down Expand Up @@ -225,6 +230,9 @@ def main(argv):

# Load settings
settings = loadSettings(args.settings)
if settings is None:
print "\nError ! Can't read the settings file.\n"
exit(103)

# Execute the command
ciTools = CITools(settings, args)
Expand Down Expand Up @@ -261,15 +269,24 @@ def getArgParser():

def loadSettings(location):

# Try the default settings file locations if the location is not specified.
if location is None:

defaultSettingsFileName = '/ci-tools-settings.json'
if os.path.exists(os.getcwd() + defaultSettingsFileName):
location = os.getcwd() + defaultSettingsFileName
else:
elif os.path.exists(os.environ['HOME'] + '/.ci-tools'+ defaultSettingsFileName):
location = os.environ['HOME'] + '/.ci-tools'+ defaultSettingsFileName

return json.loads(open(location).read())
if location is not None:
try:
settings = json.loads(open(location).read())
return settings
except ValueError:
print "\nError ! {} is not a valid JSON file.".format(location)
return None
else:
return None

# --------- Util methods ---------

Expand Down

0 comments on commit ffb716c

Please sign in to comment.