Permalink
Browse files

Check all dependencies before deploying.

Rather than checking for each change before deploying the change, check the
dependencies for all changes to be deployed before *any* of them is deployed.
  • Loading branch information...
1 parent 8078800 commit b7ec1acf4af787d1aa103f29a3ac4f4a24ca3c11 @theory committed Dec 21, 2012
Showing with 293 additions and 135 deletions.
  1. +4 −0 Changes
  2. +58 −24 lib/App/Sqitch/Engine.pm
  3. +231 −111 t/engine.t
View
@@ -12,6 +12,10 @@ Revision history for Perl extension App::Sqitch
the deploy scripts. Useful for an existing database that is being
converted to Sqitch, and you need to log changes as deployed because
they have been deployed by other means in the past.
+ - Now check that dependencies are required for all changes to be deployed
+ before deploying anything, rather than checkint for each change just
+ before deploying it. This allows a deploy to fail sooner, with no
+ database changes, when dependencies are not met.
0.940 2012-12-04T05:49:45Z
- Fixed tests that failed due to I18N issues, with thanks to Arnaud
View
@@ -123,6 +123,10 @@ sub deploy {
)
);
+ # Check that all dependencies will be satisfied.
+ $self->check_deploy_dependencies($plan, $to_index);
+
+ # Do it!
$mode ||= 'all';
my $meth = $mode eq 'change' ? '_deploy_by_change'
: $mode eq 'tag' ? '_deploy_by_tag'
@@ -240,6 +244,51 @@ sub revert {
return $self;
}
+sub check_deploy_dependencies {
+ my ( $self, $plan, $to_index ) = @_;
+
+ my $from_index = $plan->position;
+ $to_index //= $plan->count - 1;
+ my (%seen, @conflicts, @required);
+
+ while ($from_index < $to_index) {
+ my $change = $plan->change_at( ++$from_index );
+
+ # Check for conflicts.
+ push @conflicts => grep {
+ $seen{ $_->id // '' } || $self->change_id_for_depend($_)
+ } $change->conflicts;
+
+ # Check for prerequisites.
+ push @required => grep {
+ !$seen{ $_->id // ''} && !$_->resolved_id(
+ $self->change_id_for_depend($_)
+ )
+ } $change->requires;
+ $seen{$change->id} = 1;
+ }
+
+ return $self unless @conflicts or @required;
+
+ # Dependencies not satisfied. Put together the error messages.
+ my @msg;
+ push @msg, __nx(
+ 'Conflicts with previously deployed change: {changes}',
+ 'Conflicts with previously deployed changes: {changes}',
+ scalar @conflicts,
+ changes => join ' ', map { $_->as_string } @conflicts,
+ ) if @conflicts;
+
+ push @msg, __nx(
+ 'Missing required change: {changes}',
+ 'Missing required changes: {changes}',
+ scalar @required,
+ changes => join ' ', map { $_->as_string } @required,
+ ) if @required;
+
+ hurl deploy => join $/ => @msg;
+}
+
sub change_id_for_depend {
my ( $self, $dep ) = @_;
hurl engine => __x(
@@ -408,30 +457,6 @@ sub deploy_change {
$sqitch->info(' + ', $change->format_name_with_tags);
$self->begin_work($change);
- # Check for conflicts.
- if (my @conflicts = grep {
- $self->change_id_for_depend($_)
- } $change->conflicts) {
- hurl deploy => __nx(
- 'Conflicts with previously deployed change: {changes}',
- 'Conflicts with previously deployed changes: {changes}',
- scalar @conflicts,
- changes => join ' ', map { $_->as_string } @conflicts,
- )
- }
-
- # Check for dependencies.
- if (my @required = grep {
- !$_->resolved_id( $self->change_id_for_depend($_) )
- } $change->requires) {
- hurl deploy => __nx(
- 'Missing required change: {changes}',
- 'Missing required changes: {changes}',
- scalar @required,
- changes => join ' ', map { $_->as_string } @required,
- );
- }
-
return try {
$self->run_file($change->deploy_file) unless $log_only;
try {
@@ -817,6 +842,15 @@ associated changes. The C<$log_only> parameter, if passed a true values,
causes the revret to log the reverted changes I<without running the revert
scripts>.
+=head3 C<check_deploy_dependencies>
+
+ $engine->check_deploy_dependencies;
+ $engine->check_deploy_dependencies($to_index);
+
+Validates that all dependencies will be met for all changes to be deployed,
+starting with the currently-deployed change up to the specified index, or to
+the last change in the plan if no index is passed.
+
=head3 C<deploy_change>
$engine->deploy_change($change);
Oops, something went wrong.

0 comments on commit b7ec1ac

Please sign in to comment.