releasinator 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +0 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +44 -0
- data/README.md +114 -0
- data/Rakefile +1 -0
- data/lib/command_processor.rb +55 -0
- data/lib/config_hash.rb +44 -0
- data/lib/copy_file.rb +10 -0
- data/lib/current_release.rb +9 -0
- data/lib/default_config.rb +34 -0
- data/lib/downstream_repo.rb +18 -0
- data/lib/git_util.rb +67 -0
- data/lib/github_repo.rb +45 -0
- data/lib/printer.rb +21 -0
- data/lib/publisher.rb +47 -0
- data/lib/releasinator/version.rb +3 -0
- data/lib/tasks/releasinator.rake +529 -0
- data/lib/validator.rb +312 -0
- data/lib/validator_changelog.rb +82 -0
- data/releasinator.gemspec +39 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 194855b8293cef00a51d7cf0db1d92ffc40b8431
|
4
|
+
data.tar.gz: 3a83dfbf189daeed8dd226c6b58618d946d10a6b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cb334694d56c8b3152eb861d57b6861b8a7605a1ee2278916589b334f577b5abc8e8e1bc154632b25dd5abda40223c8c048add31764545b3a0526315eaed288e
|
7
|
+
data.tar.gz: 3e0c022e3146461f65cf51642a094606cf572c0e371543f8e3d9ad20bfb6e5b154739bfc9de08f915343beed4571a9745b04ce25db1005236acf9a81474f2642
|
data/.gitignore
ADDED
File without changes
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
releasinator (0.1.0)
|
5
|
+
colorize
|
6
|
+
configatron
|
7
|
+
json
|
8
|
+
octokit (~> 4.0)
|
9
|
+
semantic
|
10
|
+
vandamme
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
addressable (2.4.0)
|
16
|
+
colorize (0.7.7)
|
17
|
+
configatron (4.5.0)
|
18
|
+
faraday (0.9.2)
|
19
|
+
multipart-post (>= 1.2, < 3)
|
20
|
+
github-markup (1.4.0)
|
21
|
+
json (1.8.3)
|
22
|
+
multipart-post (2.0.0)
|
23
|
+
octokit (4.3.0)
|
24
|
+
sawyer (~> 0.7.0, >= 0.5.3)
|
25
|
+
rake (11.1.2)
|
26
|
+
redcarpet (3.3.4)
|
27
|
+
sawyer (0.7.0)
|
28
|
+
addressable (>= 2.3.5, < 2.5)
|
29
|
+
faraday (~> 0.8, < 0.10)
|
30
|
+
semantic (1.4.1)
|
31
|
+
vandamme (0.0.11)
|
32
|
+
github-markup (~> 1.3)
|
33
|
+
redcarpet (~> 3.3.2)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
bundler (~> 1.11)
|
40
|
+
rake (~> 11.1)
|
41
|
+
releasinator!
|
42
|
+
|
43
|
+
BUNDLED WITH
|
44
|
+
1.11.2
|
data/README.md
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
# Releasinator
|
2
|
+
|
3
|
+
## Problem
|
4
|
+
|
5
|
+
When automating an SDK release process, many teams and languages have different ideas. The release process is a hurdle that makes it hard for new project members to ramp up. One shouldn't have to read a `release_process.md` to release an open source SDK.
|
6
|
+
|
7
|
+
## Solution
|
8
|
+
|
9
|
+
The releasinator corrects this by enforcing standard must-have release files, being configurable where necessary, and reducing the ramp-up hurdle.
|
10
|
+
|
11
|
+
## Making it work
|
12
|
+
|
13
|
+
### Install
|
14
|
+
|
15
|
+
1. Clone this repo
|
16
|
+
2. Run `bundle install` from terminal. It should download dependencies.
|
17
|
+
|
18
|
+
### Setup
|
19
|
+
|
20
|
+
1. Set the environment variable `GITHUB_TOKEN` with a [generated personal access token](https://github.com/settings/tokens) with `repo` scope.
|
21
|
+
|
22
|
+
### Usage
|
23
|
+
|
24
|
+
1. `cd` to directory of the repo you'd like to release
|
25
|
+
2. Run `rake -t -f <path to releasinator>/Rakefile`
|
26
|
+
|
27
|
+
## Conventions
|
28
|
+
|
29
|
+
The releasinator enforces certain conventions. If a filename doesn't exactly match the convention, it is renamed to match, and automatically committed. The conventions are documented below:
|
30
|
+
|
31
|
+
1. `README.md`
|
32
|
+
2. `LICENSE`: See [here](http://stackoverflow.com/questions/5678462/should-i-provide-a-license-txt-or-copying-txt-file-in-my-project) for a relevant StackOverflow post on this discussion. This project has chosen to exclude the `.txt` extension to match other popular projects, and GitHub defaults.
|
33
|
+
3. `CONTRIBUTING.md`: See [a relevant GitHub blog post](https://github.com/blog/1184-contributing-guidelines) for relevant information. This project has chosen to include the `.md` extension, as these files can get a bit unwieldy without formatting.
|
34
|
+
4. `CHANGELOG.md` - This file is the source of truth for the releasinator. The file should be organized with the most recent release on top, and formatted correctly. The latest release is the one used when the releasinator executes, so it is a precondition that the `CHANGELOG.md` has been edited and committed **prior to releasing**.
|
35
|
+
1. Releases either are contained within an Alt-H2 (`------`) or `##H2` format. Any other format will be rejected.
|
36
|
+
2. Each release MUST start with the release version, and may contain any following text, such as the date, and/or any release summary.
|
37
|
+
|
38
|
+
## Behind the Scenes
|
39
|
+
|
40
|
+
#### Validations
|
41
|
+
|
42
|
+
1. ✓ Validate git version.
|
43
|
+
1. ✓ Validate git's cleanliness (no untracked, unstaged, or uncommitted files).
|
44
|
+
1. ✓ Validate current git branch is up to date with the latest version on server.
|
45
|
+
1. ✓ Validate current git branch is `master` (if no git flow), or `develop` or `release/<Release number>` if using git flow.
|
46
|
+
1. ✓ Validate the presence of`.gitignore`, adding it if needed, and adding any needed lines.
|
47
|
+
1. ✓ Validate the presence of the `README.md` file.
|
48
|
+
1. ✓ Validate the presence of the `CHANGELOG.md` file.
|
49
|
+
1. ✓ Validate the `CHANGELOG.md` file is properly formatted.
|
50
|
+
1. ✓ Validate semver release number sequence in `CHANGELOG.md`. (Note: cannot detect duplicate versions, due to the underlying Hash implementation of the parsing library.)
|
51
|
+
1. ✓ Validate the presence of `LICENSE`.
|
52
|
+
1. ✓ Validate the presence of `CONTRIBUTING.md`.
|
53
|
+
1. ✓ Validate the presence of `.github/ISSUE_TEMPLATE.md`.
|
54
|
+
1. ✓ Validate `LICENSE` and `CONTRIBUTING.md` are referenced in `README.md`.
|
55
|
+
1. ✓ Validate all submodules are up to date with the latest master version.
|
56
|
+
1. ✓ Validate all files are committed to git (`git ls-files --others --exclude-standard`).
|
57
|
+
1. ✓ Validate user has valid access_tokens as environment variables for all repos (public & enterprise). Public github requires `GITHUB_TOKEN`, while enterprise tokens add a modified version of their domain as a prefix. For example, github.example.com requires `GITHUB_EXAMPLE_COM_GITHUB_TOKEN`.
|
58
|
+
1. ✓ Validate user has permissions to push to repo, and downstream repos.
|
59
|
+
1. ✓ Validate anything as defined by the configuration. Examples:
|
60
|
+
* Compiling with the right version of the platform.
|
61
|
+
* Upstream library dependencies are the latest available.
|
62
|
+
|
63
|
+
#### Package manager credential management
|
64
|
+
1. Validate permissions to publish to package manager
|
65
|
+
2. If permissions are needed, retrieve them from the secret credential repo, and run any subsequent repo steps.
|
66
|
+
|
67
|
+
#### Performs internal-only tasks:
|
68
|
+
|
69
|
+
1. ✓ Confirm user has completed all manual tasks (aka pre-release checklist).
|
70
|
+
1. ✓ Confirm overwrite of local tags already matching version.
|
71
|
+
1. ✓ Create local tag.
|
72
|
+
1. ✓ Run build command, as specified in the config file.
|
73
|
+
|
74
|
+
#### Performs external-facing tasks:
|
75
|
+
|
76
|
+
1. ✓ Clone/reset any downstream external distribution repos.
|
77
|
+
2. ✓ Copy to destination repo:
|
78
|
+
|
79
|
+
* `README.md`
|
80
|
+
* `CHANGELOG.md`
|
81
|
+
* `LICENSE`
|
82
|
+
* `CONTRIBUTING.md`
|
83
|
+
* `.github/ISSUE_TEMPLATE.md`
|
84
|
+
* Any other distribution files. This will be configured.
|
85
|
+
|
86
|
+
3. ✓ Modify any dependency/versions in `README.md`, source, or sample apps to the latest version. The location and regex of these will be configured.
|
87
|
+
4. ✓ Build code and/or Sample apps.
|
88
|
+
* TODO If build fails, pause build and give developer a chance to fix the downstream build and retry without completely starting over.
|
89
|
+
|
90
|
+
5. ✓ Push to appropriate package manager (nexus/cocoapods/composer/npm/nuget/rubygem/pypi).
|
91
|
+
6. ✓ Confirm overwrite of remote tags already matching version.
|
92
|
+
7. ✓ Create root and downstream repo tag and GitHub release. The name of the release is the tag, and the annotated description and GitHub release is the relevant section of the `CHANGELOG.md`.
|
93
|
+
8. ✓ Create downstream GitHub branch.
|
94
|
+
9. ✓ Correctly handle git flow branches and merging.
|
95
|
+
9. ✓ Push to external repo (once live in external package manager).
|
96
|
+
10. ✓ Create PRs into any downstream dependencies, including the release notes in the PR. Examples:
|
97
|
+
|
98
|
+
* Create a PR into Braintree when mSDK/OTC release.
|
99
|
+
* Create a PR into Cordova when mSDK release.
|
100
|
+
* Create a PR into any other framework that has a direct dependency on this repo.
|
101
|
+
|
102
|
+
11. TODO add those same release notes within the release notes of the downstream repo.
|
103
|
+
11. Assemble a draft of news, and publish (where possible, i.e. send email, tweet, whatever).
|
104
|
+
|
105
|
+
#### Open items:
|
106
|
+
|
107
|
+
* Might need a different name - [releasinator is taken](https://qconnewyork.com/ny2015/system/files/presentation-slides/QCon%20Distributing%20a%20Mobile%20Team.pdf)
|
108
|
+
|
109
|
+
### Example build files
|
110
|
+
|
111
|
+
* https://github.paypal.com/SDK-R/PayPal-Android-SDK/blob/develop/fabfile.py
|
112
|
+
* https://github.paypal.com/SDK-R/PayPal-iOS-SDK/blob/develop/fabfile.py
|
113
|
+
* https://github.braintreeps.com/braintree/braintree-android/blob/master/Rakefile
|
114
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import "./lib/tasks/releasinator.rake"
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
require_relative 'printer'
|
3
|
+
|
4
|
+
module Releasinator
|
5
|
+
class CommandProcessor
|
6
|
+
def self.command(command, live_output=false)
|
7
|
+
puts Time.now.utc.iso8601 + ": " + "#{Dir.pwd}".bold + " exec:" + " #{command}".bold
|
8
|
+
if live_output
|
9
|
+
puts "...with live output (forked process)".bold
|
10
|
+
|
11
|
+
return_code = nil
|
12
|
+
r, io = IO.pipe
|
13
|
+
pid = fork do
|
14
|
+
return_code = system(command, :out => io, :err => io)
|
15
|
+
if !return_code
|
16
|
+
Printer.fail("Execution failure.")
|
17
|
+
abort()
|
18
|
+
end
|
19
|
+
end
|
20
|
+
io.close
|
21
|
+
r.each_line{|l| puts l.strip.white}
|
22
|
+
|
23
|
+
Process.wait(pid)
|
24
|
+
fork_exitstatus = $?.exitstatus
|
25
|
+
if 0 != fork_exitstatus
|
26
|
+
Printer.fail("Forked process failed with exitstatus:#{fork_exitstatus}")
|
27
|
+
abort()
|
28
|
+
end
|
29
|
+
else
|
30
|
+
output = `#{command}`
|
31
|
+
exitstatus = $?.exitstatus
|
32
|
+
if 0 != exitstatus
|
33
|
+
Printer.fail("Process failed with exitstatus:#{exitstatus}")
|
34
|
+
abort()
|
35
|
+
end
|
36
|
+
|
37
|
+
output
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# waits for the input command to return non-empty output.
|
42
|
+
def self.wait_for(command_to_execute, wait_for_seconds=30)
|
43
|
+
while "" == CommandProcessor.command(command_to_execute)
|
44
|
+
puts "Returned empty output. Sleeping #{wait_for_seconds} seconds."
|
45
|
+
wait_for_seconds.times do
|
46
|
+
print "."
|
47
|
+
sleep 1
|
48
|
+
end
|
49
|
+
puts
|
50
|
+
end
|
51
|
+
|
52
|
+
Printer.success("Returned non-empty output.")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/config_hash.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'configatron'
|
2
|
+
require_relative 'default_config'
|
3
|
+
require_relative 'command_processor'
|
4
|
+
require_relative 'git_util'
|
5
|
+
|
6
|
+
RELEASINATOR_NAME = "releasinator"
|
7
|
+
CONFIG_FILE_NAME = ".#{RELEASINATOR_NAME}.rb"
|
8
|
+
|
9
|
+
module Releasinator
|
10
|
+
class ConfigHash < Hash
|
11
|
+
def initialize(verbose, trace)
|
12
|
+
update({:releasinator_name => RELEASINATOR_NAME})
|
13
|
+
update({:verbose => verbose})
|
14
|
+
update({:trace => trace})
|
15
|
+
|
16
|
+
require_file_name = "./.#{RELEASINATOR_NAME}.rb"
|
17
|
+
begin
|
18
|
+
require require_file_name
|
19
|
+
rescue LoadError
|
20
|
+
is_git_already_clean = GitUtil.is_clean_git?
|
21
|
+
puts "It looks like this is your first time using #{RELEASINATOR_NAME} on this project.".yellow
|
22
|
+
puts "A default '#{CONFIG_FILE_NAME}' file has been created for you.".yellow
|
23
|
+
out_file = File.new("#{CONFIG_FILE_NAME}", "w")
|
24
|
+
out_file.write(DEFAULT_CONFIG)
|
25
|
+
out_file.close
|
26
|
+
require require_file_name
|
27
|
+
|
28
|
+
# dpn't want to commit other files
|
29
|
+
if is_git_already_clean
|
30
|
+
puts "adding default #{CONFIG_FILE_NAME} to git".yellow
|
31
|
+
CommandProcessor.command("git add #{CONFIG_FILE_NAME}")
|
32
|
+
CommandProcessor.command("git commit -m \"#{RELEASINATOR_NAME}: add default config\"")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
configatron.lock!
|
37
|
+
loaded_config_hash = configatron.to_h
|
38
|
+
|
39
|
+
update(loaded_config_hash)
|
40
|
+
|
41
|
+
puts "loaded config:" + self.to_s if verbose
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/copy_file.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
DEFAULT_CONFIG = %(configatron.product_name = "test product"
|
2
|
+
|
3
|
+
# List of items to confirm from the person releasing. Required, but empty list is ok.
|
4
|
+
configatron.prerelease_checklist_items = [
|
5
|
+
]
|
6
|
+
|
7
|
+
# The directory where all distributed docs are. Default is '.'
|
8
|
+
# configatron.base_docs_dir = '.'
|
9
|
+
|
10
|
+
def build_method
|
11
|
+
CommandProcessor.command("ls -al")
|
12
|
+
end
|
13
|
+
|
14
|
+
# The command that builds the sdk. Required.
|
15
|
+
configatron.build_method = method(:build_method)
|
16
|
+
|
17
|
+
def publish_to_package_manager(version)
|
18
|
+
sleep 1
|
19
|
+
puts "done publishing yay!"
|
20
|
+
end
|
21
|
+
|
22
|
+
# The method that publishes the sdk to the package manager. Required.
|
23
|
+
configatron.publish_to_package_manager_method = method(:publish_to_package_manager)
|
24
|
+
|
25
|
+
|
26
|
+
def wait_for_package_manager(version)
|
27
|
+
end
|
28
|
+
|
29
|
+
# The method that waits for the package manager to be done. Required
|
30
|
+
configatron.wait_for_package_manager_method = method(:wait_for_package_manager)
|
31
|
+
|
32
|
+
# Whether to publish the root repo to GitHub. Required.
|
33
|
+
configatron.release_to_github = true
|
34
|
+
)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Releasinator
|
2
|
+
class DownstreamRepo
|
3
|
+
attr_reader :name, :url, :branch, :options
|
4
|
+
def initialize(name, url, branch, options={})
|
5
|
+
@name = name
|
6
|
+
@url = url
|
7
|
+
@branch = branch
|
8
|
+
@options = options
|
9
|
+
# options are:
|
10
|
+
# :new_branch_name (if set, ignores :release_to_github)
|
11
|
+
# :release_to_github
|
12
|
+
# :files_to_copy
|
13
|
+
# :full_file_sync
|
14
|
+
# :post_copy_methods
|
15
|
+
# :build_methods
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/git_util.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative 'command_processor'
|
2
|
+
|
3
|
+
module Releasinator
|
4
|
+
class GitUtil
|
5
|
+
def self.is_clean_git?
|
6
|
+
any_changes = CommandProcessor.command("git status --porcelain")
|
7
|
+
'' == any_changes
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.get_current_branch
|
11
|
+
CommandProcessor.command("git symbolic-ref --short HEAD").strip
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.untracked_files
|
15
|
+
CommandProcessor.command("git ls-files --others --exclude-standard")
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.diff
|
19
|
+
CommandProcessor.command("git diff")
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.cached
|
23
|
+
CommandProcessor.command("git diff --cached")
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.repo_url
|
27
|
+
CommandProcessor.command("git config --get remote.origin.url").strip
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.delete_branch(branch_name)
|
31
|
+
if has_branch? branch_name
|
32
|
+
CommandProcessor.command("git branch -D #{branch_name}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.has_branch?(branch_name)
|
37
|
+
"" != CommandProcessor.command("git branch --list #{branch_name}").strip
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.has_remote_branch?(branch_name)
|
41
|
+
"" != CommandProcessor.command("git branch --list -r #{branch_name}").strip
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.checkout(branch_name)
|
45
|
+
if get_current_branch != branch_name
|
46
|
+
CommandProcessor.command("git checkout #{branch_name}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.init_gh_pages
|
51
|
+
if !has_branch? "gh-pages"
|
52
|
+
if has_remote_branch? "origin/gh-pages"
|
53
|
+
checkout("gh-pages")
|
54
|
+
else
|
55
|
+
CommandProcessor.command("git checkout --orphan gh-pages")
|
56
|
+
CommandProcessor.command("GLOBIGNORE='.git' git rm -rf *")
|
57
|
+
#http://stackoverflow.com/questions/19363795/git-rm-doesnt-remove-all-files-in-one-go
|
58
|
+
CommandProcessor.command("GLOBIGNORE='.git' git rm -rf *")
|
59
|
+
CommandProcessor.command("touch README.md")
|
60
|
+
CommandProcessor.command("git add .")
|
61
|
+
CommandProcessor.command("git commit -am \"Initial gh-pages commit\"")
|
62
|
+
CommandProcessor.command("git push -u origin gh-pages")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/github_repo.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
require 'octokit'
|
3
|
+
require_relative 'printer'
|
4
|
+
|
5
|
+
module Releasinator
|
6
|
+
class GitHubRepo
|
7
|
+
attr_reader :url, :org, :repo, :domain, :client
|
8
|
+
|
9
|
+
def initialize(url)
|
10
|
+
@url = url
|
11
|
+
if url.start_with?("https")
|
12
|
+
# https: "https://github.com/braebot/test.git"
|
13
|
+
slash_split = url.split("/")
|
14
|
+
@domain = slash_split[2]
|
15
|
+
@repo = slash_split.last.split(".git").first
|
16
|
+
slash_split.pop
|
17
|
+
@org = slash_split.last
|
18
|
+
else
|
19
|
+
# ssh: git@github.com:braebot/test.git"
|
20
|
+
colon_split = url.split(":")
|
21
|
+
at_split = colon_split.first.split("@")
|
22
|
+
@domain = at_split.last
|
23
|
+
slash_split = colon_split.last.split("/")
|
24
|
+
@org = slash_split.first
|
25
|
+
@repo = slash_split.last.split(".git").first
|
26
|
+
end
|
27
|
+
|
28
|
+
if @domain == "github.com"
|
29
|
+
check_token("GITHUB_TOKEN")
|
30
|
+
@client = Octokit::Client.new(:access_token => ENV["GITHUB_TOKEN"])
|
31
|
+
else
|
32
|
+
env_key = "#{@domain.gsub(".", "_").upcase}_GITHUB_TOKEN"
|
33
|
+
check_token(env_key)
|
34
|
+
@client = Octokit::Client.new(:access_token => ENV[env_key], :api_endpoint => "https://#{@domain}/api/v3/")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_token(token_param)
|
39
|
+
if !ENV[token_param]
|
40
|
+
Printer.fail("#{token_param} environment variable required. Please set this to your personal access token.")
|
41
|
+
abort()
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/printer.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'command_processor'
|
2
|
+
|
3
|
+
module Releasinator
|
4
|
+
class Printer
|
5
|
+
def self.success(msg)
|
6
|
+
puts "\xE2\x9C\x94\xEF\xB8\x8E ".light_green + "SUCCESS: #{msg}".green
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.fail(msg)
|
10
|
+
puts "\xE2\x9C\x98 FAILURE: #{msg}".red
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.check_proceed(warning_msg, abort_msg)
|
14
|
+
puts "#{warning_msg} Continue? (Y/n)".yellow
|
15
|
+
if 'n' == STDIN.gets.strip
|
16
|
+
self.fail(abort_msg)
|
17
|
+
abort()
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/publisher.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
require 'colorize'
|
3
|
+
require_relative 'github_repo'
|
4
|
+
require_relative 'printer'
|
5
|
+
|
6
|
+
module Releasinator
|
7
|
+
class Publisher
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def publish_draft(repo_url, release)
|
13
|
+
github_repo = GitHubRepo.new(repo_url)
|
14
|
+
|
15
|
+
begin
|
16
|
+
# https://github.com/octokit/octokit.rb/blob/master/spec/octokit/client/releases_spec.rb#L18
|
17
|
+
github_release = github_repo.client.create_release "#{github_repo.org}/#{github_repo.repo}",
|
18
|
+
release.release,
|
19
|
+
:name => release.release,
|
20
|
+
:body => release.changelog,
|
21
|
+
:draft => true,
|
22
|
+
:prerelease => false
|
23
|
+
puts github_release.inspect if @config[:trace]
|
24
|
+
rescue => error
|
25
|
+
#This will fail if the user does not have push permissions.
|
26
|
+
Printer.fail(error.inspect)
|
27
|
+
abort()
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def publish_pull_request(repo_url, release, product_name, base, head)
|
32
|
+
begin
|
33
|
+
github_repo = GitHubRepo.new(repo_url)
|
34
|
+
github_pull_request = github_repo.client.create_pull_request "#{github_repo.org}/#{github_repo.repo}",
|
35
|
+
base,
|
36
|
+
head,
|
37
|
+
"Update #{product_name} to #{release.release}",
|
38
|
+
release.changelog
|
39
|
+
puts github_pull_request.inspect if @config[:trace]
|
40
|
+
rescue => error
|
41
|
+
#This will fail if there's already a pull request
|
42
|
+
Printer.fail(error.inspect)
|
43
|
+
abort()
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|