dbdoc 0.2.0 → 0.3.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
  SHA256:
3
- metadata.gz: 95d1967a75eb0505c9dd74882fcc2fa18127b464d2358f4fe83bfb803a3291c9
4
- data.tar.gz: 655b2bf4f41c4c05e4709ec44611af42e9f529daa9891617529c131a095c6968
3
+ metadata.gz: e952e625ed6d66c0643f58a94be599f509e9c73827013a0f39a54145281b3951
4
+ data.tar.gz: dcb4a347c77a5f7524ca194f702cc5412b36cdb91b7363e871d96197fc9aff93
5
5
  SHA512:
6
- metadata.gz: 65386544fb68b47f56121ab291b86b0bbb0d462c35692e40d223faaaa56b7accc2cf401438001ddf9fb1aab01fb80f51fb28aededa4653f4ff5da41435b65e13
7
- data.tar.gz: da90433a70497544484e32bacd6806ea166b64f7cd9cf90f1111da06d9c14c90c582dc9fb7890094bea272dff25fc3033261b22f16c623c8b204b3a2b787b6da
6
+ metadata.gz: a3fd633a549a92f0bc6194bba2a27c93d0275e65b149cdeeec4592bd88ce66a41a695e2b2a35db8607f7476d4d85c5d4c7535441bf6ab58f7e67b2865116e45d
7
+ data.tar.gz: d61c04bc79f94523e3a7a3a19711f2778d99be2346c02998d15036b079844f942f910f4a16222a124ba1edd9348ea28a4cb627a8aec58aab4517575def440ef0
@@ -1,2 +1,27 @@
1
1
  Style/StringLiterals:
2
2
  EnforcedStyle: double_quotes
3
+
4
+ Metrics/ClassLength:
5
+ Max: 200
6
+
7
+ Metrics/MethodLength:
8
+ Max: 50
9
+
10
+ Style/Documentation:
11
+ Exclude:
12
+ - lib/confluence/api.rb
13
+ - lib/dbdoc/cli.rb
14
+
15
+ Metrics/AbcSize:
16
+ Exclude:
17
+ - lib/dbdoc/cli.rb
18
+
19
+ Layout/FirstHashElementIndentation:
20
+ EnforcedStyle: consistent
21
+
22
+ Metrics/BlockLength:
23
+ Exclude:
24
+ - spec/**/*_spec.rb
25
+
26
+ Security/YAMLLoad:
27
+ Enabled: false
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  gemspec
@@ -8,7 +10,7 @@ gem "kramdown"
8
10
  group :development do
9
11
  gem "byebug"
10
12
  gem "coveralls", require: false
11
- gem "rubocop"
12
13
  gem "rake", "~> 12.0"
13
14
  gem "rspec", "~> 3.0"
15
+ gem "rubocop"
14
16
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dbdoc (0.2.0)
4
+ dbdoc (0.3.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
  require "rubocop/rake_task"
data/bin/dbdoc CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #!/usr/bin/env ruby
2
4
 
3
5
  require "dbdoc"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "lib/dbdoc/version"
2
4
 
3
5
  Gem::Specification.new do |spec|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "httparty"
2
4
  require "json"
3
5
  require "yaml"
@@ -22,7 +24,7 @@ module Confluence
22
24
  "https://dbdoc.atlassian.net/wiki/rest/api/content/#{page_id}", {
23
25
  headers: {
24
26
  "Authorization" => "Basic #{basic_auth}",
25
- "Content-Type" => "application/json"
27
+ "Content-Type" => "application/json"
26
28
  }
27
29
  }
28
30
  )
@@ -36,7 +38,7 @@ module Confluence
36
38
  "https://dbdoc.atlassian.net/wiki/rest/api/content/?&spaceKey=#{@space}", {
37
39
  headers: {
38
40
  "Authorization" => "Basic #{basic_auth}",
39
- "Content-Type" => "application/json"
41
+ "Content-Type" => "application/json"
40
42
  }
41
43
  }
42
44
  )
@@ -67,7 +69,7 @@ module Confluence
67
69
  "https://dbdoc.atlassian.net/wiki/rest/api/content/#{page_id}", {
68
70
  headers: {
69
71
  "Authorization" => "Basic #{basic_auth}",
70
- "Content-Type" => "application/json"
72
+ "Content-Type" => "application/json"
71
73
  },
72
74
  body: payload.to_json
73
75
  }
@@ -115,7 +117,7 @@ module Confluence
115
117
  "https://dbdoc.atlassian.net/wiki/rest/api/content/", {
116
118
  headers: {
117
119
  "Authorization" => "Basic #{basic_auth}",
118
- "Content-Type" => "application/json"
120
+ "Content-Type" => "application/json"
119
121
  },
120
122
  body: payload.to_json
121
123
  }
@@ -1,8 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "kramdown"
2
4
 
3
5
  module Confluence
6
+ # By default, all documentation should be written in a normal
7
+ # Markdown format. Later, when we're generating/uploading final documentation,
8
+ # we'll use Confluence::MarkdownConverter to convert normal Markdown
9
+ # into Confluence specific Markdown
10
+ # https://confluence.atlassian.com/bitbucketserver/markdown-syntax-guide-776639995.html
4
11
  class MarkdownConverter
5
- CONVERTERS = %w(
12
+ CONVERTERS = %w[
6
13
  convert_h1
7
14
  convert_h2
8
15
  convert_h3
@@ -12,7 +19,7 @@ module Confluence
12
19
  convert_italic
13
20
  convert_code
14
21
  convert_unordered_list
15
- )
22
+ ].freeze
16
23
 
17
24
  def convert(original_markdown)
18
25
  return if original_markdown.nil?
@@ -81,7 +88,7 @@ module Confluence
81
88
  # TODO: add nested list convertion
82
89
  # TODO: add numbered list convertion
83
90
 
84
- # TODO :add emoji
91
+ # TODO: add emoji
85
92
  # https://support.atlassian.com/confluence-cloud/docs/use-symbols-emojis-and-special-characters/
86
93
  end
87
94
  end
@@ -1,11 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "dbdoc/constants"
2
4
  require_relative "../confluence/markdown_converter"
3
5
  require_relative "../confluence/api"
4
6
 
5
- module Dbdoc
7
+ module Confluence
8
+ # Confluence::Uploader class knows how to uploaded
9
+ # documentation to the Confluence Space provided in the config.yml.
10
+ #
11
+ # Uploader creates a root page with the database name from config.yml
12
+ # and creates nested pages for schemas and tables.
13
+ #
14
+ # A Confluence ID of each page created by dbdoc
15
+ # is logged to pages.yml file stored in the user's folder
16
+ # with the documentation.
6
17
  class Uploader
7
- def initialize(config: {})
8
- @config = config
18
+ def initialize(local_path: Dir.pwd)
19
+ @config = Dbdoc::Config.new(local_path: local_path).load
9
20
  @confluence_api = Confluence::Api.new
10
21
  @doc_folder = File.join(Dir.pwd, "doc")
11
22
  end
@@ -19,8 +30,17 @@ module Dbdoc
19
30
  @confluence_api.existing_pages["results"]
20
31
  end
21
32
 
33
+ def print_space_pages
34
+ space_pages.each do |page|
35
+ page_title = page["title"]
36
+ page_id = page["id"]
37
+
38
+ puts "#{page_title}: #{page_id}"
39
+ end
40
+ end
41
+
22
42
  def clear_confluence_space
23
- uploaded_pages = YAML.load(File.read(page_ids_file))
43
+ YAML.load(File.read(page_ids_file))
24
44
 
25
45
  space_pages.each do |page|
26
46
  page_key = page["title"]
@@ -28,24 +48,23 @@ module Dbdoc
28
48
 
29
49
  puts "--> Deleting #{page_key} #{page_id}"
30
50
 
31
- if @confluence_api.delete_page(page_id: page_id)
32
- unlog_page_id(key: page_key)
33
- end
51
+ unlog_page_id(key: page_key) if @confluence_api.delete_page(page_id: page_id)
34
52
  end
35
53
  end
36
54
 
37
55
  private
38
56
 
57
+ # rubocop:disable Metrics/AbcSize
39
58
  def delete_pages_for_dropped_schemas_or_tables
40
59
  uploaded_pages = YAML.load(File.read(page_ids_file))
41
60
 
42
- uploaded_pages.each do |key, params|
61
+ uploaded_pages.each do |key, _params|
43
62
  next if key == "root"
44
63
 
45
64
  if key.start_with?("schema:")
46
65
  schema_name = key.gsub("schema:", "")
47
66
 
