github_org_manager 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f040bda13816a4be56c79705bfc08b8ddc4103b912b0739f995fd39c8b9b4762
4
- data.tar.gz: bfbc002654df01530548f3bbbf992d3b174ef7926729e1e08b4118627be24665
3
+ metadata.gz: 448927c5116bc5a19aa7eb3ede1e38fbf835014d385f1b3060958c18b72fb72d
4
+ data.tar.gz: dbae6b024e64729cefb7c424c8c994989ce40deeeab2a111fc457a2108d45fe7
5
5
  SHA512:
6
- metadata.gz: 95727ac38a7088d1e3751af1f25b5c824376a1e84ce8235b1c21658bbab373133952ed84142ea082f6b6db78e087d2f7382f8b6ae021932215075b0efbb7f400
7
- data.tar.gz: e94d42b5257c15ad21b7d2ef59f81f3b45f7f8ae41866864100c6964f6ca7db3e2105e20c4a3d527d4f90ec56ae1a61ee6bb44fc8777f563fcf217e651bdf2a1
6
+ metadata.gz: 5bfe6d464a78f395d4be6e6697b835c759bc7e940dfd8105be7ede6097783c1ef4493abb63ed8f2e83e822416e3d669b4b2041728661988ccb779b5d0182a91e
7
+ data.tar.gz: 3810347e3e5ee96b03ea119380b5016cff5b48da980efc6dd6c720955e409b91132d932eef0f19da48bfdf4f10531af15f9db345a96f2f7e1b0b149769201fca
data/CHANGELOG.md CHANGED
@@ -1,8 +1,14 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.0.3] - 2022-02-18
4
+
5
+ - Adds ability to limit scope to teams the current user is on
6
+ - Exposes information on team membership, repos, and current user affiliations
7
+
3
8
  ## [0.0.2] - 2022-02-17
4
9
 
5
10
  - Fix old `CLIENT` reference from `0.0.1`
11
+
6
12
  ## [0.0.1] - 2022-02-17
7
13
 
8
14
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- github_org_manager (0.0.1)
4
+ github_org_manager (0.0.2)
5
5
  netrc (~> 0.11.0)
6
6
  octokit (~> 4.22.0)
7
7
 
data/README.md CHANGED
@@ -10,6 +10,12 @@ manager = GithubOrgManager::Manager.new(
10
10
  # more accurately read from for now.
11
11
  org_name: "<YOUR_ORG_HERE>",
12
12
 
13
+ # If you would like to limit this to only teams that the
14
+ # "logged in" user currently belongs to, set this to
15
+ # true and all downloads and updates will be scoped as
16
+ # such.
17
+ team_only: true,
18
+
13
19
  # Directory where your code typically is, defaults to
14
20
  # `~/dev` and ensures it exists
15
21
  dev_home: "<WHERE_YOUR_CODE_LIVES>",
@@ -45,11 +51,15 @@ gem 'github_org_manager'
45
51
 
46
52
  And then execute:
47
53
 
48
- $ bundle install
54
+ ```sh
55
+ $ bundle install
56
+ ```
49
57
 
50
58
  Or install it yourself as:
51
59
 
52
- $ gem install github_org_manager
60
+ ```sh
61
+ $ gem install github_org_manager
62
+ ```
53
63
 
54
64
  ## Development
55
65
 
@@ -59,7 +69,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
59
69
 
60
70
  ## Contributing
61
71
 
62
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/github_org_manager. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/github_org_manager/blob/main/CODE_OF_CONDUCT.md).
72
+ Bug reports and pull requests are welcome on GitHub at https://github.com/baweaver/github_org_manager. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/baweaver/github_org_manager/blob/main/CODE_OF_CONDUCT.md).
63
73
 
64
74
  ## License
65
75
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GithubOrgManager
4
- VERSION = "0.0.2"
4
+ VERSION = "0.0.3"
5
5
  end
@@ -6,6 +6,9 @@ require "octokit"
6
6
  require "netrc"
7
7
 
8
8
  module GithubOrgManager
9
+ # Manages an organization in GitHub, currently in a
10
+ # READONLY fashion for syncing purposes.
11
+ #
9
12
  class Manager
10
13
  # Where your development files are stored
