brief 0.0.5 → 1.0.0

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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +71 -55
  4. data/README.md +149 -48
  5. data/Rakefile +15 -5
  6. data/bin/brief +15 -28
  7. data/brief.gemspec +17 -11
  8. data/examples/blog/brief.rb +54 -0
  9. data/examples/blog/docs/an-intro-to-brief.html.md +9 -0
  10. data/lib/.DS_Store +0 -0
  11. data/lib/brief/briefcase.rb +78 -0
  12. data/lib/brief/cli/change.rb +14 -0
  13. data/lib/brief/cli/init.rb +66 -0
  14. data/{spec/fixtures/generated/project_overview.json → lib/brief/cli/publish.rb} +0 -0
  15. data/lib/brief/cli/write.rb +0 -0
  16. data/lib/brief/configuration.rb +19 -115
  17. data/lib/brief/core_ext.rb +11 -0
  18. data/lib/brief/document/content_extractor.rb +33 -0
  19. data/lib/brief/document/front_matter.rb +20 -0
  20. data/lib/brief/document/rendering.rb +37 -0
  21. data/lib/brief/document.rb +43 -38
  22. data/lib/brief/document_mapper.rb +158 -0
  23. data/lib/brief/dsl.rb +42 -0
  24. data/lib/brief/model/definition.rb +117 -0
  25. data/lib/brief/model.rb +177 -0
  26. data/lib/brief/repository.rb +57 -0
  27. data/lib/brief/version.rb +1 -7
  28. data/lib/brief.rb +35 -40
  29. data/spec/fixtures/example/brief.rb +27 -0
  30. data/spec/fixtures/example/docs/concept.html.md +5 -0
  31. data/spec/fixtures/example/docs/epic.html.md +19 -0
  32. data/spec/fixtures/example/docs/persona.html.md +5 -0
  33. data/spec/fixtures/example/docs/release.html.md +7 -0
  34. data/spec/fixtures/example/docs/resource.html.md +5 -0
  35. data/spec/fixtures/example/docs/user_story.html.md +24 -0
  36. data/spec/fixtures/example/docs/wireframe.html.md +5 -0
  37. data/spec/fixtures/example/models/epic.rb +16 -0
  38. data/spec/lib/brief/briefcase_spec.rb +27 -0
  39. data/spec/lib/brief/document_spec.rb +14 -22
  40. data/spec/lib/brief/dsl_spec.rb +4 -15
  41. data/spec/lib/brief/model_spec.rb +84 -0
  42. data/spec/lib/brief/repository_spec.rb +60 -0
  43. data/spec/spec_helper.rb +12 -14
  44. data/spec/support/test_helpers.rb +0 -0
  45. data/tasks/brief/release.rake +0 -0
  46. metadata +120 -110
  47. data/.gitignore +0 -1
  48. data/Guardfile +0 -5
  49. data/examples/project_overview.md +0 -23
  50. data/lib/brief/cli/commands/config.rb +0 -40
  51. data/lib/brief/cli/commands/publish.rb +0 -27
  52. data/lib/brief/cli/commands/write.rb +0 -27
  53. data/lib/brief/formatters/base.rb +0 -12
  54. data/lib/brief/formatters/github_milestone_rollup.rb +0 -52
  55. data/lib/brief/git.rb +0 -19
  56. data/lib/brief/github/wiki.rb +0 -9
  57. data/lib/brief/github.rb +0 -141
  58. data/lib/brief/github_client/authentication.rb +0 -32
  59. data/lib/brief/github_client/client.rb +0 -86
  60. data/lib/brief/github_client/commands.rb +0 -5
  61. data/lib/brief/github_client/issue_labels.rb +0 -65
  62. data/lib/brief/github_client/issues.rb +0 -22
  63. data/lib/brief/github_client/milestone_issues.rb +0 -13
  64. data/lib/brief/github_client/organization_activity.rb +0 -9
  65. data/lib/brief/github_client/organization_issues.rb +0 -13
  66. data/lib/brief/github_client/organization_repositories.rb +0 -20
  67. data/lib/brief/github_client/organization_users.rb +0 -9
  68. data/lib/brief/github_client/repository_events.rb +0 -8
  69. data/lib/brief/github_client/repository_issue_events.rb +0 -9
  70. data/lib/brief/github_client/repository_issues.rb +0 -8
  71. data/lib/brief/github_client/repository_labels.rb +0 -18
  72. data/lib/brief/github_client/repository_milestones.rb +0 -9
  73. data/lib/brief/github_client/request.rb +0 -181
  74. data/lib/brief/github_client/request_wrapper.rb +0 -121
  75. data/lib/brief/github_client/response_object.rb +0 -50
  76. data/lib/brief/github_client/single_repository.rb +0 -9
  77. data/lib/brief/github_client/user_activity.rb +0 -16
  78. data/lib/brief/github_client/user_gists.rb +0 -9
  79. data/lib/brief/github_client/user_info.rb +0 -9
  80. data/lib/brief/github_client/user_issues.rb +0 -13
  81. data/lib/brief/github_client/user_organizations.rb +0 -9
  82. data/lib/brief/github_client/user_repositories.rb +0 -9
  83. data/lib/brief/github_client.rb +0 -43
  84. data/lib/brief/handlers/base.rb +0 -62
  85. data/lib/brief/handlers/github_issue.rb +0 -41
  86. data/lib/brief/handlers/github_milestone.rb +0 -37
  87. data/lib/brief/handlers/github_wiki.rb +0 -11
  88. data/lib/brief/line.rb +0 -69
  89. data/lib/brief/parser.rb +0 -354
  90. data/lib/brief/publisher/handler_manager.rb +0 -47
  91. data/lib/brief/publisher.rb +0 -142
  92. data/lib/brief/tree.rb +0 -43
  93. data/lib/core_ext.rb +0 -37
  94. data/spec/fixtures/front_end_tutorial.md +0 -33
  95. data/spec/fixtures/generator_dsl_example.rb +0 -22
  96. data/spec/fixtures/project_overview.md +0 -48
  97. data/spec/fixtures/sample.md +0 -19
  98. data/spec/lib/brief/line_spec.rb +0 -11
  99. data/spec/lib/brief/parser_spec.rb +0 -12
