travis_migrate_to_apps 0.0.1 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +74 -0
- data/bin/travis_migrate_to_apps +1 -1
- data/lib/colors.rb +15 -0
- data/lib/travis_migrate_to_apps/cli.rb +158 -0
- data/lib/travis_migrate_to_apps/version.rb +1 -1
- data/lib/travis_migrate_to_apps.rb +1 -127
- metadata +8 -6
- data/Gemfile.lock +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 11aa9acdabfe9c4b3266ef1c1561efab04abd4ac06f89cb02931ebe29580cbb3
|
4
|
+
data.tar.gz: 21d585480351fbd6bc1e3745025e6aba13208d23a64e4f4bc32ca08f0499dfd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ddb124d2978f0845f223287e6e7bf4a688179793371971a05aa134b918889ae8dddd41ee805b050236431705fdb71c283b24851646c3f05839692f7a1d2271b
|
7
|
+
data.tar.gz: 550a753c4c3f6c654923ca8fc5b0c994707b3dd4e884cfdfb141427fd387f4aa29aaf63047a9bc160e079ff82c7291cf52a4c211924df259ea06fab99da4a524
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Migrate your GitHub organizations to use the Travis CI GitHub App integration
|
2
|
+
|
3
|
+
This gem will help you migrate the repositories you have on [https://travis-ci.com](travis-ci.com) from legacy [GitHub Services](https://developer.github.com/v3/guides/replacing-github-services/) integration to the new [GitHub Apps](https://developer.github.com/apps/) integration.
|
4
|
+
|
5
|
+
The main difference is that you will now give Travis CI access to your repositories on a repository basis instead of giving it access to all of them.
|
6
|
+
|
7
|
+
Hence, we have developped this gem to help you migrate your repositories that are currently active on Travis CI in one sweep rather than having to add them manually one by one in the GitHub UI.
|
8
|
+
|
9
|
+
Here are the steps:
|
10
|
+
|
11
|
+
## 1. Install the gem
|
12
|
+
```
|
13
|
+
gem install travis_migrate_to_apps
|
14
|
+
```
|
15
|
+
|
16
|
+
## 2. Generate a GitHub personal access token with repo scope
|
17
|
+
|
18
|
+
You can generate a new GitHub token [here](https://github.com/settings/tokens/new).
|
19
|
+
|
20
|
+
Choose the name of your liking and ensure to select the whole `repo` scope as shown below:
|
21
|
+
|
22
|
+
![GitHub new token page](https://github.com/travis-ci/travis_migrate_to_apps/blob/assets/github-token-new.png)
|
23
|
+
|
24
|
+
Then click the "Generate token" button at the bottom to generate the token.
|
25
|
+
|
26
|
+
You'll then be back on the GitHub token page:
|
27
|
+
|
28
|
+
![GitHub token page](https://github.com/travis-ci/travis_migrate_to_apps/blob/assets/github-token-added.png)
|
29
|
+
|
30
|
+
Take care of copying the newly generated token and save it for later usage.
|
31
|
+
|
32
|
+
**Note: if you are migrating an organization, the token must be generated by [an owner of the GitHub organization](https://help.github.com/articles/permission-levels-for-an-organization/).**
|
33
|
+
|
34
|
+
## 3. Activate the Travis CI GitHub Apps integration with 1 repo
|
35
|
+
|
36
|
+
Go to your profile page on Travis CI: https://travis-ci.com/profile
|
37
|
+
|
38
|
+
Click the "Activate GitHub Apps Integration" button highlighted below:
|
39
|
+
|
40
|
+
![Activate GitHub Apps Integration button](https://github.com/travis-ci/travis_migrate_to_apps/blob/assets/github-apps-button-on-profile-page.png)
|
41
|
+
|
42
|
+
You'll directed to the GitHub Apps page for the Travis CI app:
|
43
|
+
|
44
|
+
![GitHub Apps page](https://github.com/travis-ci/travis_migrate_to_apps/blob/assets/travis-ci-github-app.png)
|
45
|
+
|
46
|
+
Choose at least one repository and click the "Approve & Install" button.
|
47
|
+
|
48
|
+
You'll then be redirected to your profile page on Travis CI and the newly added repository should appear under "GitHub Apps Integration":
|
49
|
+
|
50
|
+
![Travis CI profile page](https://github.com/travis-ci/travis_migrate_to_apps/blob/assets/travis-ci-profile-with-github-apps-integration.png)
|
51
|
+
|
52
|
+
## 4. Get your Travis CI API token
|
53
|
+
|
54
|
+
Here are the two ways you can get this token:
|
55
|
+
|
56
|
+
1. On your profile page: https://travis-ci.com/profile
|
57
|
+
|
58
|
+
![Travis CI token on profile page](https://github.com/travis-ci/travis_migrate_to_apps/blob/assets/travis-ci-token-profile-page.png)
|
59
|
+
|
60
|
+
2. Via the [Travis CI client](https://github.com/travis-ci/travis.rb) by running: `travis token --pro`
|
61
|
+
|
62
|
+
## 5. Run the gem
|
63
|
+
|
64
|
+
```
|
65
|
+
travis_migrate_to_apps [owner_name] [travis_access_token] [github_access_token]
|
66
|
+
```
|
67
|
+
|
68
|
+
where
|
69
|
+
|
70
|
+
- `[owner_name]` is the GitHub account (user or organization) where the repositories you want to migrate are located
|
71
|
+
- `[travis_access_token]` is the Travis CI token obtained in step #4 above
|
72
|
+
- `[github_access_token]` is the GitHub token obtained in step #2 above
|
73
|
+
|
74
|
+
Happy migration!
|
data/bin/travis_migrate_to_apps
CHANGED
data/lib/colors.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Colors
|
2
|
+
COLORS = {
|
3
|
+
red: "\e[31m",
|
4
|
+
green: "\e[32m",
|
5
|
+
yellow: "\e[33m",
|
6
|
+
blue: "\e[34m",
|
7
|
+
gray: "\e[37m",
|
8
|
+
reset: "\e[0m"
|
9
|
+
}
|
10
|
+
|
11
|
+
def colored(color, str)
|
12
|
+
return str if color == :none
|
13
|
+
[COLORS[color], str, COLORS[:reset]].join
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'json'
|
3
|
+
require 'colors'
|
4
|
+
|
5
|
+
module TravisMigrateToApps
|
6
|
+
class Cli < Struct.new(:owner_name, :travis_access_token, :github_access_token, :api_endpoint, :github_api_endpoint)
|
7
|
+
include Colors
|
8
|
+
|
9
|
+
USAGE = 'Usage: travis_migrate_to_apps [owner_name] [travis_access_token] [github_access_token] [travis api endpoint | https://api.travis-ci.com] [github api endpoint | https://api.github.com]'
|
10
|
+
|
11
|
+
MSGS = {
|
12
|
+
start: 'Starting to migrate the account %s to use the Travis CI GitHub App integration.',
|
13
|
+
fetch_installation: "Looking up %s's GitHub App installation.",
|
14
|
+
fetch_repos: "Looking up %s's active repositories.",
|
15
|
+
migrate_repos: 'Starting to migrate %i repositories.',
|
16
|
+
migrating_repo: 'Migrating repository %s ... ',
|
17
|
+
migrated_repo: 'done.',
|
18
|
+
done: 'Done.',
|
19
|
+
missing_installation: 'Sorry, we could not find an active installation for %s.',
|
20
|
+
missing_repos: 'Sorry, we could not find any repositories to migrate.',
|
21
|
+
request_failed: "Sorry, a %s request to %s failed, please check your auth token. (%i: %s)",
|
22
|
+
}
|
23
|
+
|
24
|
+
URIS = {
|
25
|
+
travis: {
|
26
|
+
installation: '%s/owner/%s?include=owner.installation',
|
27
|
+
repositories: '%s/owner/%s/repos?repository.active=true&repository.managed_by_installation=false&limit=%i&offset=%i'
|
28
|
+
},
|
29
|
+
github: {
|
30
|
+
installation_repos: '%s/user/installations/%i/repositories/%i'
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
HEADERS = {
|
35
|
+
travis: {
|
36
|
+
'Travis-API-Version' => '3',
|
37
|
+
'User-Agent' => 'Travis GitHub App Migration Tool',
|
38
|
+
'Authorization' => 'token %{token}'
|
39
|
+
},
|
40
|
+
github: {
|
41
|
+
'Accept' => 'application/vnd.github.machine-man-preview+json',
|
42
|
+
'Authorization' => 'token %{token}'
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
PER_PAGE = 20
|
47
|
+
|
48
|
+
attr_reader :installation
|
49
|
+
attr_reader :api_endpoint
|
50
|
+
attr_reader :github_api_endpoint
|
51
|
+
|
52
|
+
def initialize(*)
|
53
|
+
super
|
54
|
+
to_h.keys.each do |key|
|
55
|
+
if key == :api_endpoint
|
56
|
+
@api_endpoint = to_h[key] ? to_h[key] : 'https://api.travis-ci.com'
|
57
|
+
elsif key == :github_api_endpoint
|
58
|
+
@github_api_endpoint = to_h[key] ? to_h[key] : 'https://api.github.com'
|
59
|
+
else
|
60
|
+
missing_arg(key) unless send(key)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def run
|
66
|
+
msg :start, owner_name, color: :yellow
|
67
|
+
validate
|
68
|
+
migrate_repos
|
69
|
+
msg :done, color: :green
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def installation
|
75
|
+
@installation ||= fetch_installation
|
76
|
+
end
|
77
|
+
|
78
|
+
def repos
|
79
|
+
@repos ||= begin
|
80
|
+
msg :fetch_repos, owner_name
|
81
|
+
fetch_repos
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate
|
86
|
+
error :missing_installation, owner_name unless installation
|
87
|
+
error :missing_repos unless repos.any?
|
88
|
+
end
|
89
|
+
|
90
|
+
def migrate_repos
|
91
|
+
msg :migrate_repos, repos.count
|
92
|
+
repos.each { |repo| migrate_repo(repo) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def migrate_repo(repo)
|
96
|
+
msg :migrating_repo, repo['name'], nl: false
|
97
|
+
uri = uri(:github, :installation_repos, github_api_endpoint, installation['github_id'], repo['github_id'])
|
98
|
+
request(:put, uri, headers(:github))
|
99
|
+
msg :migrated_repo, repo['name']
|
100
|
+
end
|
101
|
+
|
102
|
+
def fetch_installation
|
103
|
+
msg :fetch_installation, owner_name
|
104
|
+
uri = uri(:travis, :installation, api_endpoint, owner_name)
|
105
|
+
data = request(:get, uri, headers(:travis))
|
106
|
+
data['installation']
|
107
|
+
end
|
108
|
+
|
109
|
+
def fetch_repos(repos = [], page = 1)
|
110
|
+
offset = (page - 1) * PER_PAGE
|
111
|
+
uri = uri(:travis, :repositories, api_endpoint, owner_name, PER_PAGE, offset)
|
112
|
+
data = request(:get, uri, headers(:travis))
|
113
|
+
repos += data['repositories'].map { |repo| only(repo, 'name', 'github_id') }
|
114
|
+
repos = fetch_repos(repos, page + 1) unless data['@pagination']['is_last']
|
115
|
+
repos
|
116
|
+
end
|
117
|
+
|
118
|
+
def uri(target, resource, *args)
|
119
|
+
URI(URIS[target][resource] % args)
|
120
|
+
end
|
121
|
+
|
122
|
+
def headers(target)
|
123
|
+
args = { token: send(:"#{target}_access_token") }
|
124
|
+
HEADERS[target].map { |key, value| [key, value % args] }.to_h
|
125
|
+
end
|
126
|
+
|
127
|
+
def request(method, uri, headers)
|
128
|
+
req = Net::HTTP.const_get(method.to_s.capitalize).new(uri)
|
129
|
+
headers.each { |key, value| req[key] = value }
|
130
|
+
http = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true)
|
131
|
+
res = http.request(req)
|
132
|
+
error :request_failed, method, uri, res.code, res.body unless res.is_a?(Net::HTTPSuccess)
|
133
|
+
JSON.parse(res.body) if method == :get
|
134
|
+
end
|
135
|
+
|
136
|
+
def error(key, *args)
|
137
|
+
abort colored(:red, MSGS[key] % args)
|
138
|
+
end
|
139
|
+
|
140
|
+
def msg(key, *args)
|
141
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
142
|
+
msg = MSGS[key] % args
|
143
|
+
msg = colored(opts[:color], msg) if opts[:color]
|
144
|
+
method = opts[:nl].is_a?(FalseClass) ? :print : :puts
|
145
|
+
send(method, msg)
|
146
|
+
end
|
147
|
+
|
148
|
+
def missing_arg(key)
|
149
|
+
puts colored(:red, "No #{key} given")
|
150
|
+
puts USAGE
|
151
|
+
abort
|
152
|
+
end
|
153
|
+
|
154
|
+
def only(hash, *keys)
|
155
|
+
hash.select { |key, _| keys.include?(key) }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -1,127 +1 @@
|
|
1
|
-
require '
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
class TravisMigrateToApps < Struct.new(:owner_name, :travis_access_token, :github_access_token)
|
5
|
-
USAGE = 'Usage: travis_migrate_to_apps [owner_name] [travis_access_token] [github_access_token]'
|
6
|
-
|
7
|
-
MSGS = {
|
8
|
-
start: 'Starting to migrate %s to use the Travis CI GitHub App integration',
|
9
|
-
migrate_repos: 'Starting to migrate %i repositories',
|
10
|
-
migrated_repo: 'Migrated repository %s',
|
11
|
-
done: 'Done.',
|
12
|
-
missing_installation: 'Sorry but we could not find an active installation for %s',
|
13
|
-
missing_repos: 'Sorry but we could not find any repositories to migrate',
|
14
|
-
request_failed: "Sorry but a request %s failed, please check your auth token. (%i: %s)",
|
15
|
-
}
|
16
|
-
|
17
|
-
URIS = {
|
18
|
-
travis: {
|
19
|
-
installation: 'https://api.travis-ci.com/owner/%s?include=owner.installation',
|
20
|
-
repositories: 'https://api.travis-ci.com/owner/%s/repos?repository.active=true&repository.managed_by_installation=false&limit=%i&offset=%i'
|
21
|
-
},
|
22
|
-
github: {
|
23
|
-
installation_repos: 'https://api.github.com/user/installations/%i/repositories/%i'
|
24
|
-
}
|
25
|
-
}
|
26
|
-
|
27
|
-
HEADERS = {
|
28
|
-
travis: {
|
29
|
-
'Travis-API-Version' => '3',
|
30
|
-
'User-Agent' => 'Travis GitHub App Migration Tool',
|
31
|
-
'Authorization' => 'token %{token}'
|
32
|
-
},
|
33
|
-
github: {
|
34
|
-
'Accept' => 'application/vnd.github.machine-man-preview+json',
|
35
|
-
'Authorization' => 'token %{token}'
|
36
|
-
}
|
37
|
-
}
|
38
|
-
|
39
|
-
PER_PAGE = 20
|
40
|
-
|
41
|
-
attr_reader :installation
|
42
|
-
|
43
|
-
def initialize(*)
|
44
|
-
super
|
45
|
-
to_h.keys.each do |key|
|
46
|
-
abort "#{USAGE}\nNo #{key} given" unless send(key)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def run
|
51
|
-
msg :start, owner_name
|
52
|
-
validate
|
53
|
-
migrate_repos
|
54
|
-
msg :done
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def installation
|
60
|
-
@installation ||= fetch_installation
|
61
|
-
end
|
62
|
-
|
63
|
-
def repos
|
64
|
-
@repos ||= fetch_repos
|
65
|
-
end
|
66
|
-
|
67
|
-
def validate
|
68
|
-
error :missing_installation, owner_name unless installation
|
69
|
-
error :missing_repos unless repos.any?
|
70
|
-
end
|
71
|
-
|
72
|
-
def migrate_repos
|
73
|
-
msg :migrate_repos, repos.count
|
74
|
-
repos.each { |repo| migrate_repo(repo) }
|
75
|
-
end
|
76
|
-
|
77
|
-
def migrate_repo(repo)
|
78
|
-
uri = uri(:github, :installation_repos, repo['github_id'], installation['github_id'])
|
79
|
-
request(:put, uri, headers(:github))
|
80
|
-
msg :migrated_repo, repo['name']
|
81
|
-
end
|
82
|
-
|
83
|
-
def fetch_installation
|
84
|
-
uri = uri(:travis, :installation, owner_name)
|
85
|
-
data = request(:get, uri, headers(:travis))
|
86
|
-
data['installation']
|
87
|
-
end
|
88
|
-
|
89
|
-
def fetch_repos(repos = [], page = 1)
|
90
|
-
offset = (page - 1) * PER_PAGE
|
91
|
-
uri = uri(:travis, :repositories, owner_name, PER_PAGE, offset)
|
92
|
-
data = request(:get, uri, headers(:travis))
|
93
|
-
repos += data['repositories'].map { |repo| only(repo, 'name', 'github_id') }
|
94
|
-
fetch_repos(repos, page + 1) unless data['@pagination']['is_last']
|
95
|
-
repos
|
96
|
-
end
|
97
|
-
|
98
|
-
def uri(target, resource, *args)
|
99
|
-
URI(URIS[target][resource] % args)
|
100
|
-
end
|
101
|
-
|
102
|
-
def headers(target)
|
103
|
-
args = { token: send(:"#{target}_access_token") }
|
104
|
-
HEADERS[target].map { |key, value| [key, value % args] }.to_h
|
105
|
-
end
|
106
|
-
|
107
|
-
def request(method, uri, headers)
|
108
|
-
req = Net::HTTP.const_get(method.to_s.capitalize).new(uri)
|
109
|
-
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
110
|
-
http.request(req)
|
111
|
-
end
|
112
|
-
error :request_failed, uri, res.code, res.body unless res.is_a?(Net::HTTPSuccess)
|
113
|
-
JSON.parse(res.body) if method == :get
|
114
|
-
end
|
115
|
-
|
116
|
-
def error(key, *args)
|
117
|
-
abort MSGS[key] % args
|
118
|
-
end
|
119
|
-
|
120
|
-
def msg(key, *args)
|
121
|
-
puts MSGS[key] % args
|
122
|
-
end
|
123
|
-
|
124
|
-
def only(hash, *keys)
|
125
|
-
hash.select { |key, _| keys.include?(key) }
|
126
|
-
end
|
127
|
-
end
|
1
|
+
require 'travis_migrate_to_apps/cli'
|
metadata
CHANGED
@@ -1,27 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: travis_migrate_to_apps
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Travis CI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Migrate your GitHub organizations to use the Travis CI GitHub App integration.
|
14
14
|
email:
|
15
15
|
- support@travis-ci.com
|
16
|
-
executables:
|
16
|
+
executables:
|
17
|
+
- travis_migrate_to_apps
|
17
18
|
extensions: []
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
20
21
|
- Gemfile
|
21
|
-
- Gemfile.lock
|
22
22
|
- LICENSE.md
|
23
|
+
- README.md
|
23
24
|
- bin/travis_migrate_to_apps
|
25
|
+
- lib/colors.rb
|
24
26
|
- lib/travis_migrate_to_apps.rb
|
27
|
+
- lib/travis_migrate_to_apps/cli.rb
|
25
28
|
- lib/travis_migrate_to_apps/version.rb
|
26
29
|
homepage: https://github.com/travis-ci/travis_migrate_to_apps
|
27
30
|
licenses:
|
@@ -42,8 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
45
|
- !ruby/object:Gem::Version
|
43
46
|
version: '0'
|
44
47
|
requirements: []
|
45
|
-
|
46
|
-
rubygems_version: 2.6.13
|
48
|
+
rubygems_version: 3.1.2
|
47
49
|
signing_key:
|
48
50
|
specification_version: 4
|
49
51
|
summary: Migrate your GitHub organizations to use the Travis CI GitHub App integration
|
data/Gemfile.lock
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
travis_migrate_to_apps (0.0.1)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
addressable (2.5.2)
|
10
|
-
public_suffix (>= 2.0.2, < 4.0)
|
11
|
-
crack (0.4.3)
|
12
|
-
safe_yaml (~> 1.0.0)
|
13
|
-
diff-lcs (1.3)
|
14
|
-
hashdiff (0.3.7)
|
15
|
-
public_suffix (3.0.2)
|
16
|
-
rspec (3.7.0)
|
17
|
-
rspec-core (~> 3.7.0)
|
18
|
-
rspec-expectations (~> 3.7.0)
|
19
|
-
rspec-mocks (~> 3.7.0)
|
20
|
-
rspec-core (3.7.1)
|
21
|
-
rspec-support (~> 3.7.0)
|
22
|
-
rspec-expectations (3.7.0)
|
23
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
-
rspec-support (~> 3.7.0)
|
25
|
-
rspec-mocks (3.7.0)
|
26
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
-
rspec-support (~> 3.7.0)
|
28
|
-
rspec-support (3.7.1)
|
29
|
-
safe_yaml (1.0.4)
|
30
|
-
webmock (3.3.0)
|
31
|
-
addressable (>= 2.3.6)
|
32
|
-
crack (>= 0.3.2)
|
33
|
-
hashdiff
|
34
|
-
|
35
|
-
PLATFORMS
|
36
|
-
ruby
|
37
|
-
|
38
|
-
DEPENDENCIES
|
39
|
-
rspec
|
40
|
-
travis_migrate_to_apps!
|
41
|
-
webmock
|
42
|
-
|
43
|
-
BUNDLED WITH
|
44
|
-
1.16.1
|