about_yml 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +15 -0
- data/LICENSE.md +31 -0
- data/README.md +85 -0
- data/bin/about_yml_generator +6 -0
- data/bin/about_yml_scrape +58 -0
- data/bin/about_yml_validate +28 -0
- data/bin/github_org_descriptions +33 -0
- data/lib/about_yml/about.rb +82 -0
- data/lib/about_yml/schema.json +200 -0
- data/lib/about_yml/template_generator.rb +67 -0
- data/lib/about_yml/version.rb +5 -0
- data/lib/about_yml.rb +5 -0
- metadata +189 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c4b7c2cf619f3f89753d3eedf409b807dc400b91
|
4
|
+
data.tar.gz: 32b074f94be4e4c3458c4e8bb270a1f9ecfa0c02
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7335e922baee99f8a65ac43c677ed427103939a89eb445d3025dfa16358b90870597baa02ea9d760c16ed2605bd3c8cced2df4f782d81a2e17595753e8c78c57
|
7
|
+
data.tar.gz: bbfd96bc5d9a8c8f2edeff6271efb6278d4823bc8e12280c5fddb8203224bbdb653d2dcf5ed80d0ec24f7222a701a51eb7dce9f0e8d2c8daa201707269a33d5b
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
## Welcome!
|
2
|
+
|
3
|
+
We're so glad you're thinking about contributing to an 18F open source project! If you're unsure or afraid of anything, just ask or submit the issue or pull request anyways. The worst that can happen is that you'll be politely asked to change something. We appreciate any sort of contribution, and don't want a wall of rules to get in the way of that.
|
4
|
+
|
5
|
+
Before contributing, we encourage you to read our CONTRIBUTING policy (you are here), our LICENSE, and our README, all of which should be in this repository. If you have any questions, or want to read more about our underlying policies, you can consult the 18F Open Source Policy GitHub repository at https://github.com/18f/open-source-policy, or just shoot us an email/official government letterhead note to [18f@gsa.gov](mailto:18f@gsa.gov).
|
6
|
+
|
7
|
+
## Public domain
|
8
|
+
|
9
|
+
This project is in the public domain within the United States, and
|
10
|
+
copyright and related rights in the work worldwide are waived through
|
11
|
+
the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/).
|
12
|
+
|
13
|
+
All contributions to this project will be released under the CC0
|
14
|
+
dedication. By submitting a pull request, you are agreeing to comply
|
15
|
+
with this waiver of copyright interest.
|
data/LICENSE.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
As a work of the United States Government, this project is in the
|
2
|
+
public domain within the United States.
|
3
|
+
|
4
|
+
Additionally, we waive copyright and related rights in the work
|
5
|
+
worldwide through the CC0 1.0 Universal public domain dedication.
|
6
|
+
|
7
|
+
## CC0 1.0 Universal Summary
|
8
|
+
|
9
|
+
This is a human-readable summary of the [Legal Code (read the full text)](https://creativecommons.org/publicdomain/zero/1.0/legalcode).
|
10
|
+
|
11
|
+
### No Copyright
|
12
|
+
|
13
|
+
The person who associated a work with this deed has dedicated the work to
|
14
|
+
the public domain by waiving all of his or her rights to the work worldwide
|
15
|
+
under copyright law, including all related and neighboring rights, to the
|
16
|
+
extent allowed by law.
|
17
|
+
|
18
|
+
You can copy, modify, distribute and perform the work, even for commercial
|
19
|
+
purposes, all without asking permission.
|
20
|
+
|
21
|
+
### Other Information
|
22
|
+
|
23
|
+
In no way are the patent or trademark rights of any person affected by CC0,
|
24
|
+
nor are the rights that other persons may have in the work or in how the
|
25
|
+
work is used, such as publicity or privacy rights.
|
26
|
+
|
27
|
+
Unless expressly stated otherwise, the person who associated a work with
|
28
|
+
this deed makes no warranties about the work, and disclaims liability for
|
29
|
+
all uses of the work, to the fullest extent permitted by applicable law.
|
30
|
+
When using or citing the work, you should not imply endorsement by the
|
31
|
+
author or the affirmer.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# `.about.yml` schema and tools
|
2
|
+
|
3
|
+
The `.about.yml` mechanism allows an project to publish and maintain metadata
|
4
|
+
that can be easily maintained by project owners, that is visible and
|
5
|
+
accessible to interested parties, and that can be harvested and processed by
|
6
|
+
tools and automated systems. It is implemented using the
|
7
|
+
[YAML](https://en.wikipedia.org/wiki/YAML) format.
|
8
|
+
|
9
|
+
The [18F Team API](https://team-api.18f.gov/public/api/) is the original,
|
10
|
+
primary consumer of this information, which in turn provides data for:
|
11
|
+
|
12
|
+
- [18F Hub](https://github.com/18F/hub)
|
13
|
+
- [18F Dashboard](https://github.com/18F/dashboard)
|
14
|
+
- [18F.gsa.gov](https://github.com/18F/18f.gsa.gov)
|
15
|
+
|
16
|
+
We hope that every active 18F project, [working
|
17
|
+
group](https://pages.18f.gov/grouplet-playbook/working-groups/), and
|
18
|
+
[guild](https://pages.18f.gov/grouplet-playbook/guilds/) will publish
|
19
|
+
`.about.yml` files in their respective repositories. By feeding this
|
20
|
+
information through the Team API server and into our Hub, Dashboard, and main
|
21
|
+
web site, cultivation of `.about.yml` files will help make our activity more
|
22
|
+
easily transparent to our teammates, and to anyone outside our team who wishes
|
23
|
+
to discover what we're working on (and how we work).
|
24
|
+
|
25
|
+
## Installation
|
26
|
+
|
27
|
+
Run `gem install about_yml` on the command line. You can also add `gem
|
28
|
+
'about_yml'` to your project's `Gemfile` if you use
|
29
|
+
[Bundler](http://bundler.io/) and wish to configure the `about_yml_validate`
|
30
|
+
program as a pre-commit check.
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
Most users will interact with the gem through one of the following
|
35
|
+
command-line programs.
|
36
|
+
|
37
|
+
### `about_yml_generate`
|
38
|
+
|
39
|
+
This program will generate an empty `.about.yml` template with descriptions of
|
40
|
+
each field. To add a new `.about.yml` file to your project where `MY-PROJECT`
|
41
|
+
is the path to your local clone of your project's repository:
|
42
|
+
|
43
|
+
```shell
|
44
|
+
$ about_yml_generate > MY-PROJECT/.about.yml
|
45
|
+
```
|
46
|
+
|
47
|
+
### `about_yml_validate`
|
48
|
+
|
49
|
+
This program checks one or more `.about.yml` files against the `.about.yml`
|
50
|
+
schema. To check your project's `.about.yml` file:
|
51
|
+
|
52
|
+
```shell
|
53
|
+
$ about_yml_validate MY-PROJECT/.about.yml
|
54
|
+
```
|
55
|
+
|
56
|
+
### `about_yml_scrape`
|
57
|
+
|
58
|
+
This program checks for an `.about.yml` file in every GitHub repository
|
59
|
+
belonging to a specified organization, then downloads, validates, and
|
60
|
+
categorizes all of the discovered files into a single YAML object. You must
|
61
|
+
have a valid
|
62
|
+
[GitHub API token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/)
|
63
|
+
to run this command.
|
64
|
+
|
65
|
+
```shell
|
66
|
+
$ about_yml_scrape 18F > 18F_about_yml_data.yml
|
67
|
+
```
|
68
|
+
|
69
|
+
### `github_org_descriptions`
|
70
|
+
|
71
|
+
This program doesn't have anything to do with the `.about.yml` schema, but is
|
72
|
+
a small, handy program that also uses the
|
73
|
+
[`octokit`](https://rubygems.org/gems/octokit) gem to access the GitHub API.
|
74
|
+
It will return a YAML list of names and descriptions for all of the
|
75
|
+
repositories belonging to an organization.
|
76
|
+
|
77
|
+
## Public domain
|
78
|
+
|
79
|
+
This project is in the worldwide [public domain](LICENSE.md). As stated in [CONTRIBUTING](CONTRIBUTING.md):
|
80
|
+
|
81
|
+
> This project is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/).
|
82
|
+
>
|
83
|
+
> All contributions to this project will be released under the CC0
|
84
|
+
>dedication. By submitting a pull request, you are agreeing to comply
|
85
|
+
>with this waiver of copyright interest.
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/about_yml/about'
|
4
|
+
require 'English'
|
5
|
+
require 'safe_yaml'
|
6
|
+
|
7
|
+
USAGE = <<END_USAGE
|
8
|
+
Usage: #{$PROGRAM_NAME} github_org [github_token] [missing_outfile] \
|
9
|
+
[raw_abouts_file]
|
10
|
+
|
11
|
+
Scrapes the .about.yml files from an organization's GitHub repositories and
|
12
|
+
writes their contents to standard output as YAML, categorized by visibility
|
13
|
+
and owner type.
|
14
|
+
|
15
|
+
Also validates the .about.yml files and prints errors to standard error. The
|
16
|
+
program WILL NOT exit with an error if any files fail validation.
|
17
|
+
|
18
|
+
where:
|
19
|
+
github_org name of the GitHub organization to scan
|
20
|
+
github_token path to a file containing a valid GitHub API token
|
21
|
+
defaults to $HOME/.github_token
|
22
|
+
missing_outfile (optional) path to a file that will contain a list of repos
|
23
|
+
that do not have .about.yml files
|
24
|
+
raw_abouts_file (optional) if the file exists, the program will read
|
25
|
+
.about.yml data from it rather than scraping GitHub;
|
26
|
+
otherwise, the unprocessed .about.yml data scraped from
|
27
|
+
GitHub will be written to it
|
28
|
+
END_USAGE
|
29
|
+
|
30
|
+
def usage(exitstatus = 0)
|
31
|
+
(exitstatus == 0 ? $stdout : $stderr).puts USAGE
|
32
|
+
exit exitstatus
|
33
|
+
end
|
34
|
+
|
35
|
+
github_org, github_token, missing_outfile, raw_abouts_file = ARGV
|
36
|
+
github_token ||= File.join(ENV['HOME'], '.github_token')
|
37
|
+
usage 1 unless github_org && File.exist?(github_token)
|
38
|
+
|
39
|
+
if raw_abouts_file && File.exist?(raw_abouts_file)
|
40
|
+
fetch_results = SafeYAML.load_file raw_abouts_file, safe: true
|
41
|
+
else
|
42
|
+
access_key = File.read github_token
|
43
|
+
fetch_results = ::AboutYml::AboutFile.fetch_from_github github_org, access_key
|
44
|
+
File.write raw_abouts_file, fetch_results.to_yaml if raw_abouts_file
|
45
|
+
if missing_outfile
|
46
|
+
File.write missing_outfile, fetch_results['missing'].to_yaml
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
puts(%w(public private).each_with_object({}) do |scope, full_yml|
|
51
|
+
repo_to_data = fetch_results[scope]
|
52
|
+
results = ::AboutYml::AboutFile.validate_about_files repo_to_data
|
53
|
+
results['invalid'].each do |repo, result|
|
54
|
+
$stderr.puts "#{repo}:\n #{result[:errors].join "\n "}"
|
55
|
+
end
|
56
|
+
full_yml[scope] = ::AboutYml::AboutFile.organize_by_owner_type_and_name(
|
57
|
+
repo_to_data)
|
58
|
+
end.to_yaml)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/about_yml'
|
4
|
+
require 'English'
|
5
|
+
require 'safe_yaml'
|
6
|
+
|
7
|
+
def usage(exitstatus = 0)
|
8
|
+
(exitstatus == 0 ? $stdout : $stderr).puts <<END_USAGE
|
9
|
+
#{$PROGRAM_NAME} path_to_about_file [...]
|
10
|
+
|
11
|
+
Validates .about.yml file contents. Prints nothing on success; prints errors
|
12
|
+
to standard error.
|
13
|
+
END_USAGE
|
14
|
+
exit exitstatus
|
15
|
+
end
|
16
|
+
|
17
|
+
usage 1 if ARGV.empty?
|
18
|
+
ARGV.each { |f| abort "#{f} does not exist" unless File.exist? f }
|
19
|
+
|
20
|
+
exitstatus = 0
|
21
|
+
ARGV.each do |about_file|
|
22
|
+
about_data = SafeYAML.load_file about_file, safe: true
|
23
|
+
errors = ::AboutYml::AboutFile.validate_single_file about_data
|
24
|
+
next if errors.empty?
|
25
|
+
exitstatus = 1
|
26
|
+
$stderr.puts "#{about_file}:\n #{errors.join "\n "}"
|
27
|
+
end
|
28
|
+
exit exitstatus
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
require 'octokit'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
USAGE = <<END_USAGE
|
8
|
+
Usage: #{$PROGRAM_NAME} github_org [github_token]
|
9
|
+
|
10
|
+
Prints a list of an organization's GitHub repositories and their descriptions
|
11
|
+
to standard output as YAML.
|
12
|
+
|
13
|
+
where:
|
14
|
+
github_org name of the GitHub organization to scan
|
15
|
+
github_token path to a file containing a valid GitHub API token
|
16
|
+
defaults to $HOME/.github_token
|
17
|
+
END_USAGE
|
18
|
+
|
19
|
+
def usage(exitstatus = 0)
|
20
|
+
(exitstatus == 0 ? $stdout : $stderr).puts USAGE
|
21
|
+
exit exitstatus
|
22
|
+
end
|
23
|
+
|
24
|
+
github_org, github_token = ARGV
|
25
|
+
github_token ||= File.join(ENV['HOME'], '.github_token')
|
26
|
+
usage 1 unless github_org && File.exist?(github_token)
|
27
|
+
|
28
|
+
Octokit.auto_paginate = true
|
29
|
+
client = Octokit::Client.new access_token: File.read(github_token)
|
30
|
+
|
31
|
+
puts(client.org_repos(github_org).each_with_object([]) do |repo, descriptions|
|
32
|
+
descriptions << { 'repo' => repo.name, 'description' => repo.description }
|
33
|
+
end.to_yaml)
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'json'
|
3
|
+
require 'json-schema'
|
4
|
+
require 'octokit'
|
5
|
+
require 'safe_yaml'
|
6
|
+
|
7
|
+
SafeYAML::OPTIONS[:default_mode] = :safe
|
8
|
+
Octokit.auto_paginate = true
|
9
|
+
|
10
|
+
module AboutYml
|
11
|
+
class AboutFile
|
12
|
+
def self.schema
|
13
|
+
@schema ||= begin
|
14
|
+
raw_schema = File.read File.join(File.dirname(__FILE__), 'schema.json')
|
15
|
+
schema = ::JSON.parse raw_schema
|
16
|
+
::JSON::Validator.fully_validate_schema schema
|
17
|
+
schema
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.fetch_from_github(github_org, access_key)
|
22
|
+
client = Octokit::Client.new access_token: access_key
|
23
|
+
repos = client.org_repos github_org
|
24
|
+
result = {
|
25
|
+
'public' => {},
|
26
|
+
'private' => {},
|
27
|
+
'missing' => [],
|
28
|
+
'errors' => [],
|
29
|
+
}
|
30
|
+
repos.each { |repo| collect_repository_data repo, client, result }
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.fetch_file_contents(client, repo_full_name, ref: 'master')
|
35
|
+
about = client.contents repo_full_name, path: '.about.yml', ref: ref
|
36
|
+
SafeYAML.load Base64.decode64(about['content'])
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.collect_repository_data(repo, client, result)
|
40
|
+
collection = (repo.private == true) ? 'private' : 'public'
|
41
|
+
repo_name = repo.full_name
|
42
|
+
result[collection][repo_name] = fetch_file_contents client, repo_name
|
43
|
+
rescue Octokit::NotFound
|
44
|
+
result['missing'] << repo.full_name
|
45
|
+
rescue StandardError => err
|
46
|
+
$stderr.puts('Error while parsing .about.yml for ' \
|
47
|
+
"#{repo.full_name}:\n #{err}")
|
48
|
+
result['errors'] << repo.full_name
|
49
|
+
end
|
50
|
+
private_class_method :collect_repository_data
|
51
|
+
|
52
|
+
def self.validate_single_file(about_data)
|
53
|
+
::JSON::Validator.fully_validate schema, about_data
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.validate_about_files(repo_name_to_about_data)
|
57
|
+
r = { 'valid' => {}, 'invalid' => {} }
|
58
|
+
repo_name_to_about_data.each_with_object(r) do |data, results|
|
59
|
+
repo, contents = data
|
60
|
+
errors = validate_single_file contents
|
61
|
+
if errors.empty?
|
62
|
+
results['valid'][repo] = contents
|
63
|
+
else
|
64
|
+
results['invalid'][repo] = { errors: errors, contents: contents }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.organize_by_owner_type_and_name(abouts)
|
70
|
+
abouts.values.each_with_object({}) do |about, result|
|
71
|
+
owner_type = about['owner_type']
|
72
|
+
name = about['name']
|
73
|
+
if owner_type && name
|
74
|
+
(result[owner_type] ||= {})[name] = about
|
75
|
+
else
|
76
|
+
alt_id = about['full_name'] ? about['full_name'] : about['name']
|
77
|
+
result[alt_id + '/' + about['type']] = about
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
{
|
2
|
+
"title": ".about.yml - .about.yml files",
|
3
|
+
"description": ".about.yml project metadata",
|
4
|
+
"$schema": "http://json-schema.org/draft-04/hyper-schema",
|
5
|
+
"type": "object",
|
6
|
+
"properties": {
|
7
|
+
"name": {
|
8
|
+
"type": "string",
|
9
|
+
"description": "Short name that acts as the project identifier"
|
10
|
+
},
|
11
|
+
"full_name": {
|
12
|
+
"type": "string",
|
13
|
+
"description": "Full proper name of the project"
|
14
|
+
},
|
15
|
+
"type": {
|
16
|
+
"type": "string",
|
17
|
+
"description": "The type of content in the repo",
|
18
|
+
"enum": ["app", "docs", "policy"]
|
19
|
+
},
|
20
|
+
"owner_type": {
|
21
|
+
"type": "string",
|
22
|
+
"description": "Describes whether a project team, working group/guild, etc. owns the repo",
|
23
|
+
"enum": ["guild", "working-group", "project"]
|
24
|
+
},
|
25
|
+
"parent": {
|
26
|
+
"type": "string",
|
27
|
+
"description": "Name of the main project repo if this is a sub-repo; name of the working group/guild repo if this is a working group/guild subproject"
|
28
|
+
},
|
29
|
+
"stage": {
|
30
|
+
"type": "string",
|
31
|
+
"enum": ["discovery", "alpha", "beta", "live"],
|
32
|
+
"description": "Maturity stage of the project"
|
33
|
+
},
|
34
|
+
"status": {
|
35
|
+
"type": "string",
|
36
|
+
"enum": ["active", "deprecated"],
|
37
|
+
"description": "Whether or not the project is actively maintained"
|
38
|
+
},
|
39
|
+
"description": {
|
40
|
+
"type": "string",
|
41
|
+
"description": "Description of the project"
|
42
|
+
},
|
43
|
+
"testable": {
|
44
|
+
"type": "boolean",
|
45
|
+
"default": false,
|
46
|
+
"description": "Should be 'true' if the project has a continuous build"
|
47
|
+
},
|
48
|
+
"team": {
|
49
|
+
"type": "array",
|
50
|
+
"description": "Team members contributing to the project",
|
51
|
+
"items": {
|
52
|
+
"$ref": "#/definitions/person"
|
53
|
+
},
|
54
|
+
"uniqueItems": true
|
55
|
+
},
|
56
|
+
"partners": {
|
57
|
+
"type": "array",
|
58
|
+
"description": "Partners for whom the project is developed",
|
59
|
+
"items": {"type": "string"},
|
60
|
+
"uniqueItems": true
|
61
|
+
},
|
62
|
+
"milestones": {
|
63
|
+
"type": "array",
|
64
|
+
"description": "Brief descriptions of significant project developments",
|
65
|
+
"items": {"type": "string"},
|
66
|
+
"uniqueItems": true
|
67
|
+
},
|
68
|
+
"stack": {
|
69
|
+
"type": "array",
|
70
|
+
"description": "Technologies used to build the project",
|
71
|
+
"items": {"type": "string"},
|
72
|
+
"uniqueItems": true
|
73
|
+
},
|
74
|
+
"impact": {
|
75
|
+
"type": "string",
|
76
|
+
"description": "Brief description of the project's outcomes"
|
77
|
+
},
|
78
|
+
"services": {
|
79
|
+
"type": "array",
|
80
|
+
"description": "Services used to supply project status information",
|
81
|
+
"items": {
|
82
|
+
"$ref": "#/definitions/service"
|
83
|
+
},
|
84
|
+
"uniqueItems": true
|
85
|
+
},
|
86
|
+
"licenses": {
|
87
|
+
"type": "object",
|
88
|
+
"description": "Licenses that apply to the project and/or its components",
|
89
|
+
"patternProperties": {
|
90
|
+
".*": {"$ref": "#/definitions/license"}
|
91
|
+
}
|
92
|
+
},
|
93
|
+
"blog": {
|
94
|
+
"type": "array",
|
95
|
+
"description": "Blogs or websites associated with project development",
|
96
|
+
"items": {
|
97
|
+
"type": "string",
|
98
|
+
"format": "uri"
|
99
|
+
},
|
100
|
+
"format": "uri",
|
101
|
+
"uniqueItems": true
|
102
|
+
},
|
103
|
+
"links": {
|
104
|
+
"type": "array",
|
105
|
+
"description": "Links to project artifacts",
|
106
|
+
"items": {
|
107
|
+
"$ref": "#/definitions/link"
|
108
|
+
},
|
109
|
+
"format": "uri",
|
110
|
+
"uniqueItems": true
|
111
|
+
},
|
112
|
+
"contact": {
|
113
|
+
"type": "array",
|
114
|
+
"description": "Email addresses of points-of-contact",
|
115
|
+
"items": {
|
116
|
+
"type": "string",
|
117
|
+
"description": "Email address",
|
118
|
+
"format": "uri"
|
119
|
+
},
|
120
|
+
"uniqueItems": true
|
121
|
+
}
|
122
|
+
},
|
123
|
+
"required": [
|
124
|
+
"name", "full_name", "stage", "team", "licenses", "owner_type", "status", "testable"
|
125
|
+
],
|
126
|
+
"definitions": {
|
127
|
+
"person": {
|
128
|
+
"type": "object",
|
129
|
+
"description": "Individual contributor to the project",
|
130
|
+
"properties": {
|
131
|
+
"github": {
|
132
|
+
"type": "string",
|
133
|
+
"description": "GitHub user name"
|
134
|
+
},
|
135
|
+
"id": {
|
136
|
+
"type": "string",
|
137
|
+
"description": "Internal team identifier/user name"
|
138
|
+
},
|
139
|
+
"role": {
|
140
|
+
"type": "string",
|
141
|
+
"description": "Team member's role; leads should be designated as 'lead'"
|
142
|
+
}
|
143
|
+
}
|
144
|
+
},
|
145
|
+
"service": {
|
146
|
+
"type": "object",
|
147
|
+
"description": "Service used to provide project status",
|
148
|
+
"properties": {
|
149
|
+
"name": {
|
150
|
+
"type": "string",
|
151
|
+
"description": "Name of the service"
|
152
|
+
},
|
153
|
+
"category": {
|
154
|
+
"type": "string",
|
155
|
+
"description": "Type of the service"
|
156
|
+
},
|
157
|
+
"url": {
|
158
|
+
"type": "string",
|
159
|
+
"description": "URL for detailed information",
|
160
|
+
"format": "uri"
|
161
|
+
},
|
162
|
+
"badge": {
|
163
|
+
"type": "string",
|
164
|
+
"description": "URL for the status badge",
|
165
|
+
"format": "uri"
|
166
|
+
}
|
167
|
+
}
|
168
|
+
},
|
169
|
+
"license": {
|
170
|
+
"type": "object",
|
171
|
+
"description": "License under which the project (or a component of the project) is offered",
|
172
|
+
"properties": {
|
173
|
+
"name": {
|
174
|
+
"type": "string",
|
175
|
+
"description": "Name of the license from the Software Package Data Exchange (SPDX): https://spdx.org/licenses/"
|
176
|
+
},
|
177
|
+
"url": {
|
178
|
+
"type": "string",
|
179
|
+
"description": "URL for the text of the license",
|
180
|
+
"format": "uri"
|
181
|
+
}
|
182
|
+
}
|
183
|
+
},
|
184
|
+
"link": {
|
185
|
+
"type": "object",
|
186
|
+
"description": "Link to a project artifact",
|
187
|
+
"properties": {
|
188
|
+
"url": {
|
189
|
+
"type": "string",
|
190
|
+
"description": "URL for the link",
|
191
|
+
"format": "uri"
|
192
|
+
},
|
193
|
+
"text": {
|
194
|
+
"type": "string",
|
195
|
+
"description": "Anchor text for the link"
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# @author Mike Bland (michael.bland@gsa.gov)
|
2
|
+
|
3
|
+
require_relative 'about'
|
4
|
+
require 'json-schema'
|
5
|
+
require 'safe_yaml'
|
6
|
+
|
7
|
+
module AboutYml
|
8
|
+
class TemplateGenerator
|
9
|
+
attr_reader :schema, :properties, :required
|
10
|
+
def initialize
|
11
|
+
@schema = ::AboutYml::AboutFile.schema
|
12
|
+
@properties = schema['properties']
|
13
|
+
@required = schema['required']
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate
|
17
|
+
props = properties.map { |name, defn| generate_item name, defn }
|
18
|
+
"---\n# #{schema['description']}\n#\n#{props.join "\n\n"}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def generate_item(name, definition)
|
24
|
+
"#{property_description name, definition}\n#{name}:" \
|
25
|
+
"#{"\n- " if definition['type'] == 'array'}" \
|
26
|
+
"#{"\n placeholder_label:" if definition['patternProperties']}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def property_description(name, definition)
|
30
|
+
description = "# #{definition['description']}"
|
31
|
+
description += ' (required)' if required.include? name
|
32
|
+
description + value_description(definition)
|
33
|
+
end
|
34
|
+
|
35
|
+
def value_description(definition)
|
36
|
+
values = definition['enum']
|
37
|
+
return "\n# values: #{values.join ', '}" if values
|
38
|
+
type = definition['type']
|
39
|
+
return "\n# values: true, false" if type == 'boolean'
|
40
|
+
return item_description definition if type == 'array'
|
41
|
+
return pattern_desc definition if definition['patternProperties']
|
42
|
+
''
|
43
|
+
end
|
44
|
+
|
45
|
+
def item_description(definition)
|
46
|
+
item_ref = definition['items']['$ref']
|
47
|
+
return '' unless item_ref
|
48
|
+
properties = definition_properties item_ref
|
49
|
+
descs = properties.map { |name, defn| "#{name}: #{defn['description']}" }
|
50
|
+
"\n# Items:\n# - #{descs.shift}\n# #{descs.join "\n# "}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def pattern_desc(definition)
|
54
|
+
property_descs = definition['patternProperties'].map do |prop_name, ref|
|
55
|
+
descs = definition_properties(ref['$ref']).map do |defn_name, defn|
|
56
|
+
"#{defn_name}: #{defn['description']}"
|
57
|
+
end
|
58
|
+
"\n# #{prop_name}:\n# #{descs.join "\n# "}"
|
59
|
+
end.join "\n"
|
60
|
+
"\n# Items by property name pattern:#{property_descs}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def definition_properties(item_ref)
|
64
|
+
schema['definitions'][item_ref.split('/').last]['properties']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/about_yml.rb
ADDED
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: about_yml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Bland
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: safe_yaml
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: octokit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json-schema
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: go_script
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.4'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: codeclimate-test-reporter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: coveralls
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: The .about.yml mechanism allows an project to publish and maintain metadata
|
140
|
+
that can be easily maintained by project owners, that is visible and accessible
|
141
|
+
to interested parties, and that can be harvested and processed by tools and automated
|
142
|
+
systems.
|
143
|
+
email:
|
144
|
+
- michael.bland@gsa.gov
|
145
|
+
executables:
|
146
|
+
- about_yml_generator
|
147
|
+
- about_yml_scrape
|
148
|
+
- about_yml_validate
|
149
|
+
- github_org_descriptions
|
150
|
+
extensions: []
|
151
|
+
extra_rdoc_files: []
|
152
|
+
files:
|
153
|
+
- CONTRIBUTING.md
|
154
|
+
- LICENSE.md
|
155
|
+
- README.md
|
156
|
+
- bin/about_yml_generator
|
157
|
+
- bin/about_yml_scrape
|
158
|
+
- bin/about_yml_validate
|
159
|
+
- bin/github_org_descriptions
|
160
|
+
- lib/about_yml.rb
|
161
|
+
- lib/about_yml/about.rb
|
162
|
+
- lib/about_yml/schema.json
|
163
|
+
- lib/about_yml/template_generator.rb
|
164
|
+
- lib/about_yml/version.rb
|
165
|
+
homepage: https://github.com/18F/about_yml
|
166
|
+
licenses:
|
167
|
+
- CC0
|
168
|
+
metadata: {}
|
169
|
+
post_install_message:
|
170
|
+
rdoc_options: []
|
171
|
+
require_paths:
|
172
|
+
- lib
|
173
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - ">="
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: '0'
|
178
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0'
|
183
|
+
requirements: []
|
184
|
+
rubyforge_project:
|
185
|
+
rubygems_version: 2.4.5.1
|
186
|
+
signing_key:
|
187
|
+
specification_version: 4
|
188
|
+
summary: ".about.yml project metadata schema and tools"
|
189
|
+
test_files: []
|