codeinventory-github 0.1.0 → 0.1.1
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 +4 -4
- data/README.md +41 -4
- data/lib/codeinventory/github.rb +130 -21
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19dae8a55610afeed89a5575c736660b2a21345f
|
4
|
+
data.tar.gz: 29bba4eaaf69703b92a7d013e8b54de7907f9980
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc84d36b7e0b11382a27a6543ba801823ae22de8484f0946604e4ce95f4deafffdccc8f53b50eac3672e8d5a1e8ebcb5a13200b76dc0351a7f1d9aba3cc20ce9
|
7
|
+
data.tar.gz: 6c7dabbc11ec19c81c6394f2ea2d7d37163180f4164c8b9871364e5b11aff04344b58cc871cc57e16cb4e1006d6a0ee3c11ee1904faba93f9f8d5364c19a14ed
|
data/README.md
CHANGED
@@ -2,7 +2,11 @@
|
|
2
2
|
|
3
3
|
*_This is an experimental gem that is currently in an alpha stage. The features and interface are unstable and may change at any time._*
|
4
4
|
|
5
|
-
The `codeinventory-github` gem is a [CodeInventory](https://github.com/GSA/codeinventory) plugin. This plugin allows CodeInventory to gather metadata from
|
5
|
+
The `codeinventory-github` gem is a [CodeInventory](https://github.com/GSA/codeinventory) plugin. This plugin allows CodeInventory to gather metadata from GitHub repositories. It builds a list of projects based on a combination of:
|
6
|
+
|
7
|
+
* `.codeinventory.yml` and `.codeinventory.json` files in GitHub repositories
|
8
|
+
* GitHub metadata
|
9
|
+
* Manually specified overrides
|
6
10
|
|
7
11
|
## Installation
|
8
12
|
|
@@ -26,15 +30,21 @@ Basically:
|
|
26
30
|
|
27
31
|
```ruby
|
28
32
|
require "codeinventory"
|
29
|
-
require "codeinventory
|
33
|
+
require "codeinventory/github"
|
30
34
|
|
31
35
|
github_source = CodeInventory::GitHub.new(access_token: "GITHUB_ACCESS_TOKEN", org: "github_org_name")
|
32
36
|
|
33
37
|
inventory = CodeInventory::Inventory.new(github_source)
|
34
|
-
inventory.projects # Returns an array of
|
38
|
+
inventory.projects # Returns an array of projects in the GitHub org
|
35
39
|
```
|
36
40
|
|
37
|
-
When using `CodeInventory::GitHub`, provide a [GitHub access token](https://developer.github.com/v3/oauth/) and the GitHub organization name (e.g., "[GSA](https://github.com/GSA/)").
|
41
|
+
When using `CodeInventory::GitHub`, provide a [GitHub access token](https://developer.github.com/v3/oauth/) and the GitHub organization name (e.g., "[GSA](https://github.com/GSA/)").
|
42
|
+
|
43
|
+
The `codeinventory-github` plugin will then automatically harvest your project metadata from GitHub metadata.
|
44
|
+
|
45
|
+
### Using inventory files
|
46
|
+
|
47
|
+
If you want more fine-grained control over project metadata beyond what is in the GitHub metadata, you can optionally include a `.codeinventory.yml` or `.codeinventory.json` file in the root directories of your GitHub project repositories. For each repository that has such a file, `codeinventory-github` will automatically use the metadata from it.
|
38
48
|
|
39
49
|
#### YAML Format (.codeinventory.yml)
|
40
50
|
|
@@ -68,6 +78,33 @@ contact:
|
|
68
78
|
}
|
69
79
|
```
|
70
80
|
|
81
|
+
### Using overrides
|
82
|
+
|
83
|
+
You can override any of the inventory fields by passing an override hash.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
overrides = {
|
87
|
+
tags: ["my-tag-1", "my-tag-2"],
|
88
|
+
contact: {
|
89
|
+
email: "me@example.com"
|
90
|
+
}
|
91
|
+
}
|
92
|
+
github_source = CodeInventory::GitHub.new(access_token: "GITHUB_ACCESS_TOKEN", org: "github_org_name", overrides: overrides)
|
93
|
+
```
|
94
|
+
|
95
|
+
In this example, `codeinventory-github` will set the tags on all your projects to `my-tag-1` and `my-tag-2` also use the contact email you specified on all projects.
|
96
|
+
|
97
|
+
### Excluding repositories
|
98
|
+
|
99
|
+
You can exclude any repository from scanning.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
exclusions = ["not-a-real-product", "DontScanMe"]
|
103
|
+
github_source = CodeInventory::GitHub.new(access_token: "GITHUB_ACCESS_TOKEN", org: "github_org_name", exclude: exclusions)
|
104
|
+
```
|
105
|
+
|
106
|
+
In this example, `codeinventory-github` will ignore the repositories named `not-a-real-product` or `DontScanMe`.
|
107
|
+
|
71
108
|
## Development
|
72
109
|
|
73
110
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/codeinventory/github.rb
CHANGED
@@ -4,41 +4,150 @@ require "base64"
|
|
4
4
|
|
5
5
|
module CodeInventory
|
6
6
|
class GitHub
|
7
|
-
VERSION = "0.1.
|
8
|
-
attr_accessor :org
|
7
|
+
VERSION = "0.1.1"
|
8
|
+
attr_accessor :org, :overrides, :exclude
|
9
9
|
|
10
|
-
def initialize(access_token:, org:)
|
10
|
+
def initialize(access_token:, org:, overrides: {}, exclude: [])
|
11
11
|
Octokit.auto_paginate = true
|
12
12
|
@access_token = access_token
|
13
13
|
@org = org
|
14
|
+
@overrides = overrides
|
15
|
+
@exclude = exclude
|
14
16
|
end
|
15
17
|
|
16
18
|
def projects
|
17
19
|
repos = client.organization_repositories(@org)
|
20
|
+
repos.delete_if { |repo| exclude.include? repo[:name] }
|
18
21
|
projects = []
|
19
22
|
repos.each do |repo|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
33
|
-
if type == :yaml
|
34
|
-
projects << YAML.load(raw_content).to_hash
|
35
|
-
elsif type == :json
|
36
|
-
projects << JSON.parse(raw_content)
|
37
|
-
end
|
23
|
+
inventory_file_metadata = inventory_file(repo)
|
24
|
+
repo_metadata = {}
|
25
|
+
repo_metadata["name"] = name(repo, inventory_file_metadata)
|
26
|
+
repo_metadata["description"] = description(repo, inventory_file_metadata)
|
27
|
+
repo_metadata["license"] = license(repo, inventory_file_metadata)
|
28
|
+
repo_metadata["openSourceProject"] = open_source_project(repo, inventory_file_metadata)
|
29
|
+
repo_metadata["governmentWideReuseProject"] = government_wide_reuse_project(repo, inventory_file_metadata)
|
30
|
+
repo_metadata["tags"] = tags(repo, inventory_file_metadata)
|
31
|
+
repo_metadata["contact"] = { "email" => contact_email(repo, inventory_file_metadata) }
|
32
|
+
repo_metadata["repository"] = repository(repo, inventory_file_metadata)
|
33
|
+
projects << repo_metadata
|
38
34
|
end
|
39
35
|
projects
|
40
36
|
end
|
41
37
|
|
38
|
+
# Checks if the repo has an inventory file. If so, loads its metadata.
|
39
|
+
def inventory_file(repo)
|
40
|
+
filenames = [ ".codeinventory.yml", "codeinventory.yml", ".codeinventory.json", "codeinventory.json"]
|
41
|
+
repo_contents = client.contents(repo[:full_name], path: "/")
|
42
|
+
inventory_file = repo_contents.select { |file| filenames.include? file[:name] }.first
|
43
|
+
unless inventory_file.nil?
|
44
|
+
file_content = client.contents(repo[:full_name], path: inventory_file[:path])
|
45
|
+
raw_content = Base64.decode64(file_content[:content])
|
46
|
+
if inventory_file[:name].end_with? ".yml"
|
47
|
+
metadata = YAML.load(raw_content).to_hash
|
48
|
+
elsif inventory_file[:name].end_with? ".json"
|
49
|
+
metadata = JSON.parse(raw_content)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
metadata || {}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Provides a value for the name field.
|
56
|
+
# Order of precedence:
|
57
|
+
# 1. CodeInventory metadata file
|
58
|
+
# 2. GitHub repository name
|
59
|
+
def name(repo, inventory_file_metadata)
|
60
|
+
return inventory_file_metadata["name"] if inventory_file_metadata["name"]
|
61
|
+
repo[:name]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Provides a value for the description field.
|
65
|
+
# Order of precedence:
|
66
|
+
# 1. List of overrides
|
67
|
+
# 2. CodeInventory metadata file
|
68
|
+
# 3. GitHub repository description
|
69
|
+
# 4. GitHub repository name
|
70
|
+
def description(repo, inventory_file_metadata)
|
71
|
+
return @overrides[:description] if @overrides[:description]
|
72
|
+
return inventory_file_metadata["description"] if inventory_file_metadata["description"]
|
73
|
+
return repo[:description] if repo[:description]
|
74
|
+
repo[:name]
|
75
|
+
end
|
76
|
+
|
77
|
+
# Provides a value for the license field.
|
78
|
+
# Order of precedence:
|
79
|
+
# 1. List of overrides
|
80
|
+
# 2. CodeInventory metadata file
|
81
|
+
# 3. LICENSE.md or LICENSE file in the repository
|
82
|
+
# 4. nil
|
83
|
+
def license(repo, inventory_file_metadata)
|
84
|
+
return @overrides[:license] if @overrides[:license]
|
85
|
+
return inventory_file_metadata["license"] if inventory_file_metadata["license"]
|
86
|
+
# Need to set header to quiet warning about using a GitHub preview feature
|
87
|
+
headers = { accept: "application/vnd.github.drax-preview+json" }
|
88
|
+
begin
|
89
|
+
license_meta = client.repository_license_contents(repo[:full_name], headers)
|
90
|
+
license = license_meta[:html_url]
|
91
|
+
rescue Octokit::NotFound ; end
|
92
|
+
license
|
93
|
+
end
|
94
|
+
|
95
|
+
# Provides a value for the openSourceProject field.
|
96
|
+
# Order of precedence:
|
97
|
+
# 1. List of overrides
|
98
|
+
# 2. CodeInventory metadata file
|
99
|
+
# 3. GitHub repository public/private status (public=1; private=0)
|
100
|
+
def open_source_project(repo, inventory_file_metadata)
|
101
|
+
return @overrides[:openSourceProject] if @overrides[:openSourceProject]
|
102
|
+
return inventory_file_metadata["openSourceProject"] if inventory_file_metadata["openSourceProject"]
|
103
|
+
repo[:private] ? 0 : 1
|
104
|
+
end
|
105
|
+
|
106
|
+
# Provides a value for the governmentWideReuseProject field.
|
107
|
+
# Order of precedence:
|
108
|
+
# 1. List of overrides
|
109
|
+
# 2. CodeInventory metadata file
|
110
|
+
# 3. 1 (assume government-wide reuse)
|
111
|
+
def government_wide_reuse_project(repo, inventory_file_metadata)
|
112
|
+
return @overrides[:governmentWideReuseProject] if @overrides[:governmentWideReuseProject]
|
113
|
+
return inventory_file_metadata["governmentWideReuseProject"] if inventory_file_metadata["governmentWideReuseProject"]
|
114
|
+
1
|
115
|
+
end
|
116
|
+
|
117
|
+
# Provides a value for the tags field.
|
118
|
+
# Order of precedence:
|
119
|
+
# 1. List of overrides
|
120
|
+
# 2. CodeInventory metadata file
|
121
|
+
# 3. A single tag consisting of the org name.
|
122
|
+
def tags(repo, inventory_file_metadata)
|
123
|
+
return @overrides[:tags] if @overrides[:tags]
|
124
|
+
return inventory_file_metadata["tags"] if inventory_file_metadata["tags"]
|
125
|
+
[repo[:owner][:login]]
|
126
|
+
end
|
127
|
+
|
128
|
+
# Provides a value for the contact.email field.
|
129
|
+
# Order of precedence:
|
130
|
+
# 1. List of overrides
|
131
|
+
# 2. CodeInventory metadata file
|
132
|
+
# 3. GitHub organization email
|
133
|
+
def contact_email(repo, inventory_file_metadata)
|
134
|
+
return @overrides[:contact][:email] if @overrides.dig(:contact, :email)
|
135
|
+
return inventory_file_metadata["contact"]["email"] if inventory_file_metadata.dig("contact", "email")
|
136
|
+
org = client.organization(@org)
|
137
|
+
org[:email]
|
138
|
+
end
|
139
|
+
|
140
|
+
# Provies a value for the repository field.
|
141
|
+
# Order of precedence:
|
142
|
+
# 1. List of overrides
|
143
|
+
# 2. CodeInventory metadata file
|
144
|
+
# 3. GitHub repository URL
|
145
|
+
def repository(repo, inventory_file_metadata)
|
146
|
+
return @overrides[:repository] if @overrides[:repository]
|
147
|
+
return inventory_file_metadata["repository"] if inventory_file_metadata["repository"]
|
148
|
+
repo[:html_url]
|
149
|
+
end
|
150
|
+
|
42
151
|
def client
|
43
152
|
@client ||= Octokit::Client.new(access_token: @access_token)
|
44
153
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codeinventory-github
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Fredrickson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|