dbdoc 0.2.0 → 0.3.1

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.
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: