codeinventory 0.1.0 → 0.1.1

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
  SHA1:
3
- metadata.gz: 9d36a885396b768230bc4748b7b18dfcf6da7fb8
4
- data.tar.gz: e178759f92968f5fa78c53fabf508a87debbca35
3
+ metadata.gz: 992cc66fc416b27e661d1aa3519a5bb2530bb06a
4
+ data.tar.gz: 500dbda2306c83785d09b89ce7ad63ef07eba0f1
5
5
  SHA512:
6
- metadata.gz: 66f579ac72173b3d8e2a79ffc664b9b982930a2a6f903d5daf7ed60c0cbd7e2d71d4339c58d257a4861946d8ccc255167d2da6d87f72583a7eb63ded95101d40
7
- data.tar.gz: 7878947ca4b20cc8d99ba5596eedae88b2932688289b4578fa1cdebae15a65b6becae9d369b4656d51d8edf49e43896c8a1ae8ce9d434f11279f1f4aa349e53f
6
+ metadata.gz: a1ee75116c0d295503b0b7db4411b9e3c2e3796ea7d188b19ff5c2f01771898a2989f0c924446f464afe1641aa160523a9b2d75ece4a6e1360bdb09523f7136f
7
+ data.tar.gz: f88d4b3e63b10e470fdef237521fbb186e35768369e10794268de2b514177a638198bde82bf894906913d8621dc90b7fe40285140d5b9794c83b9799a3b43809
data/README.md CHANGED
@@ -6,9 +6,8 @@ The `codeinventory` gem is a tool to harvest project metadata from an agency's r
6
6
 
7
7
  * JSON files
8
8
  * CSV files
9
- * GitHub
10
9
 
11
- More sources can be added.
10
+ More sources can be added via plugins.
12
11
 
13
12
  ## Installation
14
13
 
@@ -28,20 +27,72 @@ Or install it yourself as:
28
27
 
29
28
  ## Usage
30
29
 
30
+ Basically:
31
+
31
32
  ```ruby
32
- json_source = CodeInventory::Source::JSONFile.new(File.new("some_projects.json"))
33
- csv_source = CodeInventory::Source::CSVFile.new(File.new("more_projects.csv"))
34
- github_source = CodeInventory::Source::GitHub.new(access_token: "GITHUB_ACCESS_TOKEN", org: "github_org_name")
33
+ json_source = CodeInventory::JSONFile.new(File.new("some_projects.json"))
34
+ csv_source = CodeInventory::CSVFile.new(File.new("more_projects.csv"))
35
+
36
+ inventory = CodeInventory::Inventory.new(json_source, csv_source)
37
+ inventory.projects # Returns an array of all projects in the JSON and CSV files
38
+ ```
39
+
40
+ ### JSON Source
41
+
42
+ When using `CodeInventory::JSONFile`, the source file is expected to be a JSON file in the following format:
43
+
44
+ ```json
45
+ [
46
+ {
47
+ "name": "Product One",
48
+ "description": "An awesome product.",
49
+ "license": "http://www.usa.gov/publicdomain/label/1.0/",
50
+ "openSourceProject": 1,
51
+ "governmentWideReuseProject": 1,
52
+ "tags": [
53
+ "usa"
54
+ ],
55
+ "contact": {
56
+ "email": "example@example.com"
57
+ }
58
+ },
59
+ {
60
+ "name": "Product Two",
61
+ "description": "Another awesome product.",
62
+ "license": "http://www.usa.gov/publicdomain/label/1.0/",
63
+ "openSourceProject": 0,
64
+ "governmentWideReuseProject": 0,
65
+ "tags": [
66
+ "national-security",
67
+ "top-secret"
68
+ ],
69
+ "contact": {
70
+ "email": "example@example.com"
71
+ }
72
+ }
73
+ ]
74
+
75
+ ```
76
+
77
+ See the [Code.gov documentation](https://code.gov/#/policy-guide/docs/compliance/inventory-code) for specifics on required fields and value types.
78
+
79
+ ### CSV Source
35
80
 
36
- inventory = CodeInventory::Inventory.new(json_source, csv_source, github_source)
37
- inventory.projects # Returns an array of all projects
81
+ When using `CodeInventory::CSVFile`, the source file is expected to be a CSV file in the following format:
82
+
83
+ ```csv
84
+ name,description,license,openSourceProject,governmentWideReuseProject,tags,contact.email
85
+ Product One,An awesome product.,http://www.usa.gov/publicdomain/label/1.0/,1,1,usa,example@example.com
86
+ Product Two,Another awesome product.,http://www.usa.gov/publicdomain/label/1.0/,0,0,"national-security,top-secret",example@example.com
38
87
  ```
39
88
 
89
+ See the [Code.gov documentation](https://code.gov/#/policy-guide/docs/compliance/inventory-code) for specifics on required fields and value types.
90
+
40
91
  ## Development
41
92
 
42
93
  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.
43
94
 
44
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
95
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in [`version.rb`](/lib/codeinventory/version.rb), and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
45
96
 
46
97
  ## Contributing
47
98
 
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "pry", "~> 0.10"
29
29
 
30
30
  spec.add_runtime_dependency "octokit", "~> 4.6"
31
+ spec.add_runtime_dependency "thor", "~> 0.19"
31
32
  end
data/exe/codeinv ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "codeinventory/cli"
4
+
5
+ CodeInventory::CLI::App.start(ARGV)
@@ -0,0 +1,35 @@
1
+ require "codeinventory"
2
+ require "thor"
3
+ require "pathname"
4
+
5
+ module CodeInventory
6
+ module CLI
7
+ class App < Thor
8
+ desc "csv FILENAME", "Build an inventory from a CSV file"
9
+ def csv(filename)
10
+ file = Pathname.new(filename)
11
+ unless File.exist? file
12
+ puts "No such file: #{file}"
13
+ exit 1
14
+ end
15
+ source = CodeInventory::CSVFile.new(file)
16
+ inventory = CodeInventory::Inventory.new(source)
17
+ projects = inventory.projects
18
+ puts JSON.pretty_generate(projects)
19
+ end
20
+
21
+ desc "json FILENAME", "Build an inventory from a JSON file"
22
+ def json(filename)
23
+ file = Pathname.new(filename)
24
+ unless File.exist? file
25
+ puts "No such file: #{file}"
26
+ exit 1
27
+ end
28
+ source = CodeInventory::JSONFile.new(file)
29
+ inventory = CodeInventory::Inventory.new(source)
30
+ projects = inventory.projects
31
+ puts JSON.pretty_generate(projects)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ require "codeinventory/cli/app"
@@ -0,0 +1,51 @@
1
+ require "csv"
2
+
3
+ module CodeInventory
4
+ class CSVFile
5
+ attr_reader :csv
6
+
7
+ def initialize(csv_file)
8
+ @csv = CSV.read(csv_file, { headers: true, converters: [ :integer ] })
9
+ validate_headers
10
+ end
11
+
12
+ def projects
13
+ @csv.collect do |row|
14
+ csv_data = row.to_hash
15
+ csv_data.inject({}) do |memo, pair|
16
+ csv_header, csv_value = pair
17
+ case
18
+ when csv_header == "tags"
19
+ new_pair = { "tags" => csv_value.split(",").collect { |tag| tag.strip } }
20
+ when csv_header.include?(".")
21
+ new_pair = dotted_to_nested(csv_header, csv_value)
22
+ else
23
+ new_pair = { csv_header => csv_value }
24
+ end
25
+ memo.merge(new_pair)
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ # Convert a dotted notation header and a value to a nested hash
33
+ # e.g., "contact.email" header with value "me@example.com" becomes
34
+ # { "contact" => { "email" => "me@example.com" } }
35
+ def dotted_to_nested(path, value)
36
+ path.split(".").reverse.inject(value) do |hash, element|
37
+ { element => hash }
38
+ end
39
+ end
40
+
41
+ def validate_headers
42
+ required_headers = [ "name", "description", "license", "openSourceProject", "governmentWideReuseProject", "tags", "contact.email" ]
43
+ required_headers.each do |required|
44
+ raise FileFormatError unless @csv.headers.include? required
45
+ end
46
+ end
47
+ end
48
+
49
+ class FileFormatError < StandardError
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ require "json"
2
+
3
+ module CodeInventory
4
+ class JSONFile
5
+ attr_accessor :projects
6
+
7
+ def initialize(json_file)
8
+ @projects = JSON.load(json_file)
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module CodeInventory
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/codeinventory.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  require "codeinventory/version"
2
2
  require "codeinventory/inventory"
3
- require "codeinventory/source/json_file"
4
- require "codeinventory/source/csv_file"
5
- require "codeinventory/source/github"
6
-
7
- module CodeInventory
8
- end
3
+ require "codeinventory/cli"
4
+ require "codeinventory/json_file"
5
+ require "codeinventory/csv_file"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeinventory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
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-11-15 00:00:00.000000000 Z
11
+ date: 2017-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,11 +94,26 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '4.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: thor
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.19'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.19'
97
111
  description: Harvests project metadata from an agency's repositories to build a code
98
112
  inventory. This helps agencies comply with the Federal Source Code Policy.
99
113
  email:
100
114
  - jeffrey.fredrickson@gsa.gov
101
- executables: []
115
+ executables:
116
+ - codeinv
102
117
  extensions: []
103
118
  extra_rdoc_files: []
104
119
  files:
@@ -112,11 +127,13 @@ files:
112
127
  - bin/console
113
128
  - bin/setup
114
129
  - codeinventory.gemspec
130
+ - exe/codeinv
115
131
  - lib/codeinventory.rb
132
+ - lib/codeinventory/cli.rb
133
+ - lib/codeinventory/cli/app.rb
134
+ - lib/codeinventory/csv_file.rb
116
135
  - lib/codeinventory/inventory.rb
117
- - lib/codeinventory/source/csv_file.rb
118
- - lib/codeinventory/source/github.rb
119
- - lib/codeinventory/source/json_file.rb
136
+ - lib/codeinventory/json_file.rb
120
137
  - lib/codeinventory/version.rb
121
138
  homepage: https://github.com/GSA/codeinventory
122
139
  licenses:
@@ -1,50 +0,0 @@
1
- require "csv"
2
-
3
- module CodeInventory
4
- module Source
5
- class CSVFile
6
- attr_reader :csv
7
-
8
- def initialize(csv_file)
9
- @csv = CSV.read(csv_file, { headers: true, converters: [ :integer ] })
10
- validate_headers
11
- end
12
-
13
- def projects
14
- @csv.collect do |row|
15
- csv_data = row.to_hash
16
- csv_data.inject({}) do |memo, pair|
17
- csv_header, csv_value = pair
18
- case
19
- when csv_header == "tags"
20
- new_pair = { "tags" => csv_value.split(",").collect { |tag| tag.strip } }
21
- when csv_header.include?(".")
22
- new_pair = dotted_to_nested(csv_header, csv_value)
23
- else
24
- new_pair = { csv_header => csv_value }
25
- end
26
- memo.merge(new_pair)
27
- end
28
- end
29
- end
30
-
31
- private
32
-
33
- def dotted_to_nested(path, value)
34
- path.split(".").reverse.inject(value) do |hash, element|
35
- { element => hash }
36
- end
37
- end
38
-
39
- def validate_headers
40
- required_headers = [ "name", "description", "license", "openSourceProject", "governmentWideReuseProject", "tags", "contact.email" ]
41
- required_headers.each do |required|
42
- raise FileFormatError unless @csv.headers.include? required
43
- end
44
- end
45
- end
46
-
47
- class FileFormatError < StandardError
48
- end
49
- end
50
- end
@@ -1,47 +0,0 @@
1
- require "octokit"
2
- require "yaml"
3
- require "base64"
4
-
5
- module CodeInventory
6
- module Source
7
- class GitHub
8
- attr_accessor :org
9
-
10
- def initialize(access_token:, org:)
11
- Octokit.auto_paginate = true
12
- @access_token = access_token
13
- @org = org
14
- end
15
-
16
- def projects
17
- repos = client.organization_repositories(@org)
18
- projects = []
19
- repos.each do |repo|
20
- begin
21
- contents_metadata = client.contents(repo[:full_name], path: ".codeinventory.yml")
22
- type = :yaml
23
- raw_content = Base64.decode64(contents_metadata[:content])
24
- rescue Octokit::NotFound
25
- begin
26
- contents_metadata = client.contents(repo[:full_name], path: ".codeinventory.json")
27
- type = :json
28
- raw_content = Base64.decode64(contents_metadata[:content])
29
- rescue Octokit::NotFound
30
- # Ignore repositories that don't have a CodeInventory metadata file
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
38
- end
39
- projects
40
- end
41
-
42
- def client
43
- @client ||= Octokit::Client.new(access_token: @access_token)
44
- end
45
- end
46
- end
47
- end
@@ -1,13 +0,0 @@
1
- require "json"
2
-
3
- module CodeInventory
4
- module Source
5
- class JSONFile
6
- attr_accessor :projects
7
-
8
- def initialize(json_file)
9
- @projects = JSON.load(json_file)
10
- end
11
- end
12
- end
13
- end