48
- unless Dir.exists?(File.join(@doc_folder, schema_name))
67
+ unless Dir.exist?(File.join(@doc_folder, schema_name))
49
68
  page_id = uploaded_pages[key][:page_id]
50
69
  puts "--> delete page #{key}: #{page_id}"
51
70
  @confluence_api.delete_page(page_id: page_id)
@@ -54,7 +73,7 @@ module Dbdoc
54
73
  elsif key.start_with?("table:")
55
74
  schema_name, table_name = key.gsub("table:", "").split(".")
56
75
 
57
- unless Dir.exists?(File.join(@doc_folder, schema_name, table_name))
76
+ unless Dir.exist?(File.join(@doc_folder, schema_name, table_name))
58
77
  page_id = uploaded_pages[key][:page_id]
59
78
  puts "--> delete page #{key}: #{page_id}"
60
79
  @confluence_api.delete_page(page_id: page_id)
@@ -63,6 +82,7 @@ module Dbdoc
63
82
  end
64
83
  end
65
84
  end
85
+ # rubocop:enable Metrics/AbcSize
66
86
 
67
87
  def create_or_updates_pages
68
88
  root_page_id = create_root_db_page[:page_id]
@@ -85,7 +105,7 @@ module Dbdoc
85
105
  def page_ids_file
86
106
  file = File.join(Dir.pwd, "page_ids.yml")
87
107
 
88
- unless File.exists?(file)
108
+ unless File.exist?(file)
89
109
  File.open(file, "w") do |f|
90
110
  f.puts("--- {}")
91
111
  end
@@ -111,7 +131,7 @@ module Dbdoc
111
131
  version: 0
112
132
  }
113
133
 
114
- if page_ids[key][:version] == 0
134
+ if page_ids.dig(key, :version).zero?
115
135
  puts "--> create page #{key}: #{page_id}"
116
136
  else
117
137
  puts "--> update page #{key}: #{page_id}"
@@ -137,9 +157,11 @@ module Dbdoc
137
157
  def create_root_db_page
138
158
  page_id = latest_page_id(key: "root")
139
159
 
140
- return {
141
- page_id: page_id
142
- } if page_id
160
+ if page_id
161
+ return {
162
+ page_id: page_id
163
+ }
164
+ end
143
165
 
144
166
  db_name = @config["db"]["name"]
145
167
  @confluence_api.create_page(
@@ -180,13 +202,16 @@ module Dbdoc
180
202
  Confluence::MarkdownConverter.new.convert(input)
181
203
  end
182
204
 
205
+ # rubocop:disable Metrics/AbcSize
183
206
  def upload_table(schema_name:, table_name:, schema_page_id:)
184
207
  table_folder = File.join(@doc_folder, schema_name, table_name)
185
208
 
186
209
  table_description = markdown(File.read(File.join(table_folder, "description.md")))
187
210
 
188
211
  examples_folder = File.join(table_folder, "examples")
189
- table_examples = Dir[File.join(examples_folder, "*.md")].map { |f| File.read(f) }.map { |example| markdown(example) }
212
+ table_examples = Dir[File.join(examples_folder, "*.md")].map do |f|
213
+ markdown(File.read(f))
214
+ end
190
215
 
191
216
  columns_markdown_template_file = File.join(DBDOC_HOME, "doc_files", "columns.md.erb")
192
217
 
@@ -205,18 +230,18 @@ module Dbdoc
205
230
  columns: columns_doc
206
231
  })
207
232
 
208
- page_body = <<-MARKDOWN
209
- h2. Description
233
+ page_body = <<~MARKDOWN
234
+ h2. Description
210
235
 
211
- #{table_description}
236
+ #{table_description}
212
237
 
213
- h2. Columns
238
+ h2. Columns
214
239
 
215
- #{columns_table}
240
+ #{columns_table}
216
241
 
217
- h2. Examples
242
+ h2. Examples
218
243
 
219
- #{table_examples.join("\n") }
244
+ #{table_examples.join("\n")}
220
245
  MARKDOWN
221
246
 
222
247
  page_title = schema_name == "public" ? table_name : "#{schema_name}.#{table_name}"
@@ -225,7 +250,7 @@ h2. Examples
225
250
  page_id = latest_page_id(key: page_key)
226
251
 
227
252
  if page_id
228
- response = @confluence_api.update_page(
253
+ @confluence_api.update_page(
229
254
  page_id: page_id,
230
255
  page_title: page_title,
231
256
  body: page_body,
@@ -245,5 +270,6 @@ h2. Examples
245
270
  log_page_id(key: "table:#{schema_name}.#{table_name}", page_id: table_page_id)
246
271
  end
247
272
  end
273
+ # rubocop:enable Metrics/AbcSize
248
274
  end
249
275
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "dbdoc/constants"
2
4
  require "dbdoc/version"
3
5
  require "dbdoc/config"
4
6
  require "dbdoc/manager"
5
- require "dbdoc/uploader"
7
+ require "dbdoc/folder_initializer"
6
8
 
7
9
  module Dbdoc
8
10
  class Error < StandardError; end
@@ -1,157 +1,116 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "optparse"
2
4
 
3
5
  $LOAD_PATH << File.expand_path(__dir__)
4
6
 
5
7
  module Dbdoc
6
8
  class CLI
9
+ COMMANDS = {
10
+ install: %(
11
+ Generates all necessary config files and documentation folders.
12
+
13
+ Run this command in an empty directory.
14
+ ),
15
+ query: %(
16
+ Prints a query that you need to run in the database \
17
+ you're going to document.
18
+
19
+ Export the result of this query to the "schema.csv" file \
20
+ and copy it over to the "schema" folder for processing.
21
+ ),
22
+ plan: %(
23
+ Shows you what columns/tables/schemas are new and \
24
+ going to be added/deleted from the documentation.
25
+ ),
26
+ apply: %(
27
+ Generates boilerplate documentation for newly added \
28
+ columns/tables/schemas.
29
+
30
+ Drops documentation for columns/tables/schemas that \
31
+ were deleted from the database.
32
+ ),
33
+ "confluence:upload": %(
34
+ Uploads current documentation to Confluence: pages for \
35
+ new tables/schemas will be added, pages for dropped tables/schemas \
36
+ will be deleted from your Confluence space.
37
+ ),
38
+ "confluece:pages": %(
39
+ Lists all pages in your dbdoc Confluence space \
40
+ (created manually or via dbdoc).
41
+ ),
42
+ "confluence:clear": %(
43
+ IMPORTANT This command will delete ALL pages from \
44
+ the Confluence space (pages created via dbdoc AND pages that were added manually).
45
+ ),
46
+ todo: %(
47
+ Shows you the documentation that needs to be written.
48
+ )
49
+ }.freeze
50
+
51
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
7
52
  def run(args = [])
8
- if args.first == "init"
9
- require "fileutils"
10
-
11
- schema_folder = File.join(Dir.pwd, "schema")
12
- unless Dir.exists?(schema_folder)
13
- Dir.mkdir(schema_folder)
14
- end
15
-
16
- doc_folder = File.join(Dir.pwd, "doc")
17
- unless Dir.exists?(doc_folder)
18
- Dir.mkdir(doc_folder)
19
- end
20
-
21
- target_file = File.join(Dir.pwd, "config.yml")
22
- config_file = File.join(File.expand_path(__dir__), "../..", "config", "default.yml")
23
-
24
- FileUtils.cp(config_file, target_file) unless File.exists?(target_file)
25
-
26
- target_file = File.join(Dir.pwd, ".gitignore")
27
- config_file = File.join(File.expand_path(__dir__), "../..", "config", "gitignore.template")
28
-
29
- FileUtils.cp(config_file, target_file) unless File.exists?(target_file)
30
-
31
- target_file = File.join(Dir.pwd, "confluence.yml")
32
- config_file = File.join(File.expand_path(__dir__), "../..", "config", "confluence.yml")
33
-
34
- FileUtils.cp(config_file, target_file) unless File.exists?(target_file)
35
-
36
- 0
53
+ if args.first == "install"
54
+ Dbdoc::FolderInitializer.new.init
37
55
  elsif args.first == "query"
38
- options = extract_options(args)
39
-
40
- config = Dbdoc::Config.load
41
- config.merge!(options)
42
-
43
- db_type = config["db"]["type"]
44
- query_file = File.join(File.expand_path(__dir__), "../..", "config", "schema_queries", "#{db_type}.sql")
45
- query = File.read(query_file)
46
-
47
- puts query
48
-
49
- 0
56
+ puts manager.query
50
57
  elsif args.first == "plan"
51
- options = extract_options(args)
52
-
53
- config = Dbdoc::Config.load
54
- config.merge!(options)
58
+ plan = manager.plan
55
59
 
56
- manager = Dbdoc::Manager.new(config: config)
57
- manager.plan
60
+ puts "--> New columns:"
61
+ plan[:new_columns].each do |column|
62
+ puts column
63
+ end
58
64
 
59
- 0
65
+ puts "--> Columns to drop:"
66
+ plan[:columns_to_drop].each do |column|
67
+ puts column
68
+ end
60
69
  elsif args.first == "apply"
61
- options = extract_options(args)
62
-
63
- config = Dbdoc::Config.load
64
- config.merge!(options)
65
-
66
- manager = Dbdoc::Manager.new(config: config)
67
70
  manager.apply
68
-
69
- 0
70
- elsif args.first == "upload"
71
- options = extract_options(args)
72
-
73
- config = Dbdoc::Config.load
74
- config.merge!(options)
75
-
76
- uploader = Dbdoc::Uploader.new(config: config)
71
+ elsif args.first == "confluence:upload"
77
72
  uploader.upload
78
-
79
- 0
80
- elsif args.first == "existing_pages"
81
- options = extract_options(args)
82
-
83
- config = Dbdoc::Config.load
84
- config.merge!(options)
85
-
86
- uploader = Dbdoc::Uploader.new(config: config)
87
- pages = uploader.space_pages
88
-
89
- pages.each do |page|
90
- page_title = page["title"]
91
- page_id = page["id"]
92
-
93
- puts "#{page_title}: #{page_id}"
94
- end
95
-
96
- 0
97
- elsif args.first == "clear_space"
98
- options = extract_options(args)
99
-
100
- config = Dbdoc::Config.load
101
- config.merge!(options)
102
-
103
- uploader = Dbdoc::Uploader.new(config: config)
73
+ elsif args.first == "confluence:pages"
74
+ uploader.print_space_pages
75
+ elsif args.first == "confluence:clear"
104
76
  uploader.clear_confluence_space
105
-
106
- 0
107
77
  elsif args.first == "todo"
108
- options = extract_options(args)
109
-
110
- config = Dbdoc::Config.load
111
- config.merge!(options)
112
-
113
- manager = Dbdoc::Manager.new(config: config)
114
78
  manager.todo
115
-
116
- 0
117
79
  elsif args.first == "help"
118
- puts "--> SOME HELP"
119
-
120
- 0
80
+ print_help
81
+ elsif args.first == "version"
82
+ puts Dbdoc::VERSION
121
83
  end
122
84
 
123
85
  0
124
86
  end
87
+ # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
125
88
 
126
89
  private
127
90
 
128
- # This method is needed to unindent
129
- # ["here document"](https://en.wikibooks.org/wiki/Ruby_Programming/Here_documents)
130
- # help description.
131
- #
132
91
  def unindent(str)
133
92
  str.gsub(/^#{str.scan(/^[ \t]+(?=\S)/).min}/, "")
134
93
  end
135
94
 
136
- def extract_options(args)
137
- options = {}
138
-
139
- OptionParser.new do |opts|
140
- opts.banner = unindent(<<-TEXT)
141
- dbdoc help
95
+ def manager
96
+ @manager ||= Dbdoc::Manager.new
97
+ end
142
98
 
143
- 1. dbdoc query
99
+ def uploader
100
+ @uploader ||= Confluence::Uploader.new
101
+ end
144
102
 
145
- This will print you a query you need to run to export your database schema.
146
- TEXT
103
+ def print_help
104
+ puts unindent <<-TEXT
105
+ Usage: dbdoc [command]
106
+ TEXT
107
+ puts
147
108
 
148
- opts.on("-v", "--version", "Prints current version of dbdoc") do
149
- puts Dbdoc::VERSION
150
- exit 0
151
- end
152
- end.parse!(args)
153
-
154
- options
109
+ COMMANDS.each do |command, description|
110
+ puts "dbdoc #{command}"
111
+ puts
112
+ puts unindent(description)
113
+ end
155
114
  end
156
115
  end
157
116
  end
@@ -1,28 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
4
  require "dbdoc/constants"
3
5
 
4
6
  module Dbdoc
7
+ # Dbdoc::Config class knows how to load the default config from the
8
+ # dbdoc gem folder. Later, if needed, this class could be used to merge
9
+ # user-defined config with the default one.
5
10
  class Config
6
- FILE_NAME = "config.yml".freeze
7
- DEFAULT_FILE = File.join(DBDOC_HOME, "config", "default.yml")
8
-
9
- class << self
10
- # Be default gem will try to load config file in user's project folder.
11
- # Then user's config (or empty object) will be merge with the default config
12
- # from gem's folder.
13
- #
14
- def load
15
- user_config = File.exist?(user_file) ? YAML.safe_load(File.read(user_file)) : {}
16
- default_config = YAML.safe_load(File.read(DEFAULT_FILE))
17
-
18
- default_config.merge(user_config)
19
- end
11
+ def initialize(local_path: Dir.pwd)
12
+ @local_path = local_path
13
+ end
20
14
 
21
- private
15
+ def load
16
+ config_file = File.join(@local_path, "config.yml")
22
17
 
23
- def user_file
24
- File.join(Dir.pwd, FILE_NAME)
25
- end
18
+ YAML.load(File.read(config_file))
26
19
  end
27
20
  end
28
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dbdoc
2
4
  DBDOC_HOME = File.realpath(File.join(__dir__, "..", ".."))
3
5
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "fileutils"
5
+ require "dbdoc/constants"
6
+
7
+ module Dbdoc
8
+ # Dbdoc::FolderInitializer class knows how to turn an emtpy
9
+ # folder into a dbdoc folder.
10
+ #
11
+ class FolderInitializer
12
+ def initialize(local_path: Dir.pwd)
13
+ @config = Dbdoc::Config.new(local_path: local_path).load
14
+ end
15
+
16
+ def init
17
+ create_schema_folder
18
+ create_doc_folder
19
+ create_config_file
20
+ create_gitignore_file
21
+ create_confluence_config_file
22
+ end
23
+
24
+ private
25
+
26
+ # schema folder is the one user copies the schema.csv to
27
+ # before updating/generating documentation
28
+ def create_schema_folder
29
+ schema_folder = File.join(Dir.pwd, "schema")
30
+ Dir.mkdir(schema_folder) unless Dir.exist?(schema_folder)
31
+ end
32
+
33
+ # doc folder stores all the database documentation files
34
+ def create_doc_folder
35
+ doc_folder = File.join(Dir.pwd, "doc")
36
+ Dir.mkdir(doc_folder) unless Dir.exist?(doc_folder)
37
+ end
38
+
39
+ def create_file(default_file_name, target_file_name)
40
+ target_file = File.join(Dir.pwd, target_file_name)
41
+
42
+ return if File.exist?(target_file)
43
+
44
+ config_file = File.join(File.expand_path(__dir__), "../..", "config", default_file_name)
45
+
46
+ FileUtils.cp(config_file, target_file)
47
+ end
48
+
49
+ def create_config_file
50
+ create_file("default.yml", "config.yml")
51
+ end
52
+
53
+ def create_gitignore_file
54
+ create_file("gitignore.template", ".gitignore")
55
+ end
56
+
57
+ def create_confluence_config_file
58
+ create_file("confluence.yml", "confluence.yml")
59
+ end
60
+ end
61
+ end
@@ -1,31 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
4
+ require "erb"
5
+ require "fileutils"
2
6
  require "dbdoc/constants"
3
7
 
4
8
  module Dbdoc
9
+ # Dbdoc::Manager class manages database schema documentation.
10
+ #
11
+ # It knows how to generate and update documentation based on the database
12
+ # schema generated by the schema query for user's database.
5
13
  class Manager
6
- def initialize(config: {})
7
- @config = Dbdoc::Config.load.merge(config)
14
+ def initialize(local_path: Dir.pwd)
15
+ @local_path = local_path
16
+ @config = Dbdoc::Config.new(local_path: local_path).load
8
17
  end
9
18
 
10
- def plan(verbose: true)
11
- puts "--> PLAN"
12
- puts
13
- puts
14
-
15
- input_schema = read_input_schema.map { |r| r.first(4) }.map { |r| r.join(":") }
19
+ def plan
20
+ input_schema = read_input_schema.map { |r| r.first(4).join(":") }
16
21
  current_schema = read_documented_schema
17
22
 
18
- puts "--> New columns:"
19
- pp input_schema - current_schema
20
- puts
21
- puts
22
-
23
- puts "--> Columns to drop:"
24
- pp current_schema - input_schema
23
+ {
24
+ new_columns: input_schema - current_schema,
25
+ columns_to_drop: current_schema - input_schema
26
+ }
25
27
  end
26
28
 
27
29
  def todo
28
- doc_folder_files = File.join(Dir.pwd, "doc", "**/*")
30
+ doc_folder_files = File.join(@local_path, "doc", "**/*")
29
31
 
30
32
  Dir[doc_folder_files].each do |file|
31
33
  next if file == "."
@@ -33,16 +35,24 @@ module Dbdoc
33
35
  next if File.directory?(file)
34
36
 
35
37
  File.read(file).split("\n").each_with_index do |line, i|
36
- if line.include?("TODO")
37
- relative_path = file.gsub(Dir.pwd, "")
38
+ next unless line.include?("TODO")
38
39
 
39
- puts "#{relative_path}:#{i + 1}"
40
- end
40
+ relative_path = file.gsub(@local_path, "")
41
+
42
+ puts "#{relative_path}:#{i + 1}"
41
43
  end
42
44
  end
43
45
  end
44
46
 
45
- def apply(path: Dir.pwd, verbose: true)
47
+ def query
48
+ db_type = @config["db"]["type"]
49
+ query_file = File.join(File.expand_path(__dir__), "../..", "config", "schema_queries", "#{db_type}.sql")
50
+
51
+ File.read(query_file)
52
+ end
53
+
54
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
55
+ def apply
46
56
  puts "--> APPLY"
47
57
  puts
48
58
  puts
@@ -53,14 +63,16 @@ module Dbdoc
53
63
  added_columns = input_schema - current_schema
54
64
  dropped_columns = current_schema - input_schema
55
65
 
56
- doc_folder = File.join(Dir.pwd, "doc")
66
+ doc_folder = File.join(@local_path, "doc")
67
+
68
+ Dir.mkdir(doc_folder) unless Dir.exist?(doc_folder)
57
69
 
58
70
  ## DROP COLUMNS
59
71
  dropped_columns.each do |column|
60
- schema_name, table_name, column_name, column_type = column.split(":")
72
+ schema_name, table_name, column_name = column.split(":")
61
73
 
62
74
  columns_file = File.join(doc_folder, schema_name, table_name, "columns.yml")
63
- next unless File.exists?(columns_file)
75
+ next unless File.exist?(columns_file)
64
76
 
65
77
  columns = YAML.load(File.read(columns_file))
66
78
  columns.reject! { |c| c[:name] == column_name }
@@ -87,7 +99,7 @@ module Dbdoc
87
99
  next unless File.directory?(table_folder)
88
100
 
89
101
  columns_file = File.join(table_folder, "columns.yml")
90
- next unless File.exists?(columns_file)
102
+ next unless File.exist?(columns_file)
91
103
 
92
104
  columns = YAML.load(File.read(columns_file))
93
105
 
@@ -111,16 +123,18 @@ module Dbdoc
111
123
 
112
124
  create_new_columns(added_columns)
113
125
  end
126
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
114
127
 
115
128
  private
116
129
 
117
130
  def input_schema
118
- File.read(File.join(Dir.pwd, "schema", "schema.csv"))
131
+ File.read(File.join(@local_path, "schema", "schema.csv"))
119
132
  end
120
133
 
134
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
121
135
  def read_input_schema
122
136
  rows = input_schema.split("\n")
123
- with_header = rows[0].include?("schema_name")
137
+ with_header = rows[0].include?("table_schema")
124
138
 
125
139
  rows.shift if with_header
126
140
 
@@ -128,38 +142,37 @@ module Dbdoc
128
142
  r.split(",").map(&:strip).map { |c| c.gsub('"', "") }.first(5)
129
143
  end
130
144
 
131
- config = YAML.load(File.read("config.yml"))
132
-
133
- if @config["ignorelist"]
134
- @config["ignorelist"].map { |r| r.split(/[\.\#]/) }.each do |b|
135
- schema_pattern, table_pattern, column_pattern = b
136
-
137
- rows.reject! do |row|
138
- schema_name, table_name, column_name, _, _ = row
145
+ @config["ignorelist"]&.map { |r| r.split(/[\.\#]/) }&.each do |b|
146
+ schema_pattern, table_pattern, column_pattern = b
139
147
 
140
- if column_pattern
141
- next unless column_name =~ Regexp.new(column_pattern.gsub("*", ".*"))
142
- end
148
+ rows.reject! do |row|
149
+ schema_name, table_name, column_name, = row
143
150
 
144
- if table_pattern
145
- next unless table_name =~ Regexp.new(table_pattern.gsub("*", ".*"))
146
- end
151
+ if column_pattern
152
+ next unless column_name =~ Regexp.new(column_pattern.gsub("*", ".*"))
153
+ end
147
154
 
148
- if schema_pattern
149
- next unless schema_name =~ Regexp.new(schema_pattern.gsub("*", ".*"))
150
- end
155
+ if table_pattern
156
+ next unless table_name =~ Regexp.new(table_pattern.gsub("*", ".*"))
157
+ end
151
158
 
152
- true
159
+ if schema_pattern
160
+ next unless schema_name =~ Regexp.new(schema_pattern.gsub("*", ".*"))
153
161
  end
162
+
163
+ true
154
164
  end
155
165
  end
156
166
 
157
167
  rows
158
168
  end
169
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
159
170
 
171
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
160
172
  def read_documented_schema
161
- doc_folder = File.join(Dir.pwd, "doc")
173
+ doc_folder = File.join(@local_path, "doc")
162
174
 
175
+ return [] unless Dir.exist?(doc_folder)
163
176
  return [] if Dir.empty?(doc_folder)
164
177
 
165
178
  keys = []
@@ -178,9 +191,9 @@ module Dbdoc
178
191
  next unless File.directory?(table_folder)
179
192
 
180
193
  columns_file = File.join(table_folder, "columns.yml")
181
- next unless File.exists?(columns_file)
194
+ next unless File.exist?(columns_file)
182
195
 
183
- columns = YAML.load(File.read(columns_file))
196
+ columns = YAML.load(File.read(columns_file), [Symbol])
184
197
  columns.each do |column|
185
198
  keys.push([
186
199
  schema_name,
@@ -194,9 +207,11 @@ module Dbdoc
194
207
 
195
208
  keys
196
209
  end
210
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
197
211
 
212
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
198
213
  def create_new_columns(added_columns)
199
- doc_folder = File.join(Dir.pwd, "doc")
214
+ doc_folder = File.join(@local_path, "doc")
200
215
 
201
216
  added_columns.map! { |r| r.split(":") }
202
217
  new_columns = read_input_schema.select do |row|
@@ -242,17 +257,18 @@ module Dbdoc
242
257
  # 4. create table columns.yml
243
258
  columns_yaml = File.join(table_folder, "columns.yml")
244
259
 
245
- unless File.exists?(columns_yaml)
246
- columns_erb_tamplate_file = File.join(DBDOC_HOME, "doc_files", "columns.yml.erb")
247
- columns_yaml_template = ERB.new(File.read(columns_erb_tamplate_file), nil, "-")
248
- File.open(columns_yaml, "w") do |f|
249
- f.puts columns_yaml_template.result_with_hash({
250
- columns: columns
251
- })
252
- end
260
+ next if File.exist?(columns_yaml)
261
+
262
+ columns_erb_tamplate_file = File.join(DBDOC_HOME, "doc_files", "columns.yml.erb")
263
+ columns_yaml_template = ERB.new(File.read(columns_erb_tamplate_file), nil, "-")
264
+ File.open(columns_yaml, "w") do |f|
265
+ f.puts columns_yaml_template.result_with_hash({
266
+ columns: columns
267
+ })
253
268
  end
254
269
  end
255
270
  end
256
271
  end
272
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
257
273
  end
258
274
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dbdoc
2
- VERSION = "0.2.0".freeze
4
+ VERSION = "0.3.1"
3
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbdoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anatoli Makarevich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-02 00:00:00.000000000 Z
11
+ date: 2020-08-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Dbdoc is a tool to keep your database documentation up-to-date and version
14
14
  controlled.
@@ -45,12 +45,13 @@ files:
45
45
  - doc_files/table_example.md
46
46
  - lib/confluence/api.rb
47
47
  - lib/confluence/markdown_converter.rb
48
+ - lib/confluence/uploader.rb
48
49
  - lib/dbdoc.rb
49
50
  - lib/dbdoc/cli.rb
50
51
  - lib/dbdoc/config.rb
51
52
  - lib/dbdoc/constants.rb
53
+ - lib/dbdoc/folder_initializer.rb
52
54
  - lib/dbdoc/manager.rb
53
- - lib/dbdoc/uploader.rb
54
55
  - lib/dbdoc/version.rb
55
56
  homepage: https://github.com/sqlhabit/dbdoc
56
57
  licenses: