Separate Environments from Modes

This commit is contained in:
Thomas Reynolds 2014-06-06 15:32:00 -07:00
parent d035b449ea
commit a21dca025e
19 changed files with 113 additions and 97 deletions

View file

@ -1,6 +1,7 @@
master master
=== ===
* Add support for `environments` with the `-e` CLI flag. Loads additional config from `environments/envname.rb`. Removed `development?` helper in favor of `environment?(:development)`. Added `server?` helper to differentiate between build and server mode.
* Removed `with_layout`. Use loops of `page` instead. * Removed `with_layout`. Use loops of `page` instead.
* Removed Queryable Sitemap API * Removed Queryable Sitemap API
* Removed `css_compressor` setting, use `activate :minify_css, :compressor =>` instead. * Removed `css_compressor` setting, use `activate :minify_css, :compressor =>` instead.

View file

@ -18,6 +18,10 @@ module Middleman::Cli
namespace :build namespace :build
desc 'build [options]', 'Builds the static site for deployment' desc 'build [options]', 'Builds the static site for deployment'
method_option :environment,
aliases: '-e',
default: ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development',
desc: 'The environment Middleman will run under'
method_option :clean, method_option :clean,
type: :boolean, type: :boolean,
default: true, default: true,
@ -58,18 +62,26 @@ module Middleman::Cli
@debugging = Middleman::Cli::Base.respond_to?(:debugging) && Middleman::Cli::Base.debugging @debugging = Middleman::Cli::Base.respond_to?(:debugging) && Middleman::Cli::Base.debugging
self.had_errors = false self.had_errors = false
self.class.shared_instance(options['verbose'], options['instrument']) env = options['environment'].to_sym
verbose = options['verbose'] ? 0 : 1
instrument = options['instrument']
app = ::Middleman::Application.server.inst do
config[:mode] = :build
config[:environment] = env
::Middleman::Logger.singleton(verbose, instrument)
end
opts = {} opts = {}
opts[:glob] = options['glob'] if options.key?('glob') opts[:glob] = options['glob'] if options.key?('glob')
opts[:clean] = options['clean'] opts[:clean] = options['clean']
self.class.shared_instance.run_hook :before_build, self app.run_hook :before_build, self
action BuildAction.new(self, opts) action BuildAction.new(self, app, opts)
self.class.shared_instance.run_hook :after_build, self app.run_hook :after_build, self
self.class.shared_instance.config_context.execute_after_build_callbacks(self) app.config_context.execute_after_build_callbacks(self)
if had_errors && !debugging if had_errors && !debugging
msg = 'There were errors during this build' msg = 'There were errors during this build'
@ -87,16 +99,6 @@ module Middleman::Cli
def exit_on_failure? def exit_on_failure?
true true
end end
# Middleman::Application singleton
#
# @return [Middleman::Application]
def shared_instance(verbose=false, instrument=false)
@_shared_instance ||= ::Middleman::Application.server.inst do
config[:environment] = :build
::Middleman::Logger.singleton(verbose ? 0 : 1, instrument)
end
end
end end
end end
@ -109,8 +111,8 @@ module Middleman::Cli
# #
# @param [Middleman::Cli::Build] base # @param [Middleman::Cli::Build] base
# @param [Hash] config # @param [Hash] config
def initialize(base, config={}) def initialize(base, app, config={})
@app = base.class.shared_instance @app = app
@source_dir = Pathname(@app.source_dir) @source_dir = Pathname(@app.source_dir)
@build_dir = Pathname(@app.config[:build_dir]) @build_dir = Pathname(@app.config[:build_dir])
@to_clean = Set.new @to_clean = Set.new

View file

@ -47,9 +47,7 @@ Feature: Support Rack apps mounted using map
run MySinatra run MySinatra
end end
configure :build do
endpoint "sinatra/index2.html", path: "/sinatra/" endpoint "sinatra/index2.html", path: "/sinatra/"
end
endpoint "dedoo.html", path: "/sinatra/derp.html" endpoint "dedoo.html", path: "/sinatra/derp.html"

View file

@ -0,0 +1 @@
set :api_key, "dev1"

View file

@ -0,0 +1,2 @@
set :api_key, "prod2"
activate :minify_css

View file

@ -0,0 +1,3 @@
<script>
// load: <%= config[:api_key] %>
</script>

View file

@ -0,0 +1,3 @@
body {
backgroud: red;
}

View file

@ -51,8 +51,8 @@
# Change the images directory # Change the images directory
# set :images_dir, "alternative_image_directory" # set :images_dir, "alternative_image_directory"
# Build-specific configuration # Production build configuration
configure :build do configure :production do
# For example, change the Compass output style for deployment # For example, change the Compass output style for deployment
# activate :minify_css # activate :minify_css

View file

@ -31,9 +31,6 @@ require 'middleman-core/core_extensions/request'
# Custom Extension API and config.rb handling # Custom Extension API and config.rb handling
require 'middleman-core/core_extensions/extensions' require 'middleman-core/core_extensions/extensions'
# Catch and show exceptions at the Rack level
require 'middleman-core/core_extensions/show_exceptions'
# Core Middleman Class # Core Middleman Class
module Middleman module Middleman
class Application class Application
@ -73,9 +70,13 @@ module Middleman
# @return [String] # @return [String]
config.define_setting :source, 'source', 'Name of the source directory' config.define_setting :source, 'source', 'Name of the source directory'
# Middleman environment. Defaults to :development, set to :build by the build process # Middleman mode. Defaults to :server, set to :build by the build process
# @return [String] # @return [String]
config.define_setting :environment, ((ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :development), 'Middleman environment. Defaults to :development, set to :build by the build process' config.define_setting :mode, ((ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :server), 'Middleman mode. Defaults to :server'
# Middleman environment. Defaults to :development
# @return [String]
config.define_setting :environment, :development, 'Middleman environment. Defaults to :development'
# Which file should be used for directory indexes # Which file should be used for directory indexes
# @return [String] # @return [String]
@ -139,9 +140,6 @@ module Middleman
# Basic Rack Request Handling # Basic Rack Request Handling
include Middleman::CoreExtensions::Request include Middleman::CoreExtensions::Request
# Handle exceptions
include Middleman::CoreExtensions::ShowExceptions
# Setup custom rendering # Setup custom rendering
include Middleman::CoreExtensions::Rendering include Middleman::CoreExtensions::Rendering
@ -179,9 +177,7 @@ module Middleman
# Setup the default values from calls to set before initialization # Setup the default values from calls to set before initialization
self.class.config.load_settings(self.class.superclass.config.all_settings) self.class.config.load_settings(self.class.superclass.config.all_settings)
::Middleman::Extensions.auto_activate[:before_sitemap].each do |ext_name| ::Middleman::Extensions.auto_activate(:before_sitemap, self)
activate ext_name
end
# Initialize the Sitemap # Initialize the Sitemap
@sitemap = ::Middleman::Sitemap::Store.new(self) @sitemap = ::Middleman::Sitemap::Store.new(self)
@ -204,16 +200,22 @@ module Middleman
@config_context.define_singleton_method(name, &func) @config_context.define_singleton_method(name, &func)
end end
# Whether we're in development mode # Whether we're in server mode
# @return [Boolean] If we're in dev mode # @return [Boolean] If we're in dev mode
def development? def server?
config[:environment] == :development config[:mode] == :server
end end
# Whether we're in build mode # Whether we're in build mode
# @return [Boolean] If we're in build mode # @return [Boolean] If we're in dev mode
def build? def build?
config[:environment] == :build config[:mode] == :build
end
# Whether we're in a specific environment
# @return [Boolean]
def environment?(key)
config[:environment] == key
end end
# The full path to the source directory # The full path to the source directory

View file

@ -8,7 +8,7 @@ module Middleman
attr_reader :app attr_reader :app
# Whitelist methods that can reach out. # Whitelist methods that can reach out.
delegate :config, :logger, :activate, :use, :map, :mime_type, :data, :root, to: :app delegate :config, :logger, :activate, :use, :map, :mime_type, :data, :files, :root, to: :app
def initialize(app, template_context_class) def initialize(app, template_context_class)
@app = app @app = app
@ -34,6 +34,14 @@ module Middleman
end end
end end
def include_environment(name)
path = File.dirname(__FILE__)
other_config = File.join(path, name.to_s)
if File.exist? other_config
instance_eval File.read(other_config), other_config, 1
end
end
def ready(&block) def ready(&block)
@ready_callbacks << block @ready_callbacks << block
end end

View file

@ -11,6 +11,12 @@ Middleman::Extensions.register :data, auto_activate: :before_sitemap do
Middleman::CoreExtensions::Data Middleman::CoreExtensions::Data
end end
# Catch and show exceptions at the Rack level
Middleman::Extensions.register :show_exceptions, auto_activate: :before_configuration, modes: [:server] do
require 'middleman-core/core_extensions/show_exceptions'
Middleman::CoreExtensions::ShowExceptions
end
# File Change Notifier # File Change Notifier
Middleman::Extensions.register :file_watcher, auto_activate: :before_sitemap do Middleman::Extensions.register :file_watcher, auto_activate: :before_sitemap do
require 'middleman-core/core_extensions/file_watcher' require 'middleman-core/core_extensions/file_watcher'

View file

@ -11,8 +11,6 @@ module Middleman
app.define_hook :instance_available app.define_hook :instance_available
app.define_hook :after_configuration app.define_hook :after_configuration
app.define_hook :before_configuration app.define_hook :before_configuration
app.define_hook :build_config
app.define_hook :development_config
app.config.define_setting :autoload_sprockets, true, 'Automatically load sprockets at startup?' app.config.define_setting :autoload_sprockets, true, 'Automatically load sprockets at startup?'
app.config[:autoload_sprockets] = (ENV['AUTOLOAD_SPROCKETS'] == 'true') if ENV['AUTOLOAD_SPROCKETS'] app.config[:autoload_sprockets] = (ENV['AUTOLOAD_SPROCKETS'] == 'true') if ENV['AUTOLOAD_SPROCKETS']
@ -26,11 +24,11 @@ module Middleman
# #
# @example # @example
# # Only minify when building # # Only minify when building
# configure :build do # configure :production do
# activate :minify_javascript # activate :minify_javascript
# end # end
# #
# @param [String, Symbol] env The environment to run in (:build, :development) # @param [String, Symbol] env The environment to run in
# @return [void] # @return [void]
def configure(env, &block) def configure(env, &block)
send("#{env}_config", &block) send("#{env}_config", &block)
@ -80,18 +78,19 @@ module Middleman
# Override application initialization to load `config.rb` and to call lifecycle hooks. # Override application initialization to load `config.rb` and to call lifecycle hooks.
def initialize(&block) def initialize(&block)
super
self.class.inst = self self.class.inst = self
# Search the root of the project for required files # Search the root of the project for required files
$LOAD_PATH.unshift(root) unless $LOAD_PATH.include?(root) $LOAD_PATH.unshift(root) unless $LOAD_PATH.include?(root)
# Evaluate a passed block if given
config_context.instance_exec(&block) if block_given?
super
::Middleman::Extension.clear_after_extension_callbacks ::Middleman::Extension.clear_after_extension_callbacks
::Middleman::Extensions.auto_activate[:before_configuration].each do |ext_name| ::Middleman::Extensions.auto_activate(:before_configuration, self)
activate ext_name
end
if config[:autoload_sprockets] if config[:autoload_sprockets]
begin begin
@ -102,9 +101,6 @@ module Middleman
end end
end end
# Evaluate a passed block if given
config_context.instance_exec(&block) if block_given?
run_hook :initialized run_hook :initialized
run_hook :before_configuration run_hook :before_configuration
@ -116,15 +112,13 @@ module Middleman
config_context.instance_eval File.read(local_config), local_config, 1 config_context.instance_eval File.read(local_config), local_config, 1
end end
if build? env_config = File.join(root, 'environments', "#{config[:environment]}.rb")
run_hook :build_config if File.exist? env_config
config_context.execute_configure_callbacks(:build) logger.debug "== Reading: #{config[:environment]} config"
config_context.instance_eval File.read(env_config), env_config, 1
end end
if development? config_context.execute_configure_callbacks(config[:environment])
run_hook :development_config
config_context.execute_configure_callbacks(:development)
end
run_hook :instance_available run_hook :instance_available

View file

@ -37,9 +37,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
configure_i18n configure_i18n
unless app.build?
logger.info "== Locales: #{langs.join(', ')} (Default #{@mount_at_root})" logger.info "== Locales: #{langs.join(', ')} (Default #{@mount_at_root})"
end
# Don't output localizable files # Don't output localizable files
app.ignore File.join(options[:templates_dir], '**') app.ignore File.join(options[:templates_dir], '**')

View file

@ -1,21 +1,14 @@
# Support rack/showexceptions during development # Support rack/showexceptions during development
module Middleman module Middleman::CoreExtensions
module CoreExtensions class ShowExceptions < ::Middleman::Extension
module ShowExceptions def initialize(app, options_hash={}, &block)
def self.included(app) super
# Require lib
require 'rack/showexceptions' require 'rack/showexceptions'
end
# Whether to catch and display exceptions def after_configuration
# @return [Boolean] app.use ::Rack::ShowExceptions
app.config.define_setting :show_exceptions, true, 'Whether to catch and display exceptions'
# When in dev
app.configure :development do
# Include middlemare
use ::Rack::ShowExceptions if config[:show_exceptions]
end
end
end end
end end
end end

View file

@ -14,6 +14,8 @@ module Middleman
before_configuration: [] before_configuration: []
} }
AutoActivation = Struct.new(:name, :modes)
class << self class << self
# @api private # @api private
# A hash of all registered extensions. Registered extensions are not necessarily active - this # A hash of all registered extensions. Registered extensions are not necessarily active - this
@ -21,12 +23,6 @@ module Middleman
# @return [Hash{Symbol => Class<Middleman::Extension>, Proc}] A directory of known extensions indexed by the name they were registered under. The value may be a Proc, which can be lazily called to return an extension class. # @return [Hash{Symbol => Class<Middleman::Extension>, Proc}] A directory of known extensions indexed by the name they were registered under. The value may be a Proc, which can be lazily called to return an extension class.
attr_reader :registered attr_reader :registered
# @api private
# A list of extensions that should be automatically loaded at different points in the application startup lifecycle.
# Only internal, built-in Middleman extensions should be listed here.
# @return [Hash{Symbol => Symbol}] A hash from event name to extension name.
attr_reader :auto_activate
# Register a new extension. Choose a name which will be # Register a new extension. Choose a name which will be
# used to activate the extension in `config.rb`, like this: # used to activate the extension in `config.rb`, like this:
# #
@ -71,7 +67,10 @@ module Middleman
raise 'You must provide a Middleman::Extension or a block that returns a Middleman::Extension' raise 'You must provide a Middleman::Extension or a block that returns a Middleman::Extension'
end end
@auto_activate[options[:auto_activate]] << name if options[:auto_activate] if options[:auto_activate]
descriptor = AutoActivation.new(name, options[:modes] || :all)
@auto_activate[options[:auto_activate]] << descriptor
end
end end
# @api private # @api private
@ -106,7 +105,19 @@ module Middleman
# A flattened list of all extensions which are automatically activated # A flattened list of all extensions which are automatically activated
# @return [Array<Symbol>] A list of extension names which are automatically activated. # @return [Array<Symbol>] A list of extension names which are automatically activated.
def auto_activated def auto_activated
@auto_activate.values.flatten @auto_activate.values.map(&:name).flatten
end
# @api private
# Load autoactivatable extensions for the given env.
# @param [Symbol] group The name of the auto_activation group.
# @param [Middleman::Application] app An instance of the app.
def auto_activate(group, app)
@auto_activate[group].each do |descriptor|
if descriptor[:modes] == :all || descriptor[:modes].include?(app.config[:mode])
app.activate descriptor[:name]
end
end
end end
end end
end end