11
14
  DEV_HOME = File.join(Dir.home, "dev")
@@ -16,23 +19,29 @@ module GithubOrgManager
16
19
  # ( https://github.com/octokit/octokit.rb#using-a-netrc-file )
17
20
  OCTOKIT_PARAMS = { netrc: true }
18
21
 
19
- attr_reader :dev_home, :org_name, :repos, :repo_paths
22
+ attr_reader :client, :dev_home, :org_name, :username
20
23
 
21
24
  # Creates a new Manager
22
25
  #
23
26
  # @param org_name: [String]
24
- # Organization to pull data from
27
+ # Organization to pull data from.
28
+ #
29
+ # @param team_only: [Boolean]
30
+ # Scope all data to only teams in the organization
31
+ # you belong to, meaning all syncing applies only to
32
+ # teams you're specifically on.
25
33
  #
26
34
  # @param dev_home: [String]
27
- # Where development files and repos live on your machine
35
+ # Where development files and repos live on your machine.
28
36
  #
29
37
  # @param octokit_params [Hash<Symbol, Any>]
30
- # Params passed through to Octokit::Client constructor
38
+ # Params passed through to `Octokit::Client` constructor.
31
39
  #
32
40
  # @param &octokit_configuration [Proc]
33
- # Configuration block passed to Octokit.configure
41
+ # Configuration block passed to `Octokit.configure`.
34
42
  def initialize(
35
43
  org_name:,
44
+ team_only: false,
36
45
  dev_home: DEV_HOME,
37
46
  octokit_params: OCTOKIT_PARAMS,
38
47
  &octokit_configuration
@@ -42,26 +51,118 @@ module GithubOrgManager
42
51
 
43
52
  @dev_home = path_name
44
53
  @org_name = org_name
45
- @org_path = File.join(path_name, org_name)
54
+ @org_path = File.join(@dev_home, org_name)
55
+
56
+ @client = get_client(octokit_params:, &octokit_configuration)
57
+ @username = client.user[:login]
58
+ @team_only = team_only
59
+ end
60
+
61
+ # Repositories in the organization the Manager is targeting. These
62
+ # values can be scoped to only ones owned by the username specified
63
+ # to Octokit with the `team_only` option.
64
+ #
65
+ # @return [Hash<String, String>]
66
+ # Mapping of repo name to repo URL
67
+ def repos
68
+ @repos ||= @team_only ? my_repos : team_repos
69
+ end
46
70
 
47
- @client = client(octokit_params:, &octokit_configuration)
71
+ # File paths of all repos currently in scope for your organization.
72
+ #
73
+ # @return [Hash<String, String>]
74
+ # Mapping of repo name to repo file path.
75
+ def repo_paths
76
+ @repo_paths ||= repos.to_h do |repo_name, _repo_url|
77
+ [repo_name, File.join(@org_path, repo_name)]
78
+ end
79
+ end
48
80
 
49
- @repos = @client.org_repos(@org_name).to_h do |repo_data|
81
+ # All unscoped repos belonging to an organization.
82
+ #
83
+ # @return [Hash<String, String>]
84
+ # Mapping of repo name to repo URL.
85
+ def all_repos
86
+ @all_repos ||= client.org_repos(@org_name).to_h do |repo_data|
50
87
  [repo_data[:name], repo_data[:html_url]]
51
88
  end
89
+ end
52
90
 
53
- @repo_paths = @repos.to_h do |repo_name, _repo_url|
54
- [repo_name, File.join(@org_path, repo_name)]
91
+ # Repos that the current user in Octokit is a member of a team.
92
+ # of that manages that repo.
93
+ #
94
+ # @return [Hash<String, String>]
95
+ # Mapping of repo name to repo URL.
96
+ def my_repos
97
+ @my_repos ||= all_repos.select do |name, _|
98
+ my_repo_names.include?(name)
99
+ end
100
+ end
101
+
102
+ # Gets teams under the current organization.
103
+ #
104
+ # @return [Hash<String, Numeric>]
105
+ # Mapping of team name to team id.
106
+ def org_teams
107
+ @org_teams ||= client.org_teams(@org_name).to_h do
108
+ [_1[:name], _1[:id]]
109
+ end
110
+ end
111
+
112
+ # Repos that each team manages, may have overlaps.
113
+ #
114
+ # @return [Hash<String, Array<String>>]
115
+ # Mapping of team name to a collection of repo names
116
+ # that they manage.
117
+ def team_repos
118
+ @team_repos ||= org_teams.to_h do |name, id|
119
+ [name, client.team_repos(id).map { _1[:name] }]
120
+ end
121
+ end
122
+
123
+ # Members that belong to each team.
124
+ #
125
+ # @return [Hash<String, Array<String>>]
126
+ # Mapping of team name to a collection of all of its
127
+ # members.
128
+ def team_members
129
+ @team_members ||= org_teams.to_h do |name, id|
130
+ [name, client.team_members(id).map { _1[:login] }]
55
131
  end
56
132
  end
57
133
 
134
+ # Teams that the current logged in user belongs to.
135
+ #
136
+ # @return [Set<String>]
137
+ # Names of teams.
138
+ def my_teams
139
+ @my_teams ||= team_members
140
+ .select { |_, members| members.include?(@username) }
141
+ .keys
142
+ .then { Set.new(_1) }
143
+ end
144
+
145
+ # Repos that the current logged in user has authority over.
146
+ #
147
+ # @return [Set<String>]
148
+ # Names of repos.
149
+ def my_repo_names
150
+ @my_repo_names ||= team_repos
151
+ .select { |name, _| my_teams.include?(name) }
152
+ .values
153
+ .flatten
154
+ .then { Set.new(_1) }
155
+ end
156
+
58
157
  # Make sure that every repo in the organization exists on this
59
- # machine.
158
+ # machine. Scoped to team if `team_only` is on.
159
+ #
160
+ # @return [void]
60
161
  def ensure_repo_directories_exist!
61
162
  Dir.mkdir(@org_path) unless Dir.exist?(@org_path)
62
163
 
63
164
  Dir.chdir(@org_path) do
64
- @repos.each do |name, html_url|
165
+ repos.each do |name, html_url|
65
166
  `git clone "#{html_url}"` unless Dir.exist?(@repo_paths[name])
66
167
  end
67
168
  end
@@ -69,15 +170,21 @@ module GithubOrgManager
69
170
  true
70
171
  end
71
172
 
72
- # Update all repos
173
+ # Update all repos, scoped to team if `team_only` is on.
174
+ #
175
+ # TODO: While there is a Ruby Git gem I've had some difficulty
176
+ # in getting it to work properly, hence plain old system commands
177
+ # instead for the time being.
178
+ #
179
+ # @return [void]
73
180
  def update_repos!
74
181
  # Hard to update repos which don't exist on the computer, make sure that
75
182
  # we have them all already downloaded, or do so
76
183
  ensure_repo_directories_exist!
77
184
 
78
- puts "📦 Updating #{@repo_paths.size} repos: \n"
185
+ puts "📦 Updating #{repo_paths.size} repos: \n"
79
186
 
80
- @repo_paths.each do |name, path|
187
+ repo_paths.each do |name, path|
81
188
  Dir.chdir(path) do
82
189
  main_branch = `basename $(git symbolic-ref refs/remotes/origin/HEAD)` || "main"
83
190
  current_branch = `git rev-parse --abbrev-ref HEAD`
@@ -106,7 +213,25 @@ module GithubOrgManager
106
213
  true
107
214
  end
108
215
 
109
- def client(octokit_params:, &configuration)
216
+ # If for whatever reason you need to unset all the cached
217
+ # instance variables for refreshing data.
218
+ #
219
+ # @return [void]
220
+ def clear_cache!
221
+ @repos = nil
222
+ @repo_paths = nil
223
+ @all_repos = nil
224
+ @my_repos = nil
225
+ @org_teams = nil
226
+ @team_repos = nil
227
+ @team_members = nil
228
+ @my_teams = nil
229
+ @my_repo_names = nil
230
+
231
+ true
232
+ end
233
+
234
+ private def get_client(octokit_params: OCTOKIT_PARAMS, &configuration)
110
235
  return @client if defined?(@client)
111
236
 
112
237
  Octokit.configure(&configuration) if block_given?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: github_org_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Weaver
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-17 00:00:00.000000000 Z
11
+ date: 2022-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: octokit