Integration is a Ruby on Rails plugin that provides a set of tasks to automate all steps of a synchronous continuous integration process, that is, continuous integration without a server such as CruiseControl. Why? Because that's the way we like it!
Switch branches/tags
Nothing to show
Pull request Compare This branch is 65 commits behind tapajos:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bin
doc
samples
tasks
test
BLUECLOTH-LICENSE
MIT-LICENSE
README.mkdn
Rakefile
init.rb
install.rb
uninstall.rb

README.mkdn

Integration

What

Integration is a Ruby on Rails plugin that provides a set of tasks to automate all steps of a synchronous continuous integration process, that is, continuous integration without a server such as CruiseControl. Why? Because that's the way we like it!

Installing

ruby script/plugin install git://github.com/tapajos/integration.git

After installing the plugin is ready to be used and you will need to execute only one task in order to integrate your code safely:

rake integrate

Dependencies

Integration Steps

The integration process is composed of several steps that are explained ahead. It's possible to skip one or more steps and add other steps of your own. This will be demonstrated shortly. The complete set of steps are:

  1. task scm:status:check

    Check if all local files are under control of your scm. If your scm is subversion, it also checks if no local files have been removed using only rm (file removal should always use svn remove instead).

  • task log:clear

    Remove log files.

  • task tmp:clear

    Remove temporary files.

  • task backup:local

    Backup files locally. This is done before scm update to create a recovery point if you have problems during scm update. If a file merge creates undesirable effects on the software, you can recover from the backup file. Backup file names have a timestamp. By default, the last 30 backups are kept. You may change this number as you'll see shortly. This task won't work on Windows because it uses tar. So, if you're using Windows you'll have to write your own version of this task or just stop using Windows. We highly recommend the later.

  • task scm:update

    Update local files from your remote scm repository.

  • task db:migrate

    Execute any new database migration created by other team members since the last integration.

  • test:units

    Run all unit tests.

  • test:functionals

    Run all functional tests.

  • test:integration

    Run all integration tests.

  • spec:lib

    Run all lib specs.

  • spec:models

    Run all model specs.

  • spec:helpers

    Run all helper specs.

  • spec:controllers

    Run all controller specs.

  • spec:views

    Run all view specs.

  • test:rcov:units

    Run coverage analysis of the unit tests.

  • test:rcov:units:verify

    Check if unit tests cover 100% of the application code.

  • test:rcov:functionals

    Run coverage analysis of the functional tests.

  • test:rcov:functionals:verify

    Check if functional tests cover 100% of the application code.

  • spec:rcov

    Run coverage analysis of the specs.

  • spec:rcov:verify

    Check if specs cover 100% of the application code.

  • test:plugins:selected

    Run tests on selected plugins. You might want to always run the tests of plugins you created, for example, while ignoring the tests of third party plugins. We'll show below how you can specify the plugins you want to test.

  • spec:plugins:selected

    Same as previous step, but with specs, instead of tests.

  • test:selenium:server:start

    If you use Selenium to test your application, as you certainly should, you'll need to make sure the webserver is up and running before running Selenium tests. That's what this task does.

  • test_acceptance

    Run all Selenium tests.

  • test:selenium:server:stop

    Stop the webserver.

  • scm:commit

    Commit your changes. If any of the previous tasks break, because one test failed, for instance, the script won't commit. Actually this task runs only if every checking done before work well.

Using this almost paranoid sequence of steps it will be hard to check in bad code in your repository, which is good, very good. The idea is that you should treat your repository as a sacred place, where only good code should ever enter.

Customize the integration process

To customize the integration process you need to create a task file in your project, like:

lib/tasks/integration.rake

Changing scm

By default the integration process uses subversion, but you can customize it to use git(your remote repository is git) or git-svn(your remote repository is svn, but you uses git locally):

  • git

      ENV['SCM'] = 'git'
    
  • git-svn

      ENV['SCM'] = 'git_with_svn'
    

Skipping tasks

In your custom integration rake file you may define a comma separated list of tasks that you don't want to execute. Let's see some examples:

  • Don't execute migrations

      ENV['SKIP_TASKS'] = 'db:migrate'
    
  • Don't execute spec coverage, nor spec coverage verification

      ENV['SKIP_TASKS'] = 'spec:rcov, spec:rcov:verify'
    
  • Don't execute any tests nor specs at all

      ENV['SKIP_TASKS'] = %w( 
      						test:units
      						test:functionals
      						test:integration
      						spec:lib
                              spec:models
                              spec:helpers
                              spec:controllers
                              spec:views
                              test:rcov:units
                              test:rcov:units:verify
                              test:rcov:functionals
                              test:rcov:functionals:verify
                              spec:rcov
                              spec:rcov:verify
                              test:selenium:server:start
                              test_acceptance
                              test:selenium:server:stop
                              ).join(",")
    

You can also define SKIP_TASKS when you run the integration process like this:

rake integrate SKIP_TASKS=spec:rcov,spec:rcov:verify

Adding other tasks

Integration plugin also defines callback tasks that you can use to customize it with your own tasks. You can add other tasks before or after any of the plugin tasks. Let's see an example. Say you want to sweep HTML cache pages after running Selenium. To do that, you've just created a task cache:sweep. Let's configure Integration to run it just after Selenium:

	namespace :test_acceptance do
		desc 'Runs cache sweeper'
		task :after do
			Rake::Task["cache:sweep"].invoke 
		end
	end 

A callback task is one that has the same name of a plugin task followed by :before or :after. In this case, the plugin defines a task called test_acceptance. So, you may create test_acceptance:before that will be executed before test_acceptance and test_acceptance:after to execute as soon as test_acceptance finishes. To do that, you will need to use namespaces, like we did in the previous example. Now, let's see a real example from one of our projects:

def integration_sweeper
  sh "script/integration_sweeper"
end

namespace :scm do
  namespace :status do
    namespace :check do
      task :before do
        integration_sweeper
      end
    end
  end
end

desc 'Generates error 500 page'
task :error500 do
  `curl http://localhost:4000/server_error -o #{RAILS_ROOT}/public/500.html`
end

namespace :cache do
  namespace :sweeper do
    desc 'Runs cache_sweeper before executing Selenium'
    task :start do
      integration_sweeper
    end

    desc 'Runs cache_sweeper after executing Selenium'
    task :stop do
      integration_sweeper
    end
  end
end

namespace :test_acceptance do
  desc 'Runs cache sweeper and generate static 500 error page'
  task :before do
    Rake::Task["error500"].invoke 
  end

  desc 'Runs cache sweeper'
  task :after do
    Rake::Task["cache:sweeper:stop"].invoke 
  end
end

Defining the list of plugins for which you want to run tests or specs

In your integration process, you may want to run tests or specs for certain plugins. All you need to do is name them, like this:

ENV['PLUGINS_TO_TEST'] = "packr, email"
ENV['PLUGINS_TO_SPEC'] = "brazilian_rails"

You can also inform these when you run rake integrate:

rake integrate PLUGINS_TO_TEST=packr,email PLUGINS_TO_SPEC=brazilian_rails

Defining the environment in which to run the integration process

Integration will run against the development environment by default. If you need it to run using another environment, you can do this:

ENV['RAILS_ENV'] = 'development_cache'

Once again, you can also inform this while running rake integrate:

rake integrate RAILS_ENV=test

Selenium port

When running Selenium, you might need to specify another port other them the default port 4000. That's how you do it:

ENV['SELENIUM_PORT'] = 3000

Number of backups to keep

If you want to change the number of backups that will be kept, use this:

ENV['NUMBER_OF_BACKUPS_TO_KEEP'] = 50

Backups are store in a sibling directory with the prefix 'backup-'. For instance, suppose you have a project 'amazing' in the projects directory. After the first backup, you will end up with something like this:

projects/amazing
projects/backup-amazing
projects/backup-amazing/amazing-20080304-104812.tar.gz

Commit messages

If you don't care to write commit messages, you can skip them:

ENV['SKIP_COMMIT_MESSAGES'] = 'true'

More examples

  • Reckless programmer

    So you don't have tests, nor specs but you still want to use the plugin. Besides, you want to keep the log files and prefer not to run migrations. You might get away with this customized lib/tasks/integration.rake:

      ENV['SKIP_TASKS'] = %w(
      						log:clear
      					    db:migrate
      					    test:units
      					    test:functionals
      					    test:integration
      					    spec:lib
      					    spec:models
      					    spec:helpers
      					    spec:controllers
      					    spec:views
      					    test:rcov:units
      					    test:rcov:units:verify
      					    test:rcov:functionals
      					    test:rcov:functionals:verify
      					    spec:rcov
      					    spec:rcov:verify
      					    test:plugins:selected
      					    spec:plugins:selected
      					    test:selenium:server:start
      					    test_acceptance
      					    test:selenium:server:stop
                              ).join(",")
    

    The fact that you can get away with this doesn't mean you should. Don't you think it's already time to grow up and become more professional about software development? I know you believe you have a great excuse to avoid writing those tests or specs. Still it's just an excuse. Write tests or write specs and make a better world!

  • Test conscious programmer

    You haven't jumped on the BDD bandwagon yet. Instead, you write tests, which is good, but they don't cover all of your code yet, which is bad. We believe you will improve it and make sure your tests cover 100% of your code. In the meantime you might need to skip coverage checkings. Oh, you also don't use Selenium. Shame on you! Try this:

      ENV['SKIP_TASKS'] = %w( 
      						spec:lib
      						spec:models
      						spec:helpers
      						spec:controllers
      						spec:views
      						test:rcov:units
      						test:rcov:units:verify
      						test:rcov:functionals
      						test:rcov:functionals:verify
      						spec:rcov
      						spec:rcov:verify
      						test:selenium:server:start
      						test_acceptance
      						test:selenium:server:stop
      						).join(',')
    

    As a matter of fact, since this case might be very common, we decided to create a lib/tasks/integration.rake for you once the plugin has been installed. It has this very configuration and you can use it as a starting point to customize your integration process.

  • Spec infected programmer

    So you used to TDD all around but then someone told you that this is for gramma. The new wave has a name on it: BDD. So, of course, you now have specs covering 100% of your code and doesn't have any more tests. Great! Just do it:

      ENV['SKIP_TASKS'] = %w(
      					    test:units
      					    test:functionals
      					    test:integration
      					    test:rcov:units
      					    test:rcov:units:verify
      					    test:rcov:functionals
      					    test:rcov:functionals:verify
                              ).join(",")
    

You can see more examples in the samples directory.

Forum

Discussion about the Integration Plugin are welcome on the forum below:

http://rubyforge.org/forum/?group_id=4662

Version

Integration version 0.2.4

Release Notes

  • Version 0.2.4 - Added support for git and git-svn. Thanks to Sylvestre Mergulhão and Eduardo Fiorezi.
  • Version 0.2.3 - BUG FIX: Rake db:migrate fails when default RAILS_ENV is used. Thanks to Celestino Gomes for fix this bug.
  • Version 0.2.2 - Removed vendor/plugins/* commit. This commit is necessary when use plugins with externals but it is not a good practice. Piston is the correct way to use externals plugins. If you want to use externals commit in your integration process you can create a svn:commit:after task.
  • Version 0.2.1 - BUG FIX: Setting 'RAILS_ENV' wasn't affecting migrations. This bug fix changes this behavior and makes sure that 'RAILS_ENV' set by the user will always be respected, for all tasks. Thanks to Sylvestre Mergulhão for point this out.
  • Version 0.2 - Added support for SKIP_COMMIT_MESSAGES'.

License

This code is free to be used under the terms of the MIT license.

Contact

Comments are welcome. Send your feedback through the forum or to this page

Authors

Marcos Tapajós
Vinícius Teles

Shameless advertisement

This plugin is brought to you by Improve It.

Improve It