brief 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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