Skip to content
This repository has been archived by the owner on Apr 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #24 from shantytown/18-artifact-types
Browse files Browse the repository at this point in the history
Artifact types
  • Loading branch information
nathankleyn committed Sep 28, 2015
2 parents 41b8173 + ad4a2de commit 78ffb89
Show file tree
Hide file tree
Showing 15 changed files with 181 additions and 29 deletions.
56 changes: 56 additions & 0 deletions lib/shanty/artifact.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'uri'
require 'pathname'

module Shanty
# Public: Contain information on an artifact published by a project
class Artifact
attr_reader :file_extension, :plugin, :uri

# Public: Initialise an artifact instance.
#
# file_extension - The extension of the artifact.
# plugin - The plugin publishing the artifact.
# uri - The URI to the object.
#
# Fails if the URI is not absolute or a scheme is missing.
def initialize(file_extension, plugin, uri)
@file_extension = file_extension
@plugin = plugin
@uri = uri

validate_uri
end

# Public: Whether the underlying URI of the artifact points to a local
# file path.
#
# Returns a Boolean representing whether the artifact is local.
def local?
@uri.scheme == 'file'
end

# Public: If the underlying artifact is stored locally, returns the path
# at which the artifact can be found.
#
# Returns a String representing the path at which the artifact can be found.
# Raises RuntimeError if the artifact is not local.
def to_local_path
return @uri.path if local?
fail 'URI is not a local resource'
end

# Public: A simple string representation of this artifact.
#
# Returns a String representing the URI at which this artifact can be found.
def to_s
@uri.to_s
end

private

def validate_uri
fail 'Scheme not present on URI' unless @uri.absolute?
fail 'URI is not absolute' if @uri.path.nil?
end
end
end
4 changes: 4 additions & 0 deletions lib/shanty/plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def projects
end
end

def artifacts(_)
[]
end

def with_graph(graph)
callbacks = self.class.instance_variable_get(:@with_graph_callbacks)
return [] if callbacks.nil? || callbacks.empty?
Expand Down
2 changes: 1 addition & 1 deletion lib/shanty/plugins/bundler_plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class BundlerPlugin < Plugin
projects '**/Gemfile'
subscribe :build, :bundle_install

def bundle_install
def bundle_install(_)
Bundler.with_clean_env do
# FIXME: Add support for the --jobs argument to parallelise the bundler run.
system 'bundle install --quiet'
Expand Down
2 changes: 1 addition & 1 deletion lib/shanty/plugins/cucumber_plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def cucumber_projects
end
end

def cucumber
def cucumber(_)
system 'cucumber'
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/shanty/plugins/rspec_plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def rspec_projects
end
end

def rspec
def rspec(_)
system 'rspec'
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/shanty/plugins/rubocop_plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class RubocopPlugin < Plugin
projects '**/.rubocop.yml'
subscribe :test, :rubocop

def rubocop
def rubocop(_)
system 'rubocop'
end
end
Expand Down
26 changes: 24 additions & 2 deletions lib/shanty/plugins/rubygem_plugin.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
require 'shanty/plugin'
require 'shanty/artifact'

module Shanty
# Public: Rubygem plugin for buildin gems.
class RubygemPlugin < Plugin
ARTIFACT_EXTENSION = 'gem'

tags :rubygem
projects '**/*.gemspec'
subscribe :build, :build_gem

def build_gem
system 'gem build *.gemspec'
def build_gem(project)
gemspec_files(project).each do |file|
system "gem build #{file}"
end
end

def artifacts(project)
gemspec_files(project).flat_map do |file|
gemspec = Gem::Specification.load(file)
Artifact.new(
ARTIFACT_EXTENSION,
'rubygem',
URI("file://#{project.path}/#{gemspec.name}-#{gemspec.version}.#{ARTIFACT_EXTENSION}")
)
end
end

private

def gemspec_files(project)
@gemspec_files ||= project_tree.glob(File.join(project.path, '*.gemspec'))
end
end
end
21 changes: 11 additions & 10 deletions lib/shanty/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Project
include ActsAsGraphVertex
include Env

attr_accessor :name, :path, :tags, :options
attr_accessor :artifacts, :name, :path, :tags, :options

# Multiton or Flyweight pattern - only allow once instance per unique path.
#
Expand Down Expand Up @@ -40,6 +40,7 @@ def initialize(path)
@path = path

@name = File.basename(path)
@artifacts = []
@plugins = []
@tags = []
@options = {}
Expand All @@ -61,22 +62,22 @@ def all_tags
(@tags + @plugins.flat_map { |plugin| plugin.class.tags }).map(&:to_sym).uniq
end

# Public: The artifacts published by this project and any artifacts published
# by any plugins operating on this project.
#
# Returns the Array of Artifacts available for this project.
def all_artifacts
(@artifacts + @plugins.flat_map { |plugin| plugin.artifacts(project) }).uniq
end

def publish(name, *args)
@plugins.each do |plugin|
next unless plugin.subscribed?(name)
logger.info("Executing #{name} on the #{plugin.class} plugin...")
return false if plugin.publish(name, *args) == false
return false if plugin.publish(name, self, *args) == false
end
end

# Public: The absolute paths to the artifacts that would be created by this
# project when built, if any. This is expected to be overriden in subclasses.
#
# Returns an Array of Strings representing the absolute paths to the artifacts.
def artifact_paths
[]
end

# Public: Overriden String conversion method to return a simplified
# representation of this instance that doesn't include the cyclic
# parent/children attributes as defined by the ActsAsGraphVertex mixin.
Expand Down
44 changes: 44 additions & 0 deletions spec/lib/shanty/artifact_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'shanty/artifact'

# All classes referenced belong to the shanty project
module Shanty
RSpec.describe(Artifact) do
subject { described_class.new('html', 'test', uri) }
let(:relative_path_artifact) { described_class.new('html', 'test', URI('file:kim/cage.html')) }
let(:http_artifact) { described_class.new('html', 'test', URI('http://www.nic.com/kim/cage.html')) }
let(:schemless_artifact) { described_class.new('html', 'test', URI('kim/cage.html')) }

let(:uri) { URI('file:///nic/kim/cage.html') }

describe('.new') do
it('fails if the URI is not an absolute path') do
expect { relative_path_artifact }.to raise_error('URI is not absolute')
end

it('fails if there is no scheme present in the URI') do
expect { schemless_artifact }.to raise_error('Scheme not present on URI')
end
end

describe('#local?') do
it('returns false if the file is not a local file') do
expect(http_artifact.local?).to be(false)
end

it('returns true if the file is a local file') do
expect(subject.local?).to be(true)
end
end

describe('#to_local_path') do
it('throws an exception if the resource is not local') do
allow(subject).to receive(:local?).and_return(false)
expect { subject.to_local_path }.to raise_error('URI is not a local resource')
end

it('returns the path if the resource is local') do
expect(subject.to_local_path).to eql('/nic/kim/cage.html')
end
end
end
end
4 changes: 2 additions & 2 deletions spec/lib/shanty/plugins/bundler_plugin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# All classes referenced belong to the shanty project
module Shanty
RSpec.describe(BundlerPlugin) do
include_context('basics')
include_context('graph')

it('adds the bundler tag') do
expect(described_class).to add_tags(:bundler)
Expand All @@ -22,7 +22,7 @@ module Shanty
it('calls bundler install') do
expect(subject).to receive(:system).with('bundle install --quiet')

subject.bundle_install
subject.bundle_install(project)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/shanty/plugins/cucumber_plugin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ module Shanty
it('calls cucumber') do
expect(subject).to receive(:system).with('cucumber')

subject.cucumber
subject.cucumber(project)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/shanty/plugins/rspec_plugin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module Shanty
it('calls rspec') do
expect(subject).to receive(:system).with('rspec')

subject.rspec
subject.rspec(project)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/lib/shanty/plugins/rubocop_plugin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# All classes referenced belong to the shanty project
module Shanty
RSpec.describe(RubocopPlugin) do
include_context('basics')
include_context('graph')

it('adds the rubocop tag') do
expect(described_class).to add_tags(:rubocop)
Expand All @@ -22,7 +22,7 @@ module Shanty
it('calls rubocop') do
expect(subject).to receive(:system).with('rubocop')

subject.rubocop
subject.rubocop(project)
end
end
end
Expand Down
31 changes: 28 additions & 3 deletions spec/lib/shanty/plugins/rubygem_plugin_spec.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
require 'spec_helper'
require 'fileutils'
require 'shanty/plugins/rubygem_plugin'

# All classes referenced belong to the shanty project
module Shanty
RSpec.describe(RubygemPlugin) do
include_context('basics')
include_context('graph')
let(:gemspec_path) { File.join(project_path, 'foo.gemspec') }

before do
File.write(gemspec_path, <<-eof)
Gem::Specification.new do |gem|
gem.name = 'foo'
gem.version = '1.2.3'
end
eof
end

it('adds the rubygem tag') do
expect(described_class).to add_tags(:rubygem)
Expand All @@ -20,9 +31,23 @@ module Shanty

describe('#build_gem') do
it('calls gem build') do
expect(subject).to receive(:system).with('gem build *.gemspec')
expect(subject).to receive(:system).with("gem build #{gemspec_path}")

subject.build_gem(project)
end
end

describe('#artifacts') do
let(:gem_path) { File.join(project_path, 'foo-1.2.3.gem') }

it('lists the project artifacts') do
result = subject.artifacts(project)

subject.build_gem
expect(result.length).to eql(1)
expect(result.first.to_local_path).to eql(gem_path)
expect(result.first.file_extension).to eql('gem')
expect(result.first.local?).to be true
expect(result.first.uri.scheme).to eql('file')
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions spec/lib/shanty/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ module Shanty
it('publishes the event on any listening plugins') do
allow(plugin).to receive(:subscribed?).and_return(true)

expect(plugin).to receive(:publish).with(:foo, :bar, :lux)
expect(plugin).to receive(:publish).with(:foo, subject, :bar, :lux)

subject.publish(:foo, :bar, :lux)
end
Expand All @@ -84,9 +84,9 @@ module Shanty
end
end

describe('#artifact_paths') do
it('defaults the paths to an empty array') do
expect(subject.artifact_paths).to eql([])
describe('#all_artifacts') do
it('defaults the artifacts to an empty array') do
expect(subject.all_artifacts).to eql([])
end
end

Expand Down

0 comments on commit 78ffb89

Please sign in to comment.