App-Sqitch

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

     - Removed `local` directory from the distribution, accidentally included
       in v1.2.0. Thanks to gregor herrmann for the report (#600).

1.2.0  2021-11-20T22:45:00Z
     - Fixed partitioned search for deployed changes on Oracle and Exasol to
       correctly support plans with more than 250 changes. Thanks to @Nicqu
       for the report (#521).
     - DBI connections to the registry will now be set to trace level one
       when a verbosity level of three or higher is passed to Sqitch
       (i.e., `sqitch -vvv`). Thanks to @wkoszek for the suggestion (#155).
     - Renamed the "master" branch to "main" and updated all relevant
       references.
     - Fixed the parsing of the Snowflake account name from the target URL
       to that it no longer strips out the region and cloud platform parts.
       Also deprecated the use of the region, host, and port config and
       environment variables. This is to comply with the new account name
       format. Thanks to @ldsingh00 for the report (#544).
     - The checkout command will now show a usage statement when no branch
       name is passed to it, rather than a series of warnings and a Git error.
       Thanks to François Beausoleil for the report (#561).
     - The checkout command now works when operating on a Sqitch project in

Changes  view on Meta::CPAN

       the database name and no default for the role.
     - Switched to using a constant internally to optimize windows-specific
       code paths at compile time.
     - When `deploy` detects undeployed dependencies, it now eliminates
       duplicates before listing them in the error message.
     - Now requiring IO::Pager v0.34 or later for its more consistent
       interface.
     - Added notes about creating databases to the tutorials. Thanks to Dave
       Rolsky for the prompt (#315).
     - Added a status message to tell the user when the registry is being
       updated, rather than just show each individual update. Thanks to Ben
       Hutton for the suggestion (#276).
     - Added support for a `$SQITCH_TARGET` environment variable, which takes
       precedence over all other target specifications except for command-line
       options and arguments. Thanks to @mvgrimes for the suggestion (#203).
     - Fixed target/engine/change argument parsing so it won't automatically
       fail when `core.engine` isn't set unless no targets are found. This
       lets engines be determined strictly from command-line arguments --
       derived from targets, or just listed on their own -- whether or not
       `core.engine` is set. This change eliminates the need for the
       `no_default` parameter to the `parse_args()` method of App::Sqitch

Changes  view on Meta::CPAN

       such as `--to-target`, `--upto-target`, which have been deprecated with
       warnings in in favor of options containing the string "change", such as
       `--to-change` and `--upto-change`, since v0.997 (November 2014).
     - Remove the `engine` and `target` command `set-*` actions and their
       corresponding methods, which have been deprecated in favor of the
       `alter` action since v0.9993 (August 2015).
     - Removed the automatic updating of change and tag IDs in the Postgres
       engine. This functionality was added in v0.940 (December 2012), when
       Postgres was the only engine, and the SHA-1 hash for change and tag IDs
       was changed. There were very few deployments at the time, and all
       should long since have been updated.

     [API Changes]
     - Added the URI-overriding parameters `user`, `host`, `port`, and
       `dbname` to App::Sqitch::Target so that command options can be used to
       easily set them.
     - Added support for passing attribute parameters to the `all_targets`
       group constructor on App::Sqitch::Target, so that command-line options
       can be used to assign attributes to all targets read from the
       configuration.
     - Aded the `target_params` method to App::Sqitch::Command and updated all
       commands to use it when constructing targets. This allows commands to
       define options for Target parameters, as required for moving options to
       commands as described above.
     - Added the `class_for` method to App::Sqitch::Command so that the new
       options parser described above can load a command class without
       instantiating an instance. Useful for searching command-line arguments
       for a command name.
     - Added the `create` constructor to App::Sqitch::Command to let Sqitch
       instantiate an instance of a command once it finds one via `class_for`.
       Previously, Sqitch used the `load` method, which handled the

Changes  view on Meta::CPAN

     - Removed documentation for the optional `config` parameter to the
       `all_targets` constructor of App::Sqitch::Target, since it was never
       used by Sqitch. It always fetched the config from the required `sqitch`
       parameter. Support for the `config` parameter has not been removed,
       since third-parties might use it.
     - Removed the `set_*` methods in the `engine` and `target` commands,
       which have been deprecated in favor of the new `alter` method since
       v0.9993 (August 2015).
     - Removed the `old_id` and `old_info` methods from Change and Tag, which
       date from v0.940 (December 2012), and were provided only to allow
       existing Postgres databases to be updated from the old to new ID
       format, now removed. There should be no other use case for these
       methods.

0.9998 2018-10-03T20:53:58Z
     - Fixed an issue where Sqitch would sometimes truncate the registry
       version number fetched from MySQL, most likely because the Perl runtime
       was using 32-bit integers. Fixed by casting the version to CHAR in the
       query, before Perl ever see it. Thanks to Allen Godfrey David for the
       report.
     - Added the Snowflake engine.

Changes  view on Meta::CPAN

       tables are distributed by replication to all data nodes.
     - Added support to MariaDB 5.3 and higher to the MySQL engine, thanks to
       Ed Silva.

0.991  2014-01-16T23:24:33Z
     - Greatly simplified determining the Firebird ISQL client. It no longer
       tries so hard to find a full path, but does search through the path list
       for a likely candidate between fbsql, isql-fb, and isql (or equivalents
       ending in .exe on Windows).
     - Removed a bunch of inappropriately pasted stuff from the Firebird
       tutorial, and updated it a bit.
     - `HEAD` and `ROOT` are now recognized as aliases for `@HEAD` and
       `@ROOT`, when querying the database, too. That means that `revert --to
       HEAD` now works the same as `revert --to @HEAD`, as had been expected
       in v0.990.
     - Eliminated "use of uninitialized value" warnings when database
       connections fail.
     - Reduced the minimum required DBD::Firebird to v1.11.
     - Fixed the `--verbose` option to the `target` command.
     - Eliminated more user-configuration issues in tests, thanks to
       chromatic.

Changes  view on Meta::CPAN

     - Improved error handling when deploying and reverting a change. If the
       change successfully deployed but the logging of the deployment to the
       database failed, there was just a rollback message. Sqitch will now
       emit the underlying error *and* run the revert script for the
       just-deployed change.
     - Modified the text hashed for change and tag IDs. Both now include the
       note, if present, the ID of the preceding change, and the list of
       dependencies. The result is that, when a change is modified or moved in
       the plan, it gets a new ID ID. The upshot is that things *must* be in
       order for a deploy to succeed. Existing deployments will automatically
       have their IDs updated by the `deploy` command.
     - Changed the `revert` command so that it *only* fetches information about
       changes to be reverted from the database, rather than the plan.
     - Deprecated the `@LAST` and `@FIRST` symbolic tags. With `revert` now
       fetching change information from the database, there is no longer a
       need to specify that changes be found in the database. It's possible
       some other way to search database changes will be added in the future,
       but if so, it will be less limiting than `@LAST` and `@FIRST`, because
       it will likely allow searches by literal tags.
     - Added the `rebase` command. This command combines a `revert` and a
       `deploy` into a single command, which should allow for more natural

README.md  view on Meta::CPAN

There have also been a number of presentations on Sqitch:

* [PDX.pm Presentation]: Slides from "Sane Database Management with Sqitch",
  presented to the Portland Perl Mongers in January, 2013.

* [PDXPUG Presentation]: Movie of "Sane Database Management with Sqitch",
  presented to the Portland PostgreSQL Users Group in September, 2012.

* [Agile Database Development]: Slides from a three-hour tutorial session on
  using [Git], test-driven development with [pgTAP], and change management with
  Sqitch, updated in January, 2014.

Installation
------------

To install Sqitch from a distribution download, type the following:

    perl Build.PL
    ./Build installdeps
    ./Build
    ./Build test

inc/Module/Build/Sqitch.pm  view on Meta::CPAN

                }

                $self->log_verbose("Unlinking $file\n");
                unlink $file;
                $notify = 1;
            }
        }
    }

    # If we moved any files, nofify the user that custom templates will need
    # to be updated, too.
    if ($notify) {
        $self->log_warn(q{
            #################################################################
            #                         WARNING                               #
            #                                                               #
            # As of v0.980, the location of script templates has changed.   #
            # The system-wide templates have been moved to their new        #
            # locations as described above. However, user-specific          #
            # templates have not been moved.                                #
            #                                                               #

lib/App/Sqitch/Engine.pm  view on Meta::CPAN

        );

        # Upgrade the registry if there is no script_hash column.
        unless ( exists $state->{script_hash} ) {
            $self->upgrade_registry;
            $state->{script_hash} = $state->{change_id};
        }

        # Update the script hashes if they're the same as the change ID.
        # DEPRECATTION: Added in v0.998 (Jan 2015, c86cba61c); consider removing
        # in the future when all databases are likely to be updated already.
        $self->_update_script_hashes if $state->{script_hash}
            && $state->{script_hash} eq $state->{change_id};

        $plan->position($idx);
        my $change = $plan->change_at($idx);
        if (my @tags = $change->tags) {
            $self->log_new_tags($change);
            $self->start_at( $change->format_name . $tags[-1]->format_name );
        } else {
            $self->start_at( $change->format_name );

lib/App/Sqitch/Engine/Upgrade/sqlite-1.1.sql  view on Meta::CPAN

BEGIN;

-- Create a new changes table with updated unique constraint.
CREATE TABLE new_changes (
    change_id       TEXT        PRIMARY KEY,
    script_hash     TEXT            NULL,
    change          TEXT        NOT NULL,
    project         TEXT        NOT NULL REFERENCES projects(project) ON UPDATE CASCADE,
    note            TEXT        NOT NULL DEFAULT '',
    committed_at    DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    committer_name  TEXT        NOT NULL,
    committer_email TEXT        NOT NULL,
    planned_at      DATETIME    NOT NULL,

lib/App/Sqitch/Plan/ChangeList.pm  view on Meta::CPAN


Append one or more changes to the list. Does not check for duplicates, so
use with care.

=head3 C<index_tag>

  $changelist->index_tag($index, $tag);

Index the tag at the specified index. That is, the tag is assumed to be
associated with the change at the specified index, and so the internal look up
table is updated so that the change at that index can be found via the tag's
name and ID.

=head1 See Also

=over

=item L<App::Sqitch::Plan>

The Sqitch plan.

lib/sqitch-config.pod  view on Meta::CPAN


=head1 Description

You can query/set/replace/unset Sqitch options with this command. The name is
actually the section and the key separated by a dot, and the value will be
escaped.

Multiple lines can be added to an option by using the C<--add> option. If you
want to update or unset an option which can occur on multiple lines, a Perl
regular expression C<value_regex> needs to be given. Only the existing values
that match the regex will be updated or unset. If you want to handle lines
that do not match the regex, just prepend a single C<!> (exclamation point) in
front (see L<Examples>).

The C<type> specifier can be C<--int>, C<--num>, or C<--bool>, to ensure that
the variable(s) are of the given type and convert the value to the canonical
form (simple integer for C<--int>, decimal number for C<--num>, a "true" or
"false" string for C<--bool>) If no type specifier is passed, no checks or
transformations are performed on the value.

The C<file-option> can be one of C<--local>, C<--user>, C<--system>, or

lib/sqitch.pod  view on Meta::CPAN

distribution. Sqitch can read your VCS history and write out a plan file along
with the appropriate deployment and reversion scripts. Once the bundle is
installed on a new system, Sqitch can use the plan file to deploy or the
changes in the proper order.

=item Reduced Duplication

If you're using a VCS to track your changes, you don't have to duplicate
entire change scripts for simple changes. As long as the changes are
L<idempotent|https://en.wikipedia.org/wiki/Idempotence>, you can change
your code directly, and Sqitch will know it needs to be updated.

=end comment

=back

Ready to get started? Here's where:

=over

=item Sqitch Tutorials

lib/sqitchtutorial-exasol.pod  view on Meta::CPAN

	* deploy/userflips.sql
	* revert/userflips.sql
	* verify/userflips.sql

Oh, so we can edit those files in place. Nice! How does Sqitch do it? Well, in
point of fact, it has copied the files to stand in for the previous instance
of the C<userflips> change, which we can see via C<git status>:

  > git status
  # On branch main
  # Changed but not updated:
  #   (use "git add <file>..." to update what will be committed)
  #   (use "git checkout -- <file>..." to discard changes in working directory)
  #
  #	modified:   revert/userflips.sql
  #	modified:   sqitch.plan
  #
  # Untracked files:
  #   (use "git add <file>..." to include in what will be committed)
  #
  #	deploy/userflips@v1.0.0-dev2.sql

lib/sqitchtutorial-sqlite.pod  view on Meta::CPAN

The other thing to notice is that F<revert/userflips.sql> has changed. Sqitch
replaced it with the original deploy script. As of now,
F<deploy/userflips.sql> and F<revert/userflips.sql> are identical. This is on
the assumption that the deploy script will be changed (we're reworking it,
remember?), and that the revert script should actually change things back to
how they were before. Of course, the original deploy script won't be
L<idempotent|https://en.wikipedia.org/wiki/Idempotence> -- that is, able to be
applied multiple times without changing the result beyond the initial
application. It could be if SQLite supported C<CREATE OR REPLACE VIEW>, but
since it doesn't, we will have to edit the script to drop the view before
creating it. Or, more simply, it needs to be updated to revert changes back to
how they were as-of the deployment of F<deploy/userflips@v1.0.0-dev2.sql>.

Modify F<deploy/userflips.sql> to add the C<twitter> column; in fact, let's
also add a C<DROP VIEW IF EXISTS> statement, in case we need to rework this
change again in the future:

  @@ -4,8 +4,9 @@
 
   BEGIN;
 

lib/sqitchtutorial-vertica.pod  view on Meta::CPAN

	* deploy/userflips.sql
	* revert/userflips.sql
	* verify/userflips.sql

Oh, so we can edit those files in place. Nice! How does Sqitch do it? Well, in
point of fact, it has copied the files to stand in for the previous instance
of the C<userflips> change, which we can see via C<git status>:

  > git status
  # On branch main
  # Changed but not updated:
  #   (use "git add <file>..." to update what will be committed)
  #   (use "git checkout -- <file>..." to discard changes in working directory)
  #
  #	modified:   revert/userflips.sql
  #	modified:   sqitch.plan
  #
  # Untracked files:
  #   (use "git add <file>..." to include in what will be committed)
  #
  #	deploy/userflips@v1.0.0-dev2.sql

t/engine.t  view on Meta::CPAN

$engine->seen;

is $plan->position, -1, 'Plan should start at position -1';
is $engine->start_at, undef, 'start_at should be undef';

ok $engine->_sync_plan, 'Sync the plan';
is $plan->position, -1, 'Plan should still be at position -1';
is $engine->start_at, undef, 'start_at should still be undef';
$plan->position(4);
is_deeply $engine->seen, [['current_state', undef]],
    'Should not have updated IDs or hashes';

ok $engine->_sync_plan, 'Sync the plan again';
is $plan->position, -1, 'Plan should again be at position -1';
is $engine->start_at, undef, 'start_at should again be undef';
is_deeply $engine->seen, [['current_state', undef]],
    'Still should not have updated IDs or hashes';

# Have latest_item return a tag.
$latest_change_id = $changes[2]->id;
ok $engine->_sync_plan, 'Sync the plan to a tag';
is $plan->position, 2, 'Plan should now be at position 2';
is $engine->start_at, 'widgets@beta', 'start_at should now be widgets@beta';
is_deeply $engine->seen, [
    ['current_state', undef],
    ['log_new_tags' => $plan->change_at(2)],
], 'Should have updated IDs';

# Have current_state return a script hash.
$script_hash = '550aeeab2ae39cba45840888b12a70820a2d6f83';
ok $engine->_sync_plan, 'Sync the plan with a random script hash';
is $plan->position, 2, 'Plan should now be at position 1';
is $engine->start_at, 'widgets@beta', 'start_at should now be widgets@beta';
is_deeply $engine->seen, [
    ['current_state', undef],
    ['log_new_tags' => $plan->change_at(2)],
], 'Should have updated IDs but not hashes';

# Have current_state return the last deployed ID as script_hash.
$script_hash = $latest_change_id;
ok $engine->_sync_plan, 'Sync the plan with a random script hash';
is $plan->position, 2, 'Plan should now be at position 1';
is $engine->start_at, 'widgets@beta', 'start_at should now be widgets@beta';
is_deeply $engine->seen, [
    ['current_state', undef],
    ['_update_script_hashes'],
    ['log_new_tags' => $plan->change_at(2)],
], 'Should have updated IDs and hashes';

# Return no change ID, now.
$script_hash = $latest_change_id = $changes[1]->id;
ok $engine->_sync_plan, 'Sync the plan';
is $plan->position, 1, 'Plan should be at position 1';
is $engine->start_at, 'users@alpha', 'start_at should be users@alpha';
is_deeply $engine->seen, [
    ['current_state', undef],
    ['_update_script_hashes'],
    ['log_new_tags' => $plan->change_at(1)],
], 'Should have updated hashes but not IDs';

# Have current_state return no script hash.
my $mock_whu = Test::MockModule->new('App::Sqitch::Engine::whu');
my $state = {change_id => $latest_change_id};
$mock_whu->mock(current_state => $state);
ok $engine->_sync_plan, 'Sync the plan with no script hash';
$mock_whu->unmock('current_state');
is $plan->position, 1, 'Plan should now be at position 1';
is $engine->start_at, 'users@alpha', 'start_at should still be users@alpha';
is_deeply $engine->seen, [

t/lib/DBIEngineTest.pm  view on Meta::CPAN


        # Unmock everything and call it a day.
        $mock_dbh->unmock_all;
        $mock_sqitch->unmock_all;

        ######################################################################
        # Let's make sure script_hash upgrades work.
        $engine->dbh->do('UPDATE changes SET script_hash = change_id');
        ok $engine->_update_script_hashes, 'Update script hashes';

        # Make sure they were updated properly.
        my $sth = $engine->dbh->prepare(
            'SELECT change_id, script_hash FROM changes WHERE project = ?',
        );
        $sth->execute($plan->project);
        while (my $row = $sth->fetch) {
            my $change = $plan->get($row->[0]);
            is $row->[1], $change->script_hash,
                'Should have updated script hash for ' . $change->name;
        }

        # Make sure no other projects were updated.
        $sth = $engine->dbh->prepare(
            'SELECT change_id, script_hash FROM changes WHERE project <> ?',
        );
        $sth->execute($plan->project);
        while (my $row = $sth->fetch) {
            is $row->[1], $row->[0],
                'Change ID and script hash should be ' . substr $row->[0], 0, 6;
        }

        ######################################################################

t/rework.t  view on Meta::CPAN


COMMIT;
EOF

# The note should have been required.
is_deeply \%request_params, {
    for => __ 'rework',
    scripts => [$deploy_file, $revert_file, $verify_file],
}, 'It should have prompted for a note';

# The plan file should have been updated.
ok $plan->load, 'Reload the plan file';
ok my @steps = $plan->changes, 'Get the steps';
is @steps, 2, 'Should have two steps';
is $steps[0]->name, 'foo', 'First step should be "foo"';
is $steps[1]->name, 'foo', 'Second step should also be "foo"';
is_deeply [$steps[1]->requires], [dep 'foo@alpha'],
    'Reworked step should require the previous step';

is_deeply +MockOutput->get_info, [
    [__x(

t/rework.t  view on Meta::CPAN

file_not_exists_ok($_) for ($revert_file, $verify_file);
file_exists_ok($deploy_file3);
file_not_exists_ok($_) for ($revert_file3, $verify_file3);

# The note should have been required.
is_deeply \%request_params, {
    for => __ 'rework',
    scripts => [$deploy_file],
}, 'It should have prompted for a note';

# The plan file should have been updated.
ok $plan->load, 'Reload the plan file again';
ok @steps = $plan->changes, 'Get the steps';
is @steps, 4, 'Should have four steps';
is $steps[0]->name, 'foo', 'First step should be "foo"';
is $steps[1]->name, 'foo', 'Second step should also be "foo"';
is $steps[2]->name, 'bar', 'First step should be "bar"';
is $steps[3]->name, 'bar', 'Second step should also be "bar"';
is_deeply [$steps[3]->requires], [dep 'bar@beta', dep 'foo'],
    'Requires should have been passed to reworked change';
is_deeply [$steps[3]->conflicts], [dep '!dr_evil'],



( run in 0.560 second using v1.01-cache-2.11-cpan-05444aca049 )