Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] S3 strategy #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.gem
/.bundle/
/.yardoc
/Gemfile.lock
Expand Down
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,22 @@

**Important:** this gem is not production ready.

This is the code that orchestrates Zipmark's automatically generated
documentation and its publication.
## The problem

You have systems that change and their documentation gets
outdated because they are maintaned manually.

**The solution**

DocOrchestra attempts to help mitigate that problem with several
functionalities. This is the roadmap

* automate document generation (e.g [rspec_api_documentation](https://github.com/zipmark/rspec_api_documentation) )
* automate linting of the document files (e.g [linter-api-blueprint](https://github.com/zdne/linter-api-blueprint)
* automate testing the documentation against real APIs (e.g [dredd](https://github.com/apiaryio/dredd))
* automate concatenating multiple documentation files into one (e.g microservirces)
* automate generating [API Elements](http://api-elements.readthedocs.io/en/latest/)
* automate publishing the documentation to the cloud (e.g S3)

## Installation

Expand All @@ -19,9 +33,14 @@ And then execute:

## Usage

Pending
Running this tool requires specifying a few options via ENV variables, like
the following:

```
DOC_PATH=./docs/main.apib DOC_STORAGE=s3 doc_orchestra sync
```

## Development
See [Getting Started](/docs/getting_started.md) for details.

## Contributing

Expand Down
5 changes: 5 additions & 0 deletions bin/doc_orchestra
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env ruby
require "bundler/setup"
require "doc_orchestra"

DocOrchestra.run
2 changes: 2 additions & 0 deletions doc_orchestra.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_dependency "aws-sdk", "~> 2.6"

spec.add_development_dependency "bundler", "~> 1.13"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.5"
Expand Down
26 changes: 26 additions & 0 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Getting Started

[WIP]

Each one of these steps will depend on the orchestration strategies chosen.
These are the strategies that can be defined:

* `DOC_FORMAT`: depending on this value, specific linting and testing tools
will be used. For instance, in a project with API Blueprint,
`DOC_FORMAT=apib` will define usage of `dredd` as testing tool.
* `DOC_STORAGE`: where will
will be used. For instance, in a project with API Blueprint,
`DOC_FORMAT=apib` will define usage of `dredd` as testing tool.


### Options

These are the options that can be defined. For details on how

* `DOC_FORMAT` (required, string): defines the format of the documentation.
Accepted values are: `apib` (APIBlueprint).
* `DOC_STORAGE` (required, string): defines where the documentation will be stored.
Accepted values are: `s3` (APIBlueprint).
* `DOC_ELEMENTS` (int): `1` to convert docs to
[API Elements](http://api-elements.readthedocs.io/en/latest/). Defaults to
`0`.
11 changes: 11 additions & 0 deletions lib/doc_orchestra.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
require "doc_orchestra/version"
require "doc_orchestra/configuration"
require "doc_orchestra/log"
require "doc_orchestra/strategy"
require "doc_orchestra/strategies/storage"
require "doc_orchestra/strategies/storages/s3"

module DocOrchestra
def self.run(env = ENV)
@config = Configuration.new(env)

@strategy = Strategy.new(@config)
@strategy.orchestrate
end
end
42 changes: 42 additions & 0 deletions lib/doc_orchestra/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module DocOrchestra
class Configuration
class UnexpectedConfiguration < StandardError; end
class MissingConfiguration < StandardError; end

def initialize(env)
@env = env
@dictionary = {}
end

def [](key)
if @env[key] != ""
@env[key]
end
end

def required_keys(*keys)
keys.each do |key|
if blank_value?(@env[key])
raise MissingConfiguration, "The following environment variables are missing: #{key}"
end
end
end

def required_values(key, *values)
required_keys(key)
unless values.include?(self[key])
raise UnexpectedConfiguration, "Environment variable #{key} accepted values are: #{values.join(", ")} (#{self[key]} provided). #{help_url}"
end
end

private

def blank_value?(str)
str.nil? || str == ""
end

def help_url
"See https://github.com/zipmark/doc_orchestra for details."
end
end
end
7 changes: 7 additions & 0 deletions lib/doc_orchestra/log.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module DocOrchestra
class Log
def self.out(str)
puts str
end
end
end
19 changes: 19 additions & 0 deletions lib/doc_orchestra/strategies/format/apib.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module DocOrchestra
module Strategies
module FileFormat
class Apib
def initialize(options)
@options = options
end

def method

end

private

attr_reader :options
end
end
end
end
7 changes: 7 additions & 0 deletions lib/doc_orchestra/strategies/storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module DocOrchestra
module Strategies
class Storage

end
end
end
47 changes: 47 additions & 0 deletions lib/doc_orchestra/strategies/storages/s3.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require 'aws-sdk'

module DocOrchestra
module Strategies
module Storages
class S3
REQUIRED_CONFIG = [
"STORAGE_KEY", "STORAGE_SECRET", "STORAGE_BUCKET"
]

def initialize(config:, region: 'us-west-2')
config.required_keys(*REQUIRED_CONFIG)
@key = config["STORAGE_KEY"]
@secret = config["STORAGE_SECRET"]
@bucket = config["STORAGE_BUCKET"]
@region = config["STORAGE_REGION"] || region
end

def upload
setup_credentials
create_bucket
end

private

def setup_credentials
Aws.config.update(
region: @region,
credentials: credentials
)
end

def credentials
Aws::Credentials.new(@key, @secret)
end

def create_bucket
s3 = Aws::S3::Resource.new
s3.bucket(@bucket).create
Log.out("Creating bucket '#{@bucket}'... done.")
rescue Aws::S3::Errors::BucketAlreadyExists, Aws::S3::Errors::BucketAlreadyOwnedByYou
Log.out("Bucket '#{@bucket}' already exists.")
end
end
end
end
end
18 changes: 18 additions & 0 deletions lib/doc_orchestra/strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module DocOrchestra
class Strategy
def initialize(config)
config.required_values("DOC_STORAGE", "s3")
@config = config
end

def orchestrate
storage.upload
end

private

def storage
Strategies::Storages::S3.new(config: @config)
end
end
end
77 changes: 77 additions & 0 deletions spec/doc_orchestra/configuration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
require "spec_helper"

describe DocOrchestra::Configuration do
let(:env) do
{
"DOC_STORAGE" => "s3",
"CUSTOM_KEY" => "custom value",
"BLANK_STRING" => "",
}
end

subject(:config) { described_class.new(env) }

describe "#required_keys" do
context 'when no key is missing' do
it 'does not raise errors' do
expect {
config.required_keys("CUSTOM_KEY", "DOC_STORAGE")
}.to_not raise_error
end
end

context 'when one key is not defined' do
it 'raises an error' do
expect {
config.required_keys("MISSING_KEY", "DOC_STORAGE")
}.to raise_error described_class::MissingConfiguration
end
end
end

describe '#[]' do
context 'value exists' do
it 'returns an env var value' do
expect(config["CUSTOM_KEY"]).to eq "custom value"
end
end

context 'value is a blank string' do
it 'returns nil' do
expect(config["BLANK_STRING"]).to eq nil
end
end

context 'value does not exist' do
it 'returns nil' do
expect(config["NO_KEY"]).to eq nil
end
end
end

describe '#required_values' do
context 'a value is incorrect' do
it 'raises' do
expect {
config.required_values("DOC_STORAGE", "s4", "s5")
}.to raise_error described_class::UnexpectedConfiguration
end
end

context 'the key does not exist' do
it 'raises' do
expect {
config.required_values("NO_KEY", "s3")
}.to raise_error described_class::MissingConfiguration
end
end

context 'a value is incorrect' do
it 'raises' do
expect {
config.required_values("DOC_STORAGE", "s3")
}.to_not raise_error
end
end
end
end
14 changes: 14 additions & 0 deletions spec/doc_orchestra/strategies/storages/s3_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require "doc_orchestra/strategies/storages/s3"

describe DocOrchestra::Strategies::Storages::S3 do
let(:item) { double }

subject { described_class.new(item) }

describe "#upload" do
it "returns true" do
subject.method

end
end
end
1 change: 1 addition & 0 deletions spec/fixtures/documents/main.apib
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# My documentation
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
require "doc_orchestra"
require 'pry'
require 'awesome_print'