straight_line 0.1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cd3ea639e178d3b6ba385dfd98073e7db4f2d015
4
+ data.tar.gz: 4b13db7bf8ca43cce49b9f53c5899cf727a2f562
5
+ SHA512:
6
+ metadata.gz: 24a85ef8f1e32ff7e9087ec1a64c79bcafe9ba7bce5f471d8d992184bc16b6b8fe84499a1ff7f6526be72fdb8ad503e504646ccd2389687a1459f5ebed1e27cf
7
+ data.tar.gz: 4ad03255fc52133447017b7e0234e26a763014bade78ae4fdf4b678ccbf4334a535ec824bd1e50260c5f59f877a83c328c9ef6e94c975eba7c446684c2d2618a
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea
11
+ *.gem
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "integration/workflow-test"]
2
+ path = integration/workflow-test
3
+ url = git@github.com:chrisUsick/workflow-test
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'spec/**/*'
4
+
5
+ Metrics/LineLength:
6
+ Max: 85
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.13.7
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at chris.usick@nfl.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in straight_line-git-workflow.gemspec
4
+ gemspec
5
+
6
+ gem 'rubocop', require: false
7
+ gem 'vcr'
8
+ gem 'version_bumper'
9
+ gem 'webmock'
10
+ gem 'simplecov'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Chris Usick
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # StraightLine
2
+
3
+ StraightLine is an opinionated Git workflow tool.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'straight_line'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Next, add these lines to your Rakefile:
18
+
19
+ ```ruby
20
+ require 'straight_line/tasks'
21
+ ```
22
+
23
+ Generate a github api token by following [these instructions](https://help.github.com/articles/creating-an-access-token-for-command-line-use/).
24
+ Make sure the token has the `repo` scope selected.
25
+ Save that token for the next step.
26
+
27
+ Lastly, create a `.netrc` file at `~/.netrc` with the following contents:
28
+
29
+ ```text
30
+ machine api.github.com
31
+ login <Your Github username>
32
+ password <Github API token>
33
+ ```
34
+ ## Usage
35
+
36
+ The basic workflow of StraightLine is:
37
+
38
+ 1. Create a feature branch
39
+ 2. Create a pull request for the feature
40
+ 3. Land the changes to master and delete the remote branch.
41
+
42
+ There are 3 rake commands that help with this workflow.
43
+ Note: the quotation marks are important!
44
+
45
+ 1. `rake "feature:create[<feature-name>]`
46
+ - creates a branch named `feature-name`
47
+ 2. `rake "feature:diff[<title>, <body>]"`
48
+ - Creates a pull request
49
+ - This command manages rebased and/or merging with remote when it is appropriate
50
+ - If a pull request has already been made this command simply pushes you code to the remote
51
+ 3. `rake "feature:land"`
52
+ - This command merges the feature branch to master
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/chrisUsick/straight_line](). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
57
+
58
+
59
+ ## License
60
+
61
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
62
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0.0
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'simple/git/workflow'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/sgw ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'cli/application'
7
+ Application.start ARGV
@@ -0,0 +1,8 @@
1
+ require 'thor'
2
+ require 'cli/feature'
3
+
4
+ # Thor CLI application to use this library's features
5
+ class Application < Thor
6
+ desc 'feature SUBCOMMAND ...ARGS', 'Feature sub commands'
7
+ subcommand 'feature', Cli::Feature
8
+ end
@@ -0,0 +1,12 @@
1
+ require 'thor'
2
+
3
+ module Cli
4
+ # Thor subcommand for feature related commands
5
+ class Feature < Thor
6
+ desc 'create <feature_name>', 'Creates a feature branch'
7
+ def create(feature_name)
8
+ cmd = Feature::Create.new feature_name
9
+ cmd.run
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,49 @@
1
+ require 'open3'
2
+ require 'common/shell_error'
3
+ # Basic class for wrapping shell execution
4
+ class Command
5
+ attr_accessor :working_dir
6
+ def initialize(command, args = [])
7
+ @command = command
8
+ @args = args || []
9
+ @working_dir = Dir.pwd
10
+ @sub_commands = []
11
+ end
12
+
13
+ def arg(argument, *args)
14
+ @args << argument
15
+ @args += args if args
16
+ self
17
+ end
18
+
19
+ def run(return_stderr = false)
20
+ Dir.chdir working_dir do
21
+ command_with_params = "#{@command} #{@args.join ' '}"
22
+
23
+ if return_stderr
24
+ res, status = Open3.capture2e command_with_params
25
+ else
26
+ res, stderr, status = Open3.capture3(command_with_params)
27
+ end
28
+ unless status.exitstatus == 0
29
+ output = return_stderr ? res : "#{res}\n#{stderr}"
30
+ raise ShellError, %(Command `#{command_with_params}` exited with
31
+ status code: #{status.exitstatus}. Command outputted:\n #{output})
32
+ end
33
+
34
+ sub_res = ''
35
+ sub_res = @sub_commands.map do |sub_command|
36
+ sub_command.run return_stderr
37
+ end.join("\n") unless @sub_commands.empty?
38
+
39
+ res + "\n" + sub_res
40
+ end
41
+ end
42
+
43
+ def sub_command(command)
44
+ unless command.is_a? Command
45
+ raise ArgumentError, 'command must be of type common/command'
46
+ end
47
+ @sub_commands << command
48
+ end
49
+ end
@@ -0,0 +1,18 @@
1
+ require 'common/user_error'
2
+ require 'common/command'
3
+
4
+ module Feature
5
+ # Creates a new branch for the feature
6
+ class Create
7
+ def initialize(feature_name)
8
+ raise UserError, 'Feature name required' unless feature_name
9
+ raise UserError, "Feature name can't have spaces" if feature_name.match %r[\s]
10
+ @feature_name = feature_name
11
+ end
12
+
13
+ def run
14
+ cmd = Command.new 'git', ['checkout', '-b', @feature_name]
15
+ cmd.run
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,105 @@
1
+ require 'common/command'
2
+ require 'common/feature'
3
+ require 'common/git_commands/pull'
4
+ require 'common/git_commands/rebase'
5
+ require 'common/git_commands/merge'
6
+ require 'common/git_commands/push'
7
+ require 'common/git_commands/commit'
8
+ require 'common/git_commands/log'
9
+ require 'common/user_error'
10
+ require 'common/github'
11
+ require 'octokit'
12
+
13
+ module Feature
14
+ # Multi purpose feature. It creates a pull request or pushes
15
+ # latest commits to the existing pull request
16
+ class Diff
17
+ include Feature
18
+ attr_reader :feature_name
19
+
20
+ def initialize
21
+ @feature_name = current_feature
22
+ if @feature_name == 'master'
23
+ raise UserError, 'Failed to create diff: you\'re on the master branch'
24
+ end
25
+ return if changes_committed?
26
+ raise UserError, 'Commit your changes before creating a diff'
27
+ end
28
+
29
+ def diff(params)
30
+ pull_cmd = GitCommands::Pull.new('master')
31
+ pull_cmd.run
32
+ if pull_request_exists?
33
+ diff_pull_request_exists params
34
+ else
35
+ diff_no_pull_request params
36
+ end
37
+ end
38
+
39
+ def diff_pull_request_exists(params)
40
+ GitCommands::Merge.new(feature_name, 'master').run
41
+ title, body = extract_params params, [:title, :body]
42
+ begin
43
+ GitCommands::Commit.new(title, body).run
44
+ rescue StandardError => e
45
+ unless e.message.match %r[nothing to commit]
46
+ raise e
47
+ end
48
+ end
49
+ GitCommands::Push.new(feature_name).run
50
+ end
51
+
52
+ def diff_no_pull_request(params)
53
+ GitCommands::Rebase.new('master', feature_name).run
54
+ GitCommands::Push.new(feature_name, false).run
55
+ title, body = extract_params params, [:title, :body]
56
+ pr = create_pull_request title, body
57
+ Util.logger.info %(Pull request created: #{pr.html_url}.)
58
+ end
59
+
60
+ def require_params(params, required)
61
+ required_errors = required.map do |o|
62
+ validate_param params, o
63
+ end.compact
64
+
65
+ raise required_errors.join "\n" unless required_errors.empty?
66
+ end
67
+
68
+ def extract_params(params, keys)
69
+ keys.map do |key|
70
+ case key
71
+ when :title
72
+ params[:title] || last_commit_message
73
+ else
74
+ params[key]
75
+ end
76
+ end
77
+ end
78
+
79
+ def last_commit_message
80
+ GitCommands::Log.new('-1 --pretty=%B').run.split("\n").first
81
+ end
82
+
83
+ # @return String error message if there is an error, else nil
84
+ def validate_param(params, param_spec)
85
+ case param_spec.class
86
+ when Symbol
87
+ "#{param_spec} is not provided." unless params[param_spec]
88
+ end
89
+ end
90
+
91
+ def pull_request_exists?
92
+ if Github.pull_request_for_feature(feature_name)
93
+ true
94
+ else
95
+ false
96
+ end
97
+ end
98
+
99
+ def create_pull_request(title, body)
100
+ Github.create_pull_request feature_name,
101
+ title,
102
+ body
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,54 @@
1
+ require 'common/feature'
2
+ require 'common/git_commands/merge'
3
+ require 'common/git_commands/commit'
4
+ require 'common/git_commands/pull'
5
+ require 'common/git_commands/push'
6
+ require 'common/util'
7
+ require 'common/github'
8
+
9
+ module Feature
10
+ # Merges the feature to master and pushes it
11
+ class Land
12
+ include Feature
13
+ def initialize
14
+ if current_feature == 'master'
15
+ raise UserError,
16
+ 'Failed to create diff: you\'re on the master branch'
17
+ end
18
+ return if changes_committed?
19
+ raise UserError,
20
+ 'Commit your changes before creating a diff'
21
+ end
22
+
23
+ def land(_args = {})
24
+ feature_name = current_feature
25
+ pull_cmd = GitCommands::Pull.new('master')
26
+ pull_cmd.run
27
+ GitCommands::Merge.new(feature_name, 'master').run
28
+
29
+ begin
30
+ GitCommands::Commit.new("Merge master into #{feature_name}", '').run
31
+ rescue StandardError => e
32
+ unless e.message.match %r[nothing to commit]
33
+ raise e
34
+ end
35
+ end
36
+ GitCommands::Push.new(feature_name).run
37
+ if pull_request_closed?(feature_name)
38
+ Util.logger.info %{#{feature_name} was merged in github.
39
+ You're repo is up-to-date with remote}
40
+ else
41
+ GitCommands::Merge.new('master', feature_name).run
42
+ GitCommands::Push.new('master').run
43
+ end
44
+ GitCommands::Push.new(feature_name, delete: true).run
45
+ Command.new('git checkout master').run
46
+ Util.logger.info 'Changes landed to master, on master branch now.'
47
+ end
48
+
49
+ def pull_request_closed?(feature_name)
50
+ p = Github.pull_request_for_feature feature_name
51
+ p.nil? || p.state == 'closed'
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,24 @@
1
+ require 'common/command'
2
+ # Base module for all features
3
+ module Feature
4
+ def current_feature
5
+ res = Command.new('git')
6
+ .arg('branch')
7
+ .run
8
+ .match(/^\*\s+(.*)/)[1].strip
9
+ if res.match(/no branch/)
10
+ raise UserError, %q(A rebase is in process.
11
+ Finish the rebase, then run the command again)
12
+ else
13
+ res
14
+ end
15
+ end
16
+
17
+ def changes_committed?
18
+ cmd = Command.new 'git'
19
+ cmd.arg 'status'
20
+
21
+ out = cmd.run
22
+ out =~ /nothing to commit/
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ require 'common/command'
2
+
3
+ module GitCommands
4
+ # Commit
5
+ class Commit < Command
6
+ def initialize(title, body = '')
7
+ super 'git'
8
+ arg 'commit -a'
9
+ arg %(-m "#{title}") unless title.empty?
10
+ arg %(-m "#{body}") unless body.nil? || body.empty?
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ require 'common/command'
2
+
3
+ module GitCommands
4
+ # Read a config setting
5
+ class Config < Command
6
+ def initialize(setting)
7
+ super 'git'
8
+ arg 'config --get'
9
+ arg setting
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'common/command'
2
+
3
+ module GitCommands
4
+ # return git log information
5
+ class Log < Command
6
+ def initialize(opts)
7
+ super 'git'
8
+ arg 'log'
9
+ arg opts
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ require 'common/command'
2
+ require 'common/git_commands'
3
+
4
+ module GitCommands
5
+ # Merge a branch into base
6
+ class Merge < Command
7
+ include GitCommands
8
+ def initialize(base, branch)
9
+ super('git')
10
+ arg 'checkout'
11
+ arg base
12
+ merge_command = Command.new('git')
13
+ .arg('merge --no-ff')
14
+ .arg(branch)
15
+
16
+ sub_command merge_command
17
+ end
18
+
19
+ def run(*args)
20
+ super true
21
+
22
+ rescue ShellError => e
23
+ handle_merge_conflict e
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ require 'common/command'
2
+
3
+ module GitCommands
4
+ # pull a branch from remote
5
+ class Pull < Command
6
+ def initialize(branch)
7
+ super('git')
8
+ arg 'checkout'
9
+ arg branch
10
+ pull_command = Command.new 'git'
11
+ pull_command
12
+ .arg('pull origin')
13
+ .arg branch
14
+ sub_command pull_command
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ require 'common/command'
2
+
3
+ module GitCommands
4
+ # Push a branch to remote
5
+ class Push < Command
6
+ def initialize(branch, remote_exists = true, opts = {})
7
+ super('git')
8
+ arg 'checkout'
9
+ arg branch
10
+ if remote_exists.is_a? Hash
11
+ opts = remote_exists
12
+ remote_exists = true
13
+ end
14
+
15
+ sub_command push_command(branch, remote_exists, opts)
16
+ end
17
+
18
+ def push_command(branch, remote_exists, opts)
19
+ push_command = Command.new('git')
20
+ .arg('push')
21
+
22
+ if opts[:delete]
23
+ push_command
24
+ .arg('origin')
25
+ .arg('--delete')
26
+ .arg(branch)
27
+ elsif !remote_exists
28
+ push_command
29
+ .arg('--set-upstream')
30
+ .arg('origin')
31
+ .arg(branch)
32
+ end
33
+ push_command
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ require 'common/command'
2
+ require 'common/shell_error'
3
+ require 'common/git_commands'
4
+
5
+ module GitCommands
6
+ # Rebase a branch to a base
7
+ class Rebase < Command
8
+ include GitCommands
9
+ def initialize(base, branch)
10
+ super('git')
11
+ arg 'rebase'
12
+ arg base
13
+ arg branch
14
+ end
15
+
16
+ def run(*args)
17
+ super true
18
+ rescue ShellError => e
19
+ handle_merge_conflict(e)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ require 'common/util'
2
+ module GitCommands
3
+ def handle_merge_conflict(e)
4
+ if e.message.match %r[Merge conflict in]
5
+ Util.logger.error %q(***** Hint: this looks like a merge conflict.
6
+ Try fixing the conflicts, then run `git add .` and then run the previous command again.)
7
+ end
8
+ raise e
9
+ end
10
+ end
@@ -0,0 +1,76 @@
1
+ require 'singleton'
2
+ require 'octokit'
3
+ require 'common/user_error'
4
+ require 'common/git_commands/config'
5
+
6
+ # Github API wrapper
7
+ class Github
8
+ include Singleton
9
+
10
+ def initialize
11
+ @client = nil
12
+ end
13
+
14
+ def self.make_class(name)
15
+ class << self
16
+ self
17
+ end.instance_eval do
18
+ define_method name do |*args|
19
+ instance.send name, *args
20
+ end
21
+ end
22
+ end
23
+
24
+ def login; end
25
+
26
+ def list_repos
27
+ @client.repositories query: { type: 'private' }
28
+ end
29
+
30
+ def user
31
+ @client.user
32
+ end
33
+
34
+ def ensure_logged_in
35
+ raise UserError, 'Must be logged in first' unless @client
36
+ end
37
+
38
+ def client
39
+ return @client if @client
40
+
41
+ @client = Octokit::Client.new netrc: true, auto_paginate: true
42
+ end
43
+
44
+ def create_pull_request(branch, title, body)
45
+ repo = repo_name
46
+ client.create_pull_request repo,
47
+ 'master', "#{github_login}:#{branch}", title, body
48
+ end
49
+ make_class :create_pull_request
50
+
51
+ def repo_name
52
+ cmd = GitCommands::Config.new('remote.origin.url')
53
+ remote = cmd.run
54
+ remote.match(%r{(git@github.com:)(.*/.*)})[2]
55
+ end
56
+
57
+ def github_login
58
+ client.user.login
59
+ end
60
+ make_class :github_login
61
+
62
+ def pull_requests
63
+ client.pull_requests repo_name
64
+ end
65
+ make_class :pull_requests
66
+
67
+ def pull_request_for_feature(feature)
68
+ prs = pull_requests
69
+ prs.find do |p|
70
+ p.head.ref == feature &&
71
+ p.head.user.login == Github.github_login &&
72
+ p.base.ref == 'master'
73
+ end
74
+ end
75
+ make_class :pull_request_for_feature
76
+ end
@@ -0,0 +1,4 @@
1
+
2
+ class ShellError < StandardError
3
+
4
+ end
@@ -0,0 +1,3 @@
1
+
2
+ # An error caused from user input
3
+ class UserError < StandardError; end
@@ -0,0 +1,7 @@
1
+ require 'logger'
2
+
3
+ class Util
4
+ def self.logger
5
+ @logger ||= Logger.new STDOUT
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+
2
+ # Base module definition
3
+ module StraightLine
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,12 @@
1
+ require 'rake'
2
+ require 'common/command'
3
+ require 'common/feature/create'
4
+
5
+ namespace 'feature' do
6
+ desc 'Creates a feature branch'
7
+ task :create, [:feature_name] do |_, args|
8
+ feature_name = args[:feature_name]
9
+ cmd = Feature::Create.new feature_name
10
+ cmd.run
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'common/command'
3
+ require 'common/feature/diff'
4
+
5
+ namespace 'feature' do
6
+ desc 'Manages a pull request for the current feature branch'
7
+ task :diff, [:title, :body] do |_, args|
8
+ Feature::Diff.new.diff(args)
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ require 'rake'
2
+ require 'common/command'
3
+ require 'common/feature/land'
4
+
5
+ namespace 'feature' do
6
+ desc 'Merges master into the feature branch then merges
7
+ feature into master, and pushes to master'
8
+ task :land, [] do |_, args|
9
+ Feature::Land.new.land(args)
10
+ end
11
+ end
data/lib/tasks.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'tasks/feature/create'
2
+ require 'tasks/feature/diff'
3
+ require 'tasks/feature/land'
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'common/command'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'straight_line'
8
+ spec.version = File.read('VERSION').strip
9
+ spec.authors = ['Chris Usick']
10
+ spec.email = ['christopher.usick@gmail.com']
11
+
12
+ spec.summary = 'Rake commands to perform simple git workflow'
13
+ spec.description = %(
14
+ This module provides an opinionated git workflow)
15
+ spec.homepage = 'https://github.com/chrisUsick/straight_line'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.bindir = 'exe'
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.13'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ spec.add_dependency 'thor'
29
+ spec.add_dependency 'octokit'
30
+ spec.add_dependency 'netrc'
31
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: straight_line
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Usick
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-02-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: octokit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: netrc
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: |2-
98
+
99
+ This module provides an opinionated git workflow
100
+ email:
101
+ - christopher.usick@gmail.com
102
+ executables:
103
+ - sgw
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - ".gitignore"
108
+ - ".gitmodules"
109
+ - ".rspec"
110
+ - ".rubocop.yml"
111
+ - ".travis.yml"
112
+ - CODE_OF_CONDUCT.md
113
+ - Gemfile
114
+ - LICENSE.txt
115
+ - README.md
116
+ - Rakefile
117
+ - VERSION
118
+ - bin/console
119
+ - bin/setup
120
+ - exe/sgw
121
+ - lib/cli/application.rb
122
+ - lib/cli/feature.rb
123
+ - lib/common/command.rb
124
+ - lib/common/feature.rb
125
+ - lib/common/feature/create.rb
126
+ - lib/common/feature/diff.rb
127
+ - lib/common/feature/land.rb
128
+ - lib/common/git_commands.rb
129
+ - lib/common/git_commands/commit.rb
130
+ - lib/common/git_commands/config.rb
131
+ - lib/common/git_commands/log.rb
132
+ - lib/common/git_commands/merge.rb
133
+ - lib/common/git_commands/pull.rb
134
+ - lib/common/git_commands/push.rb
135
+ - lib/common/git_commands/rebase.rb
136
+ - lib/common/github.rb
137
+ - lib/common/shell_error.rb
138
+ - lib/common/user_error.rb
139
+ - lib/common/util.rb
140
+ - lib/straight_line.rb
141
+ - lib/tasks.rb
142
+ - lib/tasks/feature/create.rb
143
+ - lib/tasks/feature/diff.rb
144
+ - lib/tasks/feature/land.rb
145
+ - straight_line.gemspec
146
+ homepage: https://github.com/chrisUsick/straight_line
147
+ licenses:
148
+ - MIT
149
+ metadata: {}
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ requirements: []
165
+ rubyforge_project:
166
+ rubygems_version: 2.5.1
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: Rake commands to perform simple git workflow
170
+ test_files: []