M .ruby-version +1 -1
M Gemfile.devel +2 -0
@@ 3,3 3,5 @@ gemspec
gem 'hglib', path: '../hglib'
gem 'cztop-reactor', path: '../CZTop-Reactor'
+gem 'pry'
+
M README.md +12 -13
@@ 127,29 127,28 @@ Now you can start the worker, which will
Now we need our repositories to notify the assembly server when events occur.
We'll hook up a Mercurial repo for a Ruby library so that it runs unit tests
whenever there's a new commit. First we'll install assemblage and the Mercurial
-client library on the repo server and create a run directory for repo
-operations:
+client library on the repo server and create a publisher for repo operations:
user@example-repo $ sudo gem install assemblage hglib
user@example-repo $ mkdir /usr/local/hg/repos/.assemblage
user@example-repo $ cd /usr/local/hg/repos/.assemblage
- user@example-repo $ assemblage repo setup project1
- Setting up a new assemblage repo config directory in
+ user@example-repo $ assemblage publisher setup
+ Setting up a new assemblage publisher config directory in
/usr/local/hg/repos/.assemblage...
- Set up with repo name: project1
- Client public key is:
+ Publisher public key is:
bq9VheQbLtcu]LGK4I&xzK3^UW0Iyak/6<YS=^$w
done.
-Now we'll need to register the repo on the server like we did before for the
-worker:
+Now we'll need to register the publisher on the server like we did before for
+the worker:
+
+ user@example $ assemblage publisher add \
+ 'bq9VheQbLtcu]LGK4I&xzK3^UW0Iyak/6<YS=^$w'
+ Accepting publisher events from pub-example-com-0a44fe...
+ done.
user@example $ assemblage repo add --type=hg project1 \
- 'bq9VheQbLtcu]LGK4I&xzK3^UW0Iyak/6<YS=^$w' \
- http://repo.example.com/project1
- Looking for repo registration... found.
- Approving repo events from http://repo.example.com/project1...
- done.
+ http://repo.example.com/project1
We'll add a hook to the repository's .hg/hgrc that looks like:
M lib/assemblage.rb +15 -0
@@ 1,6 1,8 @@
# -*- ruby -*-
#encoding: utf-8
+require 'securerandom'
+require 'socket'
require 'set'
require 'loggability'
require 'configurability'
@@ 46,9 48,11 @@ module Assemblage
autoload :CLI, 'assemblage/cli'
autoload :DbObject, 'assemblage/db_object'
autoload :Protocol, 'assemblage/protocol'
+ autoload :Publisher, 'assemblage/publisher'
autoload :Repository, 'assemblage/repository'
autoload :Server, 'assemblage/server'
autoload :Worker, 'assemblage/worker'
+ autoload :VCSStrategy, 'assemblage/vcs_strategy'
require 'assemblage/mixins'
@@ 140,5 144,16 @@ module Assemblage
end
+ ### Generate a unique name prefixed with +noun+ to use as an ID for a new
+ ### publisher, worker, etc.
+ def self::make_unique_id( noun )
+ raw = [
+ noun,
+ Socket.gethostname.split('.').first.downcase,
+ SecureRandom.hex( 8 )
+ ].join( '-' )
+ return raw.gsub( /[^\w\-]+/, '-' ).squeeze( '-' )
+ end
+
end # module Assemblage
A => lib/assemblage/command/publisher.rb +103 -0
@@ 0,0 1,103 @@
+# -*- ruby -*-
+# frozen_string_literal: true
+
+require 'pathname'
+require 'assemblage/cli' unless defined?( Assemblage::CLI )
+
+
+# Assemblage Publisher commands
+module Assemblage::CLI::PublisherCommand
+ extend Assemblage::CLI::Subcommand
+
+
+ SETUP_ADVICE = %{
+ Now you can tell a server to accept repository events published from this host
+ like so:
+ assemblage server add-publisher %{name} '%{public_key}' <server_directory>
+
+ You can use this publisher to publish events from a Mercurial repository
+ by adding a hook:
+
+ [hooks]
+ incoming.myrepo = assemblage -c %{directory}/config.yml publish commit %{name} $HG_NODE
+
+ }.gsub( /^\t+/, '' )
+
+
+ desc "Publisher commands"
+ command :publisher do |publisher|
+
+ publisher.desc 'Set up a new repo event publisher run directory'
+ publisher.long_desc <<-END_DESC
+ Set up a new run directory for hooks that run in one or more repositories.
+ This is how the commit (or other) hook authenticates to the server when
+ it runs.
+ END_DESC
+ publisher.arg :NAME
+ publisher.arg :DIRECTORY
+ publisher.command :setup do |setup|
+
+ setup.action do |globals, options, args|
+ name = args.shift or help_now!( "No name specified.", 64 )
+ directory = Pathname( args.shift || '.' ).expand_path
+ name = options.name
+
+ prompt.say "Creating a publisher run directory in %s..." % [ directory ]
+ Assemblage::Publisher.setup_run_directory( directory )
+
+ prompt.say "Generating a publisher key..."
+ Assemblage::Publisher.generate_cert
+
+ msg = SETUP_ADVICE % {
+ public_key: Assemblage::Publisher.public_key,
+ directory: directory,
+ name: name
+ }
+ prompt.say( msg )
+ end
+ end
+
+
+ publisher.desc "Output the publisher's public key"
+ publisher.long_desc <<-END_DESC
+ Output the publisher's public key to STDOUT.
+ END_DESC
+ publisher.arg :DIRECTORY, :optional
+ publisher.command 'show-key' do |show_key|
+ show_key.action do |globals, options, args|
+ directory = Pathname( args.shift || '.' ).expand_path
+
+ Assemblage.use_run_directory( directory )
+ prompt.say "Worker's public key:"
+ puts Assemblage::Publisher.public_key
+ end
+ end
+
+
+ publisher.desc "Add a server key to a publisher config"
+ publisher.long_desc <<-END_DESC
+ Add the specified PUBLIC_KEY for a server named NAME to the server config
+ in SERVER_DIRECTORY.
+ END_DESC
+ publisher.arg :ENDPOINT
+ publisher.arg :PUBLIC_KEY
+ publisher.arg :DIRECTORY, :optional
+ publisher.command 'add-server' do |add|
+
+ add.action do |globals, options, args|
+ endpoint = args.shift or help_now!( "Missing the endpoint." )
+ public_key = args.shift or help_now!( "Missing the server public key." )
+
+ Assemblage.use_run_directory( args.shift )
+
+ prompt.say "Adding server key for connecting to %s..." % [ endpoint ]
+ Assemblage::Publisher.add_server( endpoint, public_key )
+ prompt.say "done."
+ end
+
+ end
+
+ end
+
+end # module Assemblage::CLI::PublisherCommand
+
M lib/assemblage/command/repo.rb +1 -90
@@ 1,7 1,6 @@
# -*- ruby -*-
# frozen_string_literal: true
-require 'pathname'
require 'assemblage/cli' unless defined?( Assemblage::CLI )
@@ 10,94 9,6 @@ module Assemblage::CLI::RepoCommand
extend Assemblage::CLI::Subcommand
- SETUP_ADVICE = %{
- Now you can tell a server to accept commits from a repository on this host
- like so:
- assemblage repo add %{name} '%{public_key}' <uri>
-
- Once it is registered, you can add :
- assemblage commit %{directory}
-
- }.gsub( /^\t+/, '' )
-
-
- desc "Repository commands"
- command :repo do |repo|
-
- repo.desc "Specify a name that will identify the repository server"
- repo.flag [:N, :name], type: String,
- must_match: Assemblage::Auth::CLIENT_NAME_PATTERN,
- required: true
-
- repo.desc 'Set up a new run directory for repository hooks'
- repo.long_desc <<-END_DESC
- Set up a new run directory for hooks that run in one or more repositories.
- This is how the commit (or other) hook authenticates to the server when
- it runs.
- END_DESC
- repo.arg :DIRECTORY
- repo.command :setup do |setup|
-
- setup.action do |globals, options, args|
- directory = Pathname( args.shift || '.' ).expand_path
- name = options.name
-
- prompt.say "Creating a repo run directory in %s..." % [ directory ]
- Assemblage::Repository.setup_run_directory( directory )
-
- prompt.say "Generating a repo key..."
- Assemblage::Repository.generate_cert
- msg = SETUP_ADVICE % {
- public_key: Assemblage::Repository.public_key,
- directory: directory,
- name: name
- }
- prompt.say( msg )
- end
- end
-
-
- repo.desc "Output the repo's public key"
- repo.long_desc <<-END_DESC
- Output the repo's public key to STDOUT.
- END_DESC
- repo.arg :DIRECTORY, :optional
- repo.command 'show-key' do |show_key|
- show_key.action do |globals, options, args|
- directory = Pathname( args.shift || '.' ).expand_path
-
- Assemblage.use_run_directory( directory )
- prompt.say "Worker's public key:"
- puts Assemblage::Repository.public_key
- end
- end
-
+end # module Assemblage::CLI::RepoCommand
- repo.desc "Add a new repository key to a server"
- repo.long_desc <<-END_DESC
- Allow connections from a repository named NAME to the server config
- in SERVER_DIRECTORY.
- END_DESC
- repo.arg :NAME
- repo.arg :PUBLIC_KEY
- repo.arg :SERVER_DIRECTORY, :optional
- repo.command :add do |add|
-
- add.action do |globals, options, args|
- name = args.shift or help_now!( "Missing the repo name." )
- public_key = args.shift or help_now!( "Missing the repo public key." )
-
- Assemblage.use_run_directory( args.shift )
-
- prompt.say "Approving connections from %s..." % [ name ]
- Assemblage::Server.add_repo( name, public_key )
- prompt.say "done."
- end
-
- end
-
- end
-
-end # module Assemblage::CLI::StartServer
-
M lib/assemblage/command/server.rb +130 -18
@@ 2,6 2,7 @@
# frozen_string_literal: true
require 'assemblage/cli' unless defined?( Assemblage::CLI )
+require 'assemblage/server'
# Assemblage server commands
@@ 10,45 11,63 @@ module Assemblage::CLI::ServerCommand
CREATE_ADVICE = %{
You can start the assembly server like so:
- assemblage start server %{directory}
+ assemblage server start %{directory}
Server public key is:
%{public_key}
}.gsub( /^\t+/, '' )
+ # The range of ports to choose from if an endpoint isn't specified when creating
+ # a new server.
+ ENDPOINT_PORT_RANGE = 14000 .. 16000
desc "Server commands"
command :server do |server|
- server.desc "Specify the URI to a database to use."
- server.flag [:D, :database], type: String
-
server.desc 'Set up a new assembly server'
server.long_desc <<-END_DESC
- Set up a new assembly server in the given DIRECTORY. If the DIRECTORY is
+ Set up a new assembly server in the given DIRECTORY and DATABASE. If the DIRECTORY is
not specified, the current directory will be used. If the target directory
- is not empty, this command will abort.
+ is not empty, this command will abort. If no DATABASE is specified, a Sqlite database
+ will be created in the target directory. If an ENDPOINT is specified, the server
+ will accept connections using that specification; otherwise a random port on
+ `localhost` will be chosen.
END_DESC
server.arg :DIRECTORY
+ server.arg :DATABASE, :optional
+ server.arg :ENDPOINT, :optional
server.command :create do |create|
create.action do |globals, options, args|
directory = Pathname( args.shift || '.' ).expand_path
+ database = args.shift
+ endpoint = args.shift
- if options[:database]
- Configurability.loaded_config ||= Configurability.default_config
- Assemblage.config.assemblage.db.uri = options[:database]
+ Configurability.loaded_config ||= Configurability.default_config
+
+ if database && database != ''
+ prompt.say "Setting the database to: %p" % [ database ]
+ Assemblage.config.assemblage.db.uri = database
end
+ unless endpoint
+ port = rand( ENDPOINT_PORT_RANGE )
+ endpoint = "tcp://%s:%d"
+ end
+
+ prompt.say "Setting the endpoint to: %p" % [ endpoint ]
+ Assemblage.config.assemblage.server.endpoint = endpoint
+
prompt.say "Creating a server run directory in %s..." % [ directory ]
Assemblage::Server.setup_run_directory( directory )
prompt.say "Generating a server key..."
Assemblage::Server.generate_cert
- prompt.say "Creating the assemblies database..."
+ prompt.say "Creating the assemblies database (%s)..." %
+ [ Assemblage.config.assemblage.db.uri ]
Assemblage::Server.create_database
msg = CREATE_ADVICE % {
@@ 60,24 79,117 @@ module Assemblage::CLI::ServerCommand
end
- server.desc "Add a new server to a worker"
+ server.desc "Output the server's public key"
server.long_desc <<-END_DESC
- Add a cert and configuration for a new server to a worker run directory.
+ Output the server's public key to STDOUT.
+ END_DESC
+ server.arg :DIRECTORY, :optional
+ server.command 'show-key' do |show_key|
+ show_key.action do |globals, options, args|
+ directory = Pathname( args.shift || '.' ).expand_path
+
+ Assemblage.use_run_directory( directory )
+ prompt.say "Server's public key:"
+ puts Assemblage::Server.public_key
+ end
+ end
+
+
+ server.desc "Output the server's endpoint"
+ server.long_desc <<-END_DESC
+ Output the server's endpoint to STDOUT.
END_DESC
- server.arg :URL
+ server.arg :DIRECTORY, :optional
+ server.command 'show-endpoint' do |show_key|
+ show_key.action do |globals, options, args|
+ directory = Pathname( args.shift || '.' ).expand_path
+
+ Assemblage.use_run_directory( directory )
+ prompt.say "Server's endpoint:"
+ puts Assemblage::Server.endpoint
+ end
+ end
+
+
+ server.desc "Add a new worker to a server"
+ server.long_desc <<-END_DESC
+ Add a cert and configuration for a new worker to a server run directory.
+ END_DESC
+ server.arg :NAME
server.arg :PUBLIC_KEY
- server.arg :WORKER_DIRECTORY, :optional
- server.command :add do |add|
+ server.arg :SERVER_DIRECTORY, :optional
+ server.command 'add-worker' do |add|
add.action do |globals, options, args|
- url = args.shift or help_now!( "Missing the server url." )
- public_key = args.shift or help_now!( "Missing the server public key." )
+ name = args.shift or help_now!( "Missing the worker name." )
+ public_key = args.shift or help_now!( "Missing the worker public key." )
+
+ Assemblage.use_run_directory( args.shift )
+
+ prompt.say "Approving connections from %s..." % [ name ]
+ Assemblage::Server.add_worker( name, public_key )
+ prompt.say "done."
+ end
+
+ end
+
+
+ server.desc "Add a new publisher to a server"
+ server.long_desc <<-END_DESC
+ Add a cert and configuration for a new publisher to a server run directory.
+ END_DESC
+ server.arg :NAME
+ server.arg :PUBLIC_KEY
+ server.arg :SERVER_DIRECTORY, :optional
+ server.command 'add-publisher' do |add|
+
+ add.action do |globals, options, args|
+ name = args.shift or help_now!( "Missing the publisher name." )
+ public_key = args.shift or help_now!( "Missing the publisher public key." )
Assemblage.use_run_directory( args.shift )
- Assemblage::Worker.add_server( url, public_key )
+ prompt.say "Approving connections from %s..." % [ name ]
+ Assemblage::Server.add_publisher( name, public_key )
prompt.say "done."
end
+
+ end
+
+
+ server.desc "Add a new repository to a server"
+ server.long_desc <<-END_DESC
+ Add a new repository named NAME and type TYPE to the server config in SERVER_DIRECTORY.
+ Workers will check out source from the specified URL in response to events
+ published from it.
+
+ Valid types are:
+ #{Assemblage::VCSStrategy.available.map(&:to_s).join(', ')}
+ END_DESC
+ server.arg :NAME
+ server.arg :TYPE
+ server.arg :URL
+ server.arg :SERVER_DIRECTORY, :optional
+ server.command 'add-repo' do |add|
+
+ add.action do |globals, options, args|
+ name = args.shift or help_now!( "Missing the repo name." )
+ type = args.shift or help_now!( "Missing the repo type." )
+ url = args.shift or help_now!( "Missing the repo URL." )
+ directory = args.shift || '.'
+
+ unless Assemblage::VCSStrategy.available.include?( type )
+ help_now! "Invalid repo type %p; supported types are: %s" %
+ [ type, Assemblage::VCSStrategy.available.join(', ') ]
+ end
+
+ Assemblage.use_run_directory( args.shift )
+
+ prompt.say "Approving connections from %s..." % [ name ]
+ Assemblage::Server.add_repo( name, public_key )
+ prompt.say "done."
+ end
+
end
M lib/assemblage/command/worker.rb +10 -12
@@ 11,10 11,10 @@ module Assemblage::CLI::WorkerCommand
CREATE_ADVICE = %{
Now you can register this worker with a server like so:
- assemblage add worker %{name} '%{public_key}' <server directory>
+ assemblage worker add %{name} '%{public_key}' <server directory>
Once it is registered, you can start the assembly worker like so:
- assemblage start worker %{directory}
+ assemblage worker start %{directory}
}.gsub( /^\t+/, '' )
@@ 80,26 80,24 @@ module Assemblage::CLI::WorkerCommand
end
- worker.desc "Add a new worker to a server"
+ worker.desc "Add a new server to a worker"
worker.long_desc <<-END_DESC
- Add a cert and configuration for a new worker to a server run directory.
+ Add a cert and configuration for a new server to a worker run directory.
END_DESC
- worker.arg :NAME
+ worker.arg :URL
worker.arg :PUBLIC_KEY
- worker.arg :SERVER_DIRECTORY, :optional
- worker.command :add do |add|
+ worker.arg :WORKER_DIRECTORY, :optional
+ worker.command 'add-server' do |add|
add.action do |globals, options, args|
- name = args.shift or help_now!( "Missing the worker name." )
- public_key = args.shift or help_now!( "Missing the worker public key." )
+ url = args.shift or help_now!( "Missing the server url." )
+ public_key = args.shift or help_now!( "Missing the server public key." )
Assemblage.use_run_directory( args.shift )
+ Assemblage::Worker.add_server( url, public_key )
- prompt.say "Approving connections from %s..." % [ name ]
- Assemblage::Server.add_worker( name, public_key )
prompt.say "done."
end
-
end
A => lib/assemblage/publisher.rb +69 -0
@@ 0,0 1,69 @@
+# -*- ruby -*-
+# frozen_string_literal: true
+
+require 'loggability'
+
+require 'assemblage' unless defined?( Assemblage )
+
+
+# A client that pushes events for one or more repositories to the server.
+class Assemblage::Publisher
+ extend Loggability,
+ Configurability
+
+ # Loggability API -- log to the assemblage logger
+ log_to :assemblage
+
+
+ configurability( 'assemblage.publisher' ) do
+
+ ##
+ # The ZeroMQ endpoint URL of the server to publish to
+ setting :server_endpoint
+
+ end
+
+
+ ### Generate a client CZTop::Certificate for the publisher.
+ def self::generate_cert
+ Assemblage::Auth.generate_local_cert unless Assemblage::Auth.has_local_cert?
+ end
+
+
+ ### Return the publisher's public key as a Z85-encoded ASCII string.
+ def self::public_key
+ return Assemblage::Auth.local_cert.public_key
+ end
+
+
+ ### Add a server with the specified +endpoint+ and +public_key+ to the current run
+ ### directory.
+ def self::add_server( endpoint, public_key )
+ self.log.info "Adding server at %p with public key: %s" % [ endpoint, public_key ]
+ Assemblage::Auth.save_remote_cert( 'server', public_key )
+
+ Assemblage.config.assemblage.publisher.server_endpoint = endpoint
+ Assemblage.config.write
+ end
+
+
+ ### Set up the +directory+ as a publisher run directory. Raises an
+ ### exception if the directory already exists and is not empty.
+ def self::setup_run_directory( directory='.' )
+ directory = Pathname( directory || '.' )
+ raise "Directory not empty" if directory.exist? && !directory.empty?
+
+ self.log.debug "Attempting to set up %s as a run directory." % [ directory ]
+ directory.mkpath
+ directory.chmod( 0755 )
+
+ config = Assemblage.config || Configurability.default_config
+ config.assemblage.auth.cert_store_dir ||= (directory + 'certs').to_s
+
+ Loggability.with_level( :fatal ) do
+ config.install
+ end
+ config.write( directory + Assemblage::DEFAULT_CONFIG_FILE )
+ end
+
+end # class Assemblage::Publisher
M lib/assemblage/repository.rb +0 -35
@@ 20,40 20,5 @@ class Assemblage::Repository < Assemblag
# Assemblies for this repository
one_to_many :assemblies, class: 'Assemblage::Assembly'
- ##
- #
-
- ### Generate a client CZTop::Certificate for the repo.
- def self::generate_cert
- Assemblage::Auth.generate_local_cert unless Assemblage::Auth.has_local_cert?
- end
-
-
- ### Return the repo's public key as a Z85-encoded ASCII string.
- def self::public_key
- return Assemblage::Auth.local_cert.public_key
- end
-
-
- ### Set up the +directory+ as a repo run directory. Raises an
- ### exception if the directory already exists and is not empty.
- def self::setup_run_directory( directory='.' )
- directory = Pathname( directory || '.' )
- raise "Directory not empty" if directory.exist? && !directory.empty?
-
- self.log.debug "Attempting to set up %s as a run directory." % [ directory ]
- directory.mkpath
- directory.chmod( 0755 )
-
- config = Assemblage.config || Configurability.default_config
- config.assemblage.auth.cert_store_dir ||= (directory + 'certs').to_s
-
- Loggability.with_level( :fatal ) do
- config.install
- end
- config.write( directory + Assemblage::DEFAULT_CONFIG_FILE )
- end
-
-
end # class Assemblage::Repository
M lib/assemblage/server.rb +9 -5
@@ 116,15 116,15 @@ class Assemblage::Server
### directory.
def self::add_worker( name, public_key )
self.log.info "Adding worker %p with public key: %s" % [ name, public_key ]
- cert = Assemblage::Auth.save_remote_cert( name, public_key )
+ Assemblage::Auth.save_remote_cert( name, public_key )
end
- ### Add a repository with the specified +name+ and +public_key+ to the current run
+ ### Add a publisher with the specified +name+ and +public_key+ to the current run
### directory.
- def self::add_repo( name, public_key )
- self.log.info "Adding repo %p with public key: %s" % [ name, public_key ]
- cert = Assemblage::Auth.save_remote_cert( name, public_key )
+ def self::add_publisher( name, public_key )
+ self.log.info "Adding publisher %p with public key: %s" % [ name, public_key ]
+ Assemblage::Auth.save_remote_cert( name, public_key )
end
@@ 370,10 370,14 @@ class Assemblage::Server
def client_for_sender( frame )
rid = frame.routing_id
return self.clients.fetch( rid ) do
+ require 'pry'; binding.pry
clientname = frame.meta( Assemblage::Auth::CLIENT_NAME_KEY )
+
if clientname
+ self.log.debug "Looking up client %p" % [ clientname ]
self.connect_client( clientname, rid )
else
+ self.log.error "No client name associated with %p" % [ frame ]
nil
end
end
M lib/assemblage/vcs_strategy.rb +11 -1
@@ 12,7 12,17 @@ require 'assemblage' unless defined?( As
class Assemblage::VCSStrategy
extend Pluggability
- plugin_paths 'assemblage/vcs_strategy'
+ plugin_prefixes 'assemblage/vcs_strategy'
+
+
+ ### Return the list of available strategies as an Array of Strings.
+ def self::available
+ self.load_all
+ return self.derivatives.keys.
+ reject {|obj| obj.is_a?(Class) }.
+ map( &:downcase ).
+ uniq
+ end
### Clone the repository at the given +url+ into the specified +directory+ at
M spec/assemblage/server_spec.rb +1 -0
@@ 89,6 89,7 @@ describe Assemblage::Server, db: true do
Assemblage.use_run_directory( @assemblage_dir )
Loggability.level = :debug
+ Loggability.format_with( :color )
described_class.add_worker( 'testworker1', @worker_cert.public_key )
A => spec/assemblage/vcs_strategy_spec.rb +46 -0
@@ 0,0 1,46 @@
+#!/usr/bin/env rspec -cfd
+
+require_relative '../spec_helper'
+
+require 'assemblage/vcs_strategy'
+
+
+describe Assemblage::VCSStrategy do
+
+ before( :each ) do
+ @original_derivatives = described_class.derivatives.dup
+ end
+
+ after( :each ) do
+ described_class.derivatives.replace( @original_derivatives )
+ end
+
+
+ let( :type1_class ) do
+ Class.new( described_class ) do
+ def self::name; "#{described_class}::Mercurial"; end
+ end
+ end
+ let( :type2_class ) do
+ Class.new( described_class ) do
+ def self::name; "#{described_class}::Git"; end
+ end
+ end
+
+
+ it "can return a list of the names of available types" do
+ allow( described_class ).to receive( :load_all )
+ described_class.derivatives.replace({
+ 'mercurial' => type1_class,
+ 'Mercurial' => type1_class,
+ type1_class => type1_class,
+ 'git' => type2_class,
+ 'Git' => type2_class,
+ type2_class => type2_class,
+ })
+
+ expect( described_class.available ).to contain_exactly( 'git', 'mercurial' )
+ end
+
+end
+
M spec/assemblage_spec.rb +8 -0
@@ 14,6 14,13 @@ describe Assemblage do
end
+ it "can generate a unique string ID for an object" do
+ expect( Socket ).to receive( :gethostname ).and_return( "Netrehesh.local" )
+ expect( described_class.make_unique_id( 'doot' ) ).
+ to match( /^doot-netrehesh-[[:xdigit:]]{16}$/ )
+ end
+
+
describe "configurability" do
before( :all ) do
@@ 123,6 130,7 @@ describe Assemblage do
Assemblage.load_config( 'a/different/configfile.yml', database: {dbname: 'test'} )
end
+
end
end