Skip to content

Commit

Permalink
Add pr description support
Browse files Browse the repository at this point in the history
* add changelog entry

* adding new flag for passing PR documentation

* adding tests for pr_description

* bump version to 1.6.0

* update README with latest command syntax

* fix rebase issue

* moved get_pr_description to apply_transformations

Co-authored-by: Etienne Grignon <etienne_grignon@intuit.com>
  • Loading branch information
sharpyy and etiennegrignon-intuit authored Jun 23, 2020
1 parent 0fd86e3 commit dce7eb6
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 19 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com),
and this project adheres to [Semantic Versioning](https://semver.org).

## [2.1.0] - 2020-06-23
### Added
- New optional flag to pass a description to the PR created by gordian.

## [2.0.0] - 2020-06-23
### Added
- Gordian now forks the repo instead of creating a branch in the specified repo so that users can run Gordian against repos that they do not have write permissions on.
Expand Down
48 changes: 40 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ Gordian applies transformations to files in github repositories and create PRs f

This project grew from a need to keep various kubernetes services consistent and roll out changes at scale. The main use case for this tool is to make changes to configuration files across multiple repositories simultaneously.

# Use Cases
# Usage

## Search and Replace

You can use the docker image to search and replace various strings across repositories.
You can use the docker image to search and replace various strings across repositories. It supports simple and complex search/replace strings operations.

```
docker run --rm -it argoprojlabs/gordian:latest -h
usage: gordian [-h] [-c CONFIG_FILE] [-g GITHUB_API] --pr PR_MESSAGE [-v] [-d]
[-b BRANCH] [-M | -m | -p] -s SEARCH -r REPLACE
[-b BRANCH] [-t TARGET_BRANCH] [-l PR_LABELS [PR_LABELS ...]]
[-M | -m | -p]
[--description DESCRIPTION | --description-file DESCRIPTION_FILE]
[--force-changelog FORCE_CHANGELOG] -s SEARCH -r REPLACE
optional arguments:
-h, --help show this help message and exit
Expand All @@ -38,9 +41,22 @@ optional arguments:
-d, --dry-run Enable dry run mode (default: False)
-b BRANCH, --branch BRANCH
Branch name to use (default: None)
-M, --major Bump the major version. (default: False)
-m, --minor Bump the minor version. (default: False)
-p, --patch Bump the patch version. (default: False)
-t TARGET_BRANCH, --target-branch TARGET_BRANCH
Target branch (default: master)
-l PR_LABELS [PR_LABELS ...], --labels PR_LABELS [PR_LABELS ...]
List of space separated label names you wish to add to
your pull request(s) (default: [])
-M, --major Bump the major version. (default: None)
-m, --minor Bump the minor version. (default: None)
-p, --patch Bump the patch version. (default: None)
--description DESCRIPTION
Description to be passed to the PR. (default: )
--description-file DESCRIPTION_FILE
Local file path for the description to be passed to
the PR. (default: None)
--force-changelog FORCE_CHANGELOG
Fail if changelog does not exist or cannot be parsed
(default: None)
-s SEARCH, --search SEARCH
The string to search for in config files. (default:
None)
Expand All @@ -49,9 +65,21 @@ optional arguments:
string. (default: None)
```

## Simple transformations

You can use the command line interface to make simple changes across various JSON and YAML files, as shown in this example that modifies a kubernetes API Version.

The following command will update the repositories listed in the default config file `config.yaml` by making a new pull request to the target `master` branch
using a new origin branch `update_k8s_apiversion` by updating all files that contains `apiVersion: apps/v1beta2` to replace it with `apiVersion: apps/v1`.
The new PR will have the labels `k8s.1.16` and `support` assigned to it and the `minor` version will be bumped.

```bash
docker run --rm -it argoprojlabs/gordian:latest -b "update_k8s_apiversion" --pr "update_k8s_apiversion" -s "apiVersion: apps/v1beta2" -r "apiVersion: apps/v1" -l k8s.1.16 -v -m
```

## Complex transformations

You can use the interface to script complex changes across various JSON and YAML files, as shown in this example that modifies a kubernetes resource. You can see more examples in the `examples` directory.
You can use the python script interface to make complex changes across various JSON and YAML files, as shown in this example that modifies a kubernetes resource. You can see more examples in the `examples` directory.

```python
import sys
Expand Down Expand Up @@ -130,8 +158,12 @@ collected 33 items

# Support

## Contributors
## Creators
- [Rene Martin](https://github.com/agarfu)
- [Jonathan Nevelson](https://github.com/jnevelson)
- [Corey Caverly](https://github.com/coreycaverly)
- [Sara Blumin](https://github.com/sblumin)

## Contributors
- [Jeremy Chavez](https://github.com/kaosx5s)
- [Etienne Grignon](https://github.com/sharpyy)
38 changes: 29 additions & 9 deletions gordian/gordian.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,6 @@ def get_basic_parser():
dest='target_branch',
help='Target branch'
)
parser.add_argument(
'--force-changelog',
required=False,
dest='force_changelog',
help='Fail if changelog does not exist or cannot be parsed'
)
parser.add_argument(
'-l','--labels',
required=False,
Expand Down Expand Up @@ -114,6 +108,24 @@ def get_basic_parser():
const='patch',
help='Bump the patch version.'
)
pr_desc = parser.add_mutually_exclusive_group(required=False)
pr_desc.add_argument(
'--description',
default='',
dest='description',
help='Description to be passed to the PR.'
)
pr_desc.add_argument(
'--description-file',
dest='description_file',
help='Local file path for the description to be passed to the PR.'
)
parser.add_argument(
'--force-changelog',
required=False,
dest='force_changelog',
help='Fail if changelog does not exist or cannot be parsed'
)
return parser


Expand Down Expand Up @@ -142,9 +154,16 @@ def create_parser(args):

def apply_transformations(args, transformations, pr_created_callback=None):
config = Config(args.config_file)
transform(args, transformations, config.get_data(), pr_created_callback=pr_created_callback)
pr_description = get_pr_description(args)
transform(args, transformations, config.get_data(), pr_description, pr_created_callback=pr_created_callback)

def get_pr_description(args):
if args.description_file is not None:
with open(args.description_file,'r') as fh:
return fh.read()
return args.description

def transform(args, transformations, repositories, pr_created_callback):
def transform(args, transformations, repositories, pr_description, pr_created_callback):
pull_request_urls = []
for repo_name in repositories:
logger.info(f'Processing repo: {repo_name}')
Expand All @@ -155,7 +174,8 @@ def transform(args, transformations, repositories, pr_created_callback):
repo.bump_version(args.dry_run)
if not args.dry_run:
try:
pull_request = repo.create_pr(args.pr_message, '', args.target_branch, args.pr_labels)
pull_request = repo.create_pr(args.pr_message, pr_description, args.target_branch, args.pr_labels)
pull_request.set_labels(*args.pr_labels)
pull_request_urls.append(pull_request.html_url)
if pr_created_callback is not None:
logger.debug(f'Calling post pr created callback with: {pull_request}, {repo.branch_name}')
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
setup_reqs = ['pytest', 'pytest-cov', 'pytest-runner', 'flake8']
setuptools.setup(
name="gordian",
version="2.0.0",
version="2.1.0",
author="Intuit",
author_email="cg-sre@intuit.com",
description="A tool to search and replace files in a Git repo",
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/pr_description
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Custom file for pr description
16 changes: 15 additions & 1 deletion tests/test_gordian.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest
from gordian.config import Config
from gordian.gordian import apply_transformations
from unittest.mock import MagicMock, patch, call, Mock, ANY
from unittest.mock import MagicMock, patch, call, Mock, mock_open, ANY


class TestGordian(unittest.TestCase):
Expand All @@ -19,6 +19,8 @@ def __init__(self, config_file='./tests/fixtures/test_config.yaml', dry_run = Fa
self.semver_label = None
self.target_branch = 'master'
self.pr_labels = ['test']
self.description = ''
self.description_file = None

def test_apply_transformations_without_changes(self):
with patch('gordian.gordian.Repo') as RepoMock, patch('gordian.transformations.Transformation') as TransformationMockClass:
Expand Down Expand Up @@ -75,3 +77,15 @@ def test_apply_transformations_with_changes_default_labels(self):
apply_transformations(gordian_args, [TransformationMockClass])
RepoMock.assert_has_calls([call().bump_version(False), call().bump_version(False)], any_order=True)
RepoMock.assert_has_calls([call().create_pr('test', '', 'master', ANY), call().create_pr('test', '', 'master', ANY)], any_order=True)
self.assertNotIn(call()._repo.create_pull().set_labels(ANY), RepoMock.mock_calls)

def test_apply_transformations_with_changes_custom_description(self):
with patch('gordian.gordian.Repo') as RepoMock, patch('gordian.transformations.Transformation', ) as TransformationMockClass:
instance = RepoMock.return_value
instance.dirty = True
gordian_args = TestGordian.Args()
description = 'Custom file for pr description\n'
gordian_args.description_file = './tests/fixtures/pr_description'
apply_transformations(gordian_args, [TransformationMockClass])
RepoMock.assert_has_calls([call().bump_version(False), call().bump_version(False)], any_order=True)
RepoMock.assert_has_calls([call().create_pr('test', description, 'master', ANY), call().create_pr('test', description, 'master', ANY)], any_order=True)

0 comments on commit dce7eb6

Please sign in to comment.