@@ -1,27 +0,0 @@
1
- command :publish do |c|
2
- c.syntax = 'brief publish PUBLISHER [options]'
3
- c.description = 'publish a brief file with whatever publisher template you want to use.'
4
-
5
- c.option '--from FILE', 'Specify a file to read from. Otherwise we use $EDITOR'
6
-
7
- c.action do |args, options|
8
- path = case
9
- when options.from
10
- Pathname(options.from)
11
- when (Pathname(args.last).exist? rescue false)
12
- Pathname(args.pop)
13
- end
14
-
15
- document = Brief::Document.new(path: path)
16
-
17
- publisher = if path && path.exist? && args.empty?
18
- guess = path.basename.to_s.gsub(/\.\w+$/,'')
19
-
20
- Brief::Publisher.find(guess)
21
- else
22
- Brief::Publisher.find(args)
23
- end
24
-
25
- document.publish(publisher)
26
- end
27
- end
@@ -1,27 +0,0 @@
1
- command :write do |c|
2
- c.syntax = 'brief write PUBLISHER [options]'
3
-
4
- c.option '--file FILE', 'Specify a file to read from. Otherwise we use $EDITOR'
5
-
6
- c.action do |args, options|
7
- path = case
8
- when options.file
9
- Pathname(options.file)
10
- when (Pathname(args.last).exist? rescue false)
11
- Pathname(args.pop)
12
- end
13
-
14
-
15
- publisher = Brief::Publisher.find(args)
16
-
17
- content = ask_editor(publisher.sample)
18
-
19
- if content == publisher.sample
20
- say "Ignoring editor input, same as sample"
21
- else
22
- document = Brief::Document.new(content)
23
- document.publish(publisher)
24
- end
25
- end
26
- end
27
-
@@ -1,12 +0,0 @@
1
- module Brief
2
- module Formatters
3
- class Base
4
-
5
- attr_accessor :element
6
-
7
- def initialize(element)
8
- @element = element
9
- end
10
- end
11
- end
12
- end
@@ -1,52 +0,0 @@
1
- # The GithubMilestoneRollup formatter takes the raw input markdown
2
- # which specifies a relationship between the milestone and its child
3
- # issues with all of the necessary detail, and replaces it with a
4
- # bulleted list of links to the issues on github, with their titles,
5
- # assignee relationship, and current status
6
- #
7
- # So for example, given the raw input:
8
- #
9
- # --- BEGIN RAW INPUT
10
- #
11
- # ## Milestone Heading
12
- #
13
- # Content for the milestone description.
14
- #
15
- # ### Nested Issue One
16
- #
17
- # Detail for nested issue one.
18
- # Blah blah blah
19
- #
20
- # ### Nested Issue Two
21
- #
22
- # Detail for nested issue two
23
- #
24
- # --- END RAW INPUT ---
25
- #
26
- # We should get:
27
- #
28
- # --- BEGIN FORMATTED OUTPUT ---
29
- #
30
- # ## (Milestone Heading)[https://github.com/datapimp/brief/milestones/1]
31
- #
32
- # Content for milestone description
33
- #
34
- # ### (Nested Issue One)[https://github.com/datapimp/brief/issues/1]
35
- # Assigned To|Last Updated|Status
36
- # ---|---|---
37
- # datapimp|July 4, 2014|open
38
- #
39
- # ### (Nested Issue Two)[https://github.com/datapimp/brief/issues/2]
40
- # Assigned To|Last Updated|Status
41
- # ---|---|---
42
- # datapimp|July 4, 2014|open
43
- #
44
- # --- END FORMATTED OUTPUT ---
45
- #
46
- module Brief
47
- module Formatters
48
- class GithubMilestoneRollup < Base
49
-
50
- end
51
- end
52
- end
data/lib/brief/git.rb DELETED
@@ -1,19 +0,0 @@
1
- module Brief
2
- module Git
3
- def self.current_github_repository
4
- return nil unless Pathname(Dir.pwd).join('.git').exist?
5
-
6
- return @current_github_repository if @current_github_repository
7
-
8
- github_remote = `git remote`.lines.to_a.detect do |remote_name|
9
- `git remote show #{ remote_name }`.match(/github\.com/)
10
- end
11
-
12
- if github_remote
13
- lines = `git remote show #{ github_remote }`.lines.to_a.map(&:strip)
14
- line = lines.detect {|l| l.match(/Fetch URL/)}
15
- @current_github_repository = line.split(':').last.gsub(/\.git$/,'')
16
- end
17
- end
18
- end
19
- end
@@ -1,9 +0,0 @@
1
- module Brief
2
- module Github
3
- module Wiki
4
- def self.initialize!
5
-
6
- end
7
- end
8
- end
9
- end
data/lib/brief/github.rb DELETED
@@ -1,141 +0,0 @@
1
- require 'brief/formatters/github_milestone_rollup'
2
- require 'brief/handlers/github_issue'
3
- require 'brief/handlers/github_milestone'
4
- require 'brief/handlers/github_wiki'
5
-
6
- module Brief
7
- def self.github_nickname
8
- (Brief.profile.github_nickname rescue nil) || Brief::Git.current_github_repository.try(:split, '/').try(:first)
9
- end
10
-
11
- def self.github_repository_name
12
- (Brief.profile.github_repository_name rescue nil) || Brief::Git.current_github_repository.try(:split, '/').try(:last)
13
- end
14
-
15
- def self.repository_issues
16
- @repository_issues ||= Brief::GithubClient::RepositoryIssues.new(user: github_nickname, repo: github_repository_name)
17
- end
18
-
19
- def self.repository_milestones
20
- @repository_milestones ||= Brief::GithubClient::RepositoryMilestones.new(user: github_nickname, repo: github_repository_name)
21
- end
22
- end
23
-
24
- Brief.define "Issue" do
25
- before(:write) do
26
- require "brief/github_client"
27
- !Brief.config.github_repository.nil?
28
- end
29
-
30
- before(:publish) do
31
- require "brief/github_client"
32
- !Brief.config.github_repository.nil?
33
- end
34
-
35
- sample <<-EOF
36
- # This is the issue title
37
-
38
- Anything else that you put here will be part of the issue body
39
- EOF
40
-
41
- levels do
42
- level(1) do
43
- desc "Github Issue"
44
- define_handler :publish, "Brief::Handlers::GithubIssue"
45
- end
46
- end
47
- end
48
-
49
- Brief.define "Milestone with issues" do
50
- before(:write) do
51
- require "brief/github_client"
52
- !Brief.config.github_repository.nil?
53
- end
54
-
55
- before(:publish) do
56
- require "brief/github_client"
57
- !Brief.config.github_repository.nil?
58
- end
59
-
60
- sample <<-EOF
61
- # This is a milestone heading
62
-
63
- A milestone is some logical way of grouping issues and attaching a date to them. You will write the body
64
- of the individual issues and optionally assign them or label them by writing them below. When this brief
65
- gets published, the issues will be created and added to the milestone.
66
-
67
- ## This is an issue that belongs to the above milestone
68
-
69
- The content of your issue goes here. Normal github flavored markdown is supported.
70
- EOF
71
-
72
- levels do
73
- level(1) do
74
- desc "Github Milestone"
75
- define_handler :publish, "Brief::Handlers::GithubMilestone"
76
- replaces_items_from_level 3, :with => nil
77
- end
78
-
79
- level(2) do
80
- desc "Github Issue"
81
- define_handler :publish, "Brief::Handlers::GithubIssue"
82
- end
83
- end
84
- end
85
-
86
-
87
- Brief.define "Project Overview" do
88
- aliases :overview, :project_overview
89
-
90
- before(:write) do
91
- require "brief/github_client"
92
- !Brief.config.github_repository.nil?
93
- end
94
-
95
- before(:publish) do
96
- require "brief/github_client"
97
- !Brief.config.github_repository.nil?
98
- end
99
-
100
- sample <<-EOF
101
- # This is a project overview
102
-
103
- A body paragraph or two here will be the content for a cover page. You can supply whatever background
104
- info, domain knowledge requirements, processes, file dependencies and links, whatever.
105
-
106
- The content for the nested milestones and issues below will be transformed into raw markdown
107
- which will generate a status summary of the milestones and issues as they get created in the Github API.
108
-
109
- ## This is a milestone heading
110
-
111
- A milestone is some logical way of grouping issues and attaching a date to them. You will write the body
112
- of the individual issues and optionally assign them or label them by writing them below. When this brief
113
- gets published, the issues will be created and added to the milestone.
114
-
115
- ### This is an issue that belongs to the above milestone
116
-
117
- The content of your issue goes here. Normal github flavored markdown is supported.
118
- EOF
119
-
120
- levels do
121
- order(2,3,1)
122
-
123
- level(1) do
124
- desc "Wiki Page"
125
- define_handler :publish, "Brief::Handlers::GithubWiki"
126
- replaces_items_from_level 2, :with => "Brief::Formatters::GithubMilestoneRollup"
127
- end
128
-
129
- level(2) do
130
- desc "Github Milestone"
131
- define_handler :publish, "Brief::Handlers::GithubMilestone"
132
- replaces_items_from_level 3, :with => nil
133
- end
134
-
135
- level(3) do
136
- desc "Github Issue"
137
- define_handler :publish, "Brief::Handlers::GithubIssue"
138
- end
139
- end
140
- end
141
-
@@ -1,32 +0,0 @@
1
- module Brief::GithubClient
2
- class Authentication
3
- attr_accessor :github_token, :options
4
-
5
- InvalidAuth = Class.new(Exception)
6
-
7
- def initialize(options={})
8
- options.symbolize_keys! if options.is_a?(Hash)
9
- @options = options
10
- fetch_token
11
- end
12
-
13
- protected
14
-
15
- def fetch_token
16
- @github_token = case
17
- when options.respond_to?(:github_token)
18
- options.github_token
19
- when options.is_a?(Hash) && options.has_key?(:github_token)
20
- options[:github_token]
21
- when options.is_a?(Hash) && (options.has_key?(:username) && options.has_key?(:password))
22
- raise "Not implemented. use personal access tokens."
23
-
24
- when "#{ENV['GITHUB_TOKEN']}".length > 1
25
- ENV['GITHUB_TOKEN']
26
- else
27
- raise InvalidAuth
28
- end
29
-
30
- end
31
- end
32
- end
@@ -1,86 +0,0 @@
1
- require 'typhoeus'
2
-
3
- class Brief::GithubClient::Client
4
- attr_accessor :options, :cache
5
-
6
- InvalidAuth = Class.new(Exception)
7
-
8
- def initialize options={}
9
- @options = options
10
-
11
- if options[:auto]
12
- options[:github_token] ||= Brief::GithubClient::Authentication.new.github_token
13
- end
14
- end
15
-
16
- def request_wrapper_class
17
- Brief::GithubClient::RequestWrapper
18
- end
19
-
20
- def fetch(request_type,*args)
21
- fetch_request_object(request_type, *args).to_object
22
- end
23
-
24
- def fetch_request_object request_type, *args
25
- options = args.extract_options!
26
- request_type = request_type.to_s.camelize
27
-
28
- if request_klass = Brief::GithubClient.const_get(request_type) rescue nil
29
- request_klass.new(options)
30
- end
31
- end
32
-
33
- def github_token
34
- options.fetch(:github_token, impersonate_user.try(:github_token))
35
- end
36
-
37
- def impersonate_user
38
- @impersonate_user ||= options.fetch(:user, nil)
39
- end
40
-
41
- def headers
42
- base = {
43
- "Authorization" => "token #{ github_token }",
44
- "Accepts" => "application/json"
45
- }
46
-
47
- base.merge(options[:headers] || {}).stringify_keys
48
- end
49
-
50
- def anonymous?
51
- !!(options[:public] || options[:anonymous])
52
- end
53
-
54
- def delete_request type, params={}
55
- if !github_token.present? && !anonymous?
56
- raise InvalidAuth
57
- end
58
-
59
- request_wrapper_class.new(type,params,headers).delete
60
- end
61
-
62
- def post_request type, params={}
63
- if !github_token.present? && !anonymous?
64
- raise InvalidAuth
65
- end
66
-
67
- request_wrapper_class.new(type,params,headers).post
68
- end
69
-
70
- def get_request type, params={}
71
- if !github_token.present? && !anonymous?
72
- raise InvalidAuth
73
- end
74
-
75
- request_wrapper_class.new(type,params,headers).get
76
- end
77
-
78
- def update_request type, params={}
79
- if !github_token.present? && !anonymous?
80
- raise InvalidAuth
81
- end
82
-
83
- request_wrapper_class.new(type,params,headers).update
84
- end
85
-
86
- end
@@ -1,5 +0,0 @@
1
- module Brief::GithubClient
2
- module Commands
3
-
4
- end
5
- end
@@ -1,65 +0,0 @@
1
- module Brief::GithubClient
2
- class IssueLabels < Request
3
-
4
- requires :org, :repo
5
-
6
- def endpoint
7
- "repos/#{ org }/#{ repo }/labels"
8
- end
9
-
10
- Defaults = {
11
- # stage labels
12
- "s:backlog" => "c7def8",
13
- "s:greenlit" => "bfe5bf",
14
- "s:review" => "fef2c0",
15
- "s:in_progress" => "3ded58",
16
-
17
- # priority labels
18
- "p:1" => "e11d21",
19
- "p:2" => "eb6420",
20
-
21
- # type labels
22
- "t:development" => "bada55",
23
- "t:design" => "55adba",
24
- "t:ux" => "2234fe",
25
- "t:project" => "ae3498",
26
-
27
- # acceptance labels
28
- "a:approved" => "339933",
29
- "a:rejected" => "993333"
30
- }
31
-
32
- def missing_defaults
33
- current = all.collect(&:name)
34
- @missing_defaults ||= Defaults.keys - current
35
- end
36
-
37
- def missing_defaults?
38
- missing_defaults.length > 0
39
- end
40
-
41
- def create_status_sort_labels
42
- Defaults.each do |name, color|
43
- create_or_update(name, color)
44
- end
45
- end
46
-
47
- def delete_github_defaults
48
- %w{bug duplicate enhancement invalid wontfix question}.each do |name|
49
- destroy(name)
50
- end
51
- end
52
-
53
- def create_or_update name, color
54
- existing = show(name)
55
-
56
- unless existing.nil? || (existing.present? && existing.respond_to?(:message))
57
- update(name, name: name, color: color)
58
- return show(name)
59
- end
60
-
61
- create(name: name, color: color)
62
- end
63
-
64
- end
65
- end
@@ -1,22 +0,0 @@
1
- module Brief::GithubClient
2
- class Issues < Request
3
- requires :org, :repo
4
-
5
- def endpoint
6
- case
7
- when supplied_org && repo
8
- "#{ supplied_org }/#{ repo }/issues"
9
- when user && repo
10
- "repos/#{ user }/#{ repo }/issues"
11
- when supplied_org
12
- "orgs/#{ supplied_org }/issues"
13
- when user
14
- "users/#{ user }/issues"
15
- end
16
- end
17
-
18
- def params
19
- @params.merge(sort:"updated")
20
- end
21
- end
22
- end
@@ -1,13 +0,0 @@
1
- module Brief::GithubClient
2
- class MilestoneIssues < RepositoryIssues
3
- def params
4
- p = @params
5
-
6
- if options[:milestone] && milestone.respond_to?(:number)
7
- p[:milestone_number] = milestone.number
8
- end
9
-
10
- p
11
- end
12
- end
13
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class OrganizationActivity < Request
3
- requires :supplied_org, :user
4
-
5
- def endpoint
6
- "users/#{ user }/events/orgs/#{ org }"
7
- end
8
- end
9
- end
@@ -1,13 +0,0 @@
1
- module Brief::GithubClient
2
- class OrganizationIssues < Request
3
- requires :supplied_org
4
-
5
- def endpoint
6
- "orgs/#{ org }/issues"
7
- end
8
-
9
- def params
10
- @params.merge(sort:"updated")
11
- end
12
- end
13
- end
@@ -1,20 +0,0 @@
1
- module Brief::GithubClient
2
- class OrganizationRepositories < Request
3
- requires :supplied_org
4
-
5
- def endpoint
6
- "orgs/#{ org }/repos"
7
- end
8
-
9
- def all
10
- @all ||= self.result
11
- end
12
-
13
- def to_list
14
- all.map do |repository|
15
- repository.slice("id","name","html_url","description","ssh_url")
16
- end
17
- end
18
-
19
- end
20
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class OrganizationUsers < Request
3
- requires :supplied_org
4
-
5
- def endpoint
6
- "orgs/#{ org }/members"
7
- end
8
- end
9
- end
@@ -1,8 +0,0 @@
1
- module Brief::GithubClient
2
- class RepositoryEvents < Request
3
- requires :org, :repo
4
- def endpoint
5
- "repos/#{ org }/#{ repo }/events"
6
- end
7
- end
8
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class RepositoryIssueEvents < Request
3
- requires :org, :repo
4
-
5
- def endpoint
6
- "repos/#{ org }/#{ repo }/issues/events"
7
- end
8
- end
9
- end
@@ -1,8 +0,0 @@
1
- module Brief::GithubClient
2
- class RepositoryIssues < Request
3
- requires :org, :repo
4
- def endpoint
5
- "repos/#{ org }/#{ repo }/issues"
6
- end
7
- end
8
- end
@@ -1,18 +0,0 @@
1
- module Brief::GithubClient
2
- class RepositoryLabels < Request
3
- requires :org, :repo
4
-
5
- def endpoint
6
- "repos/#{ org }/#{ repo }/labels"
7
- end
8
-
9
- def stage_labels
10
- @stage_labels ||= all.select {|label| label.name && label.name.match(/^s:/) }
11
- end
12
-
13
- def priority_labels
14
- @priority_labels ||= all.select {|label| label.name && label.name.match(/^p:/) }
15
- end
16
-
17
- end
18
- end
@@ -1,9 +0,0 @@
1
- module Brief::GithubClient
2
- class RepositoryMilestones < Request
3
- requires :org, :repo
4
-
5
- def endpoint
6
- "repos/#{ org }/#{ repo }/milestones"
7
- end
8
- end
9
- end