sync_readme 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.
@@ -0,0 +1,81 @@
1
+ # SyncReadme
2
+
3
+ `sync_readme` is a gem designed to help you synchronize a readme between a repository and a confluence wiki page. The idea is that on merge to master, you can run the sync to take docs FROM the readme and put them in the confluence page.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ``` ruby
10
+ gem 'sync_readme'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install sync_readme
20
+
21
+ Then set up a .sync_readme.yml file
22
+
23
+ ``` yaml
24
+ default: readme # optional if not set, default runs all configurations
25
+
26
+ readme:
27
+ url: http://confluence.url.here # required
28
+ page_id: 123456 # required
29
+ filename: Readme.md # required
30
+ username: foo # optional, generally better as an environment variable
31
+ password: bar # optional, generally better as an environment variable
32
+ notice: this file is sync'd! # optional, adds the notice (as html) to the top of the confluance docs
33
+ strip_title: false # optional, defaults false, strips the first h1 (#) tag from the file
34
+ syntax_highlighting: true # optional, defaults true, uses coderay sytax highlighting on code blocks
35
+ ```
36
+
37
+ You'll also need to set environment variables with credentials to update the page in question:
38
+
39
+ ```
40
+ CONFLUENCE_USERNAME=jsmith
41
+ CONFLUENCE_PASSWORD=$UPER $ECURE PA$$WORD
42
+ ```
43
+
44
+ ## Usage
45
+ ```
46
+ sync_readme [configuration]
47
+ ```
48
+
49
+ ## Adding to Gitlab-CI
50
+
51
+ 1. Create a confluence user specifically to sync with
52
+ 2. If you haven't already, create the pages you want to sync to on confluence and get their IDs.
53
+ 3. Create your `.sync_readme.yml` file like the one above (or see the example)
54
+ 4. Add `gem 'sync_readme'` to your apps gemfile
55
+ 5. Set `CONFLUENCE_USERNAME` and `CONFLUENCE_PASSWORD` as CI Variables.
56
+ 6. Add the following job to your .gitlab-ci.yml
57
+ ``` yaml
58
+ Sync To Confluence:
59
+ stage: update_docs # Replace that with the stage you want this to run
60
+ only: master # Only run on master branch probably after you deploy
61
+ script:
62
+ - bundle exec sync_readme --all # Alternately just the profile you want to run
63
+ ```
64
+
65
+ ## Development
66
+
67
+ Set up a copy of ruby 2.3.1 (We suggest rbenv)
68
+
69
+ `bundle install`
70
+
71
+ ## Running Tests
72
+
73
+ `bundle exec rspec`
74
+
75
+ ## Contributing
76
+
77
+ Contributions are welcome as long as they contain tests for the behaviors added or changed.
78
+
79
+ ## License
80
+
81
+ The gem is available as open source under the terms of the [BSD-3-Clause](http://opensource.org/licenses/BSD-3-Clause).
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sync_readme'
4
+ SyncReadme.invoke(ARGV)
@@ -0,0 +1,40 @@
1
+ require 'sync_readme/config'
2
+ require 'sync_readme/confluence_sync'
3
+ require 'sync_readme/reader'
4
+ require 'sync_readme/version'
5
+ require 'optparse'
6
+ require 'dotenv'
7
+
8
+ Dotenv.load
9
+
10
+ module SyncReadme
11
+ def self.invoke(args)
12
+ options = {}
13
+ OptionParser.new do |opts|
14
+ opts.banner = "Usage: sync_readme [options] [profile]"
15
+
16
+ opts.on("-a", "--all", "Run verbosely") do
17
+ options[:all] = true
18
+ end
19
+ end.parse!(args)
20
+
21
+ default_profile = SyncReadme::Config.default
22
+
23
+ if options[:all] || (args.empty? && default_profile.nil?)
24
+ SyncReadme::Config.profiles.each do |profile|
25
+ SyncReadme.perform(profile)
26
+ end
27
+ elsif args.empty?
28
+ SyncReadme.perform(default_profile)
29
+ else
30
+ SyncReadme.perform(args.last)
31
+ end
32
+ end
33
+
34
+ def self.perform(profile)
35
+ config = SyncReadme::Config.new(profile)
36
+ content = SyncReadme::Reader.new(config).html
37
+ sync = SyncReadme::ConfluenceSync.new(config)
38
+ sync.update_page_content(content)
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ require 'yaml'
2
+
3
+ module SyncReadme
4
+ class Config
5
+ DEFAULT_CONFIG_FILE = File.join(Dir.pwd, '.sync_readme.yml')
6
+ NO_CONFIGURATION_ERROR = "this profile has not been configured, please add it to #{DEFAULT_CONFIG_FILE}".freeze
7
+
8
+ def self.profiles(config_file = DEFAULT_CONFIG_FILE)
9
+ YAML.load_file(config_file).keys.select { |key| key != 'default' }
10
+ end
11
+
12
+ def self.default(config_file = DEFAULT_CONFIG_FILE)
13
+ default = YAML.load_file(config_file)['default']
14
+ unless default
15
+ profiles = SyncReadme::Config.profiles(config_file)
16
+ return profiles[0] unless profiles.empty? || profiles[1]
17
+ raise NO_CONFIGURATION_ERROR if profiles.empty?
18
+ end
19
+ default
20
+ end
21
+
22
+ def initialize(profile, config_file = DEFAULT_CONFIG_FILE)
23
+ @raw_config = YAML.load_file(config_file)[profile]
24
+ raise NO_CONFIGURATION_ERROR unless @raw_config
25
+ end
26
+
27
+ def url
28
+ @raw_config['url']
29
+ end
30
+
31
+ def username
32
+ ENV['CONFLUENCE_USERNAME'] || @raw_config['username']
33
+ end
34
+
35
+ def notice
36
+ @raw_config['notice']
37
+ end
38
+
39
+ def password
40
+ ENV['CONFLUENCE_PASSWORD'] || @raw_config['password']
41
+ end
42
+
43
+ def page_id
44
+ @raw_config['page_id']
45
+ end
46
+
47
+ def filename
48
+ @raw_config['filename']
49
+ end
50
+
51
+ def strip_title?
52
+ @raw_config['strip_title'].nil? ? false : @raw_config['strip_title']
53
+ end
54
+
55
+ def syntax_highlighting?
56
+ @raw_config['syntax_highlighting'].nil? ? true : @raw_config['syntax_highlighting']
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,55 @@
1
+ require 'json'
2
+ require 'faraday'
3
+
4
+ module SyncReadme
5
+ class ConfluenceSync
6
+ def initialize(config)
7
+ @page_id = config.page_id
8
+ @client = Faraday.new(url: config.url) do |faraday|
9
+ faraday.request :url_encoded
10
+ # faraday.response :logger # log requests to STDOUT
11
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
12
+ faraday.basic_auth(config.username, config.password)
13
+ end
14
+ end
15
+
16
+ def update_page_content(content)
17
+ page = get_page
18
+ update(updated_page_params(page, content))
19
+ end
20
+
21
+ def get_page
22
+ response = @client.get("/rest/api/content/#{@page_id}", expand: 'body.view,version')
23
+ JSON.parse(response.body)
24
+ end
25
+
26
+ def update(params)
27
+ @client.put do |request|
28
+ request.url "/rest/api/content/#{@page_id}"
29
+ request.headers['Content-Type'] = 'application/json'
30
+ request.body = params.to_json
31
+ end
32
+ end
33
+
34
+ def updated_page_params(page, new_content)
35
+ {
36
+ version: {
37
+ number: increment_version(page),
38
+ minorEdit: true
39
+ },
40
+ title: page['title'],
41
+ type: 'page',
42
+ body: {
43
+ storage: {
44
+ value: new_content,
45
+ representation: 'storage'
46
+ }
47
+ }
48
+ }
49
+ end
50
+
51
+ def increment_version(page)
52
+ page['version']['number'] + 1
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,28 @@
1
+ require 'kramdown'
2
+
3
+ module SyncReadme
4
+ class Reader
5
+ def initialize(config)
6
+ @file_contents = File.read(config.filename)
7
+ @notice = config.notice
8
+ @strip_title = config.strip_title?
9
+ @highlighter = config.syntax_highlighting? ? 'coderay' : nil
10
+ end
11
+
12
+ def html
13
+ markdown = @file_contents
14
+ markdown.sub!(/# .*\n/, '') if @strip_title
15
+ options = {
16
+ input: 'GFM',
17
+ syntax_highlighter: @highlighter,
18
+ syntax_highlighter_opts: {
19
+ css: 'style',
20
+ line_numbers: 'table'
21
+ }
22
+ }
23
+ value = Kramdown::Document.new(markdown, options).to_html
24
+ value = "#{@notice}#{value}" if @notice
25
+ value
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module SyncReadme
2
+ VERSION = '1.0.0'.freeze
3
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sync_readme/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'sync_readme'
8
+ spec.version = SyncReadme::VERSION
9
+ spec.authors = ['Alex Ives']
10
+ spec.email = ['alex.ives@govdelivery.com']
11
+
12
+ spec.summary = 'Syncs markdown files with confluence'
13
+ spec.description = 'Converts markdown files and synchronizes them with confluence pages'
14
+ spec.homepage = 'https://github.com/govdelivery/sync_readme'
15
+ spec.license = 'BSD-3-Clause'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'faraday', '~> 0.11'
23
+ spec.add_dependency 'kramdown', '~> 1.13'
24
+ spec.add_dependency 'dotenv', '~> 2.1.2'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.12'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.0'
29
+ spec.add_development_dependency 'rubocop', '~> 0.47'
30
+ spec.add_development_dependency 'pry', '~> 0.10.4'
31
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sync_readme
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Ives
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-02-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.11'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: kramdown
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.13'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.13'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dotenv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.1.2
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.1.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.47'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.47'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.10.4
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.10.4
125
+ description: Converts markdown files and synchronizes them with confluence pages
126
+ email:
127
+ - alex.ives@govdelivery.com
128
+ executables:
129
+ - sync_readme
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".gitignore"
134
+ - ".gitlab-ci.yml"
135
+ - ".rspec"
136
+ - ".rubocop.yml"
137
+ - ".ruby-version"
138
+ - ".sync_readme.example.yml"
139
+ - CODE_OF_CONDUCT.md
140
+ - Gemfile
141
+ - LICENSE
142
+ - README.md
143
+ - Rakefile
144
+ - exe/sync_readme
145
+ - lib/sync_readme.rb
146
+ - lib/sync_readme/config.rb
147
+ - lib/sync_readme/confluence_sync.rb
148
+ - lib/sync_readme/reader.rb
149
+ - lib/sync_readme/version.rb
150
+ - sync_readme.gemspec
151
+ homepage: https://github.com/govdelivery/sync_readme
152
+ licenses:
153
+ - BSD-3-Clause
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.5.1
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Syncs markdown files with confluence
175
+ test_files: []