View file

@ -30,7 +30,7 @@ module Middleman
# @param [Hash] locals # @param [Hash] locals
# @return [String] # @return [String]
def evaluate(context, locals, &block) def evaluate(context, locals, &block)
return super if middleman_app.build? return super unless middleman_app.server?
begin begin
super super

View file

@ -29,10 +29,6 @@ Given /^"([^\"]*)" is set to "([^\"]*)"$/ do |variable, value|
} }
end end
Given /^current environment is "([^\"]*)"$/ do |env|
@current_env = env.to_sym
end
Given /^the Server is running$/ do Given /^the Server is running$/ do
root_dir = File.expand_path(current_dir) root_dir = File.expand_path(current_dir)
@ -45,14 +41,12 @@ Given /^the Server is running$/ do
ENV['MM_ROOT'] = root_dir ENV['MM_ROOT'] = root_dir
initialize_commands = @initialize_commands || [] initialize_commands = @initialize_commands || []
initialize_commands.unshift lambda {
config[:environment] = @current_env || :development
config[:show_exceptions] = false
}
@server_inst = Middleman::Application.server.inst do @server_inst = Middleman::Application.server.inst do
app.initialized do
initialize_commands.each do |p| initialize_commands.each do |p|
instance_exec(&p) config_context.instance_exec(&p)
end
end end
end end

View file

@ -19,7 +19,7 @@ module Middleman
attr_accessor :current_engine attr_accessor :current_engine
# Shorthand references to global values on the app instance. # Shorthand references to global values on the app instance.
delegate :config, :logger, :sitemap, :build?, :development?, :data, :extensions, :source_dir, :root, to: :app delegate :config, :logger, :sitemap, :server?, :build?, :environment?, :data, :extensions, :source_dir, :root, to: :app
# Initialize a context with the current app and predefined locals and options hashes. # Initialize a context with the current app and predefined locals and options hashes.
# #