App-SD

 view release on metacpan or  search on metacpan

lib/App/SD/CLI/Command/Ticket/Comment/Update.pm  view on Meta::CPAN

    $self->print_usage if $self->has_arg('h');

    $self->require_uuid;

    my $record = $self->_load_record;
    my @prop_set = $self->prop_set;

    # we don't want to do prop: value editing by default for comments since
    # it's just a blob of text
    if (!@prop_set || $self->has_arg('edit')) {
        my $updated_comment = $self->edit_text($record->prop('content'));
        $record->set_prop(name => 'content', value => $updated_comment);
        print "Updated comment " . $record->luid . " (" . $record->uuid . ")\n";
    } else {
        super();
    }
};

__PACKAGE__->meta->make_immutable;
no Any::Moose;

1;

lib/App/SD/CLI/Command/Ticket/Create.pm  view on Meta::CPAN

      $done =  $self->try_to_edit( template => \$template_to_edit, record => $record);
    }

};

sub process_template {
    my $self = shift;
    my %args = validate( @_, { template => 1, edited => 1, record => 1 } );

    my $record      = $args{record};
    my $updated     = $args{edited};
    ( my $props_ref, my $comment ) = $self->parse_record_template($updated);

    for my $prop ( keys %$props_ref ) {
        $self->context->set_prop( $prop => $props_ref->{$prop} );
    }

    my $error;
        local $@;
        eval { super(); } or chomp ($error = $@ || "Something went wrong!");

    return $self->handle_template_errors(
        error        => $error . "\n\nYou can bypass validation for a "
                        ."property by appending a ! to it.",
        template_ref => $args{template},
        bad_template => $updated,
        rtype        => $record->type,
    ) if ($error);

    $self->add_comment( content => $comment, uuid => $self->record->uuid )
        if $comment;

    return 1;
}


lib/App/SD/CLI/Command/Ticket/Update.pm  view on Meta::CPAN

      $done =  $self->try_to_edit( template => \$template_to_edit, record => $record);
    }

};

sub process_template {
    my $self = shift;
    my %args = validate( @_, { template => 1, edited => 1, record => 1 } );

    my $record      = $args{record};
    my $updated     = $args{edited};
    my ( $props_ref, $comment ) = $self->parse_record_template($updated);

    no warnings 'uninitialized';

    # if a formerly existing prop was removed from the output, delete it
    # (deleting is currently the equivalent of setting to '', and
    # we want to do this all in one changeset)
    for my $prop ( keys %{ $record->get_props } ) {
        next if ( grep { $_ eq $prop } $record->immutable_props );
        $props_ref->{$prop} = ''
            if (!exists $props_ref->{$prop} &&

lib/App/SD/CLI/Command/Ticket/Update.pm  view on Meta::CPAN

    # set the new props
    if ( keys %$props_ref ) {
        my $error;
        local $@;
        eval { $record->set_props( props => $props_ref ) }
            or $error = $@ || "Something went wrong!";

        return $self->handle_template_errors(
            error        => $error,
            template_ref => $args{template},
            bad_template => $updated
        ) if ($error);

        print 'Updated ticket ' . $record->luid . ' (' . $record->uuid . ")\n";
    } else {
        print "No changes in properties.\n";
    }

    $self->add_comment( content => $comment, uuid => $record->uuid ) if $comment;
    return 1;
}

lib/App/SD/ForeignReplica.pm  view on Meta::CPAN

    my $self = shift;
    my %args = validate( @_,
        { ticket => 1,
          changeset => { isa => 'Prophet::ChangeSet' }, start_time => 1} );

    my $earliest_valid_txn_date;

    # walk through every transaction on the ticket, starting with the latest

    for my $txn ( $self->get_txn_list_by_date($args{ticket}) ) {
        # walk backwards through all transactions on the ticket we just updated
        # Skip any transaction where the remote user isn't me, this might
        # include any transaction RT created with a scrip on your behalf

        next unless $txn->{creator} eq $self->foreign_username;

        # get the completion time _after_ we do our next round trip to rt to
        # try to make sure a bit of lag doesn't skew us to the wrong side of a
        # 1s boundary
       if (!$earliest_valid_txn_date){
            my $change_window =  time() - $args{start_time};

lib/App/SD/Replica/gcode/PullEncoder.pm  view on Meta::CPAN


    if ( $Net::Google::Code::VERSION lt '0.15' ) {
        die
"query support is only for Net::Google::Code version not less than 0.15"
          if $args{query};
        require Net::Google::Code::Issue::Search;
        my $search =
          Net::Google::Code::Issue::Search->new(
            project => $self->sync_source->project, );

        if ( $search->updated_after($last_changeset_seen_dt) ) {
            return $search->results;
        }
        else {
            return [];
        }
    }
    else {
        my $issue = Net::Google::Code::Issue->new(
            map { $_ => $self->sync_source->gcode->$_ }
              grep { $self->sync_source->gcode->$_ }
              qw/project email password/ );

        if ( keys %query == 0 ) {

            # we can use old updated_after method here if no query strings
            # loading issue by checking feeds update is more effective, if
            # possible
            local $Net::Google::Code::Issue::USE_HYBRID = 0;
            require Net::Google::Code::Issue::Search;
            my $search =
              Net::Google::Code::Issue::Search->new(
                project => $self->sync_source->project, );

            # 0 here is to not fallback to ->search method
            if ( $search->updated_after( $last_changeset_seen_dt, 0 ) ) {
                return $search->results;
            }
        }

        $query{can} ||= 'all';
        $query{max_results} ||= 1_000_000_000;
        delete $query{q} unless defined $query{q};
        my $results = $issue->list( %query,
            updated_min => $query{updated_min}
              && $query{updated_min} gt "$last_changeset_seen_dt"
            ? $query{updated_min}
            : "$last_changeset_seen_dt" );

        $_->load for @$results;
        return $results;
    }
}

sub _only_pull_tickets_modified_after {
    my $self = shift;

lib/App/SD/Replica/github.pm  view on Meta::CPAN


Tickets have two states: open or closed.

Once a ticket is created, the following modifications can be made to it:
- edit ticket body/title
- add a new comment
- edit a comment's body
- close a ticket (or reopen)

Thus, there is no "history" API call---we just get the current state, and we
can formulate our own history based on the list of comments, updated_at
timestamps, and comparing our state with the current state.

GitHub issues can also have arbitrary "labels" applied to them, but we're
currently ignoring this functionality.

=cut

sub BUILD {
    my $self = shift;

lib/App/SD/Replica/github/PullEncoder.pm  view on Meta::CPAN

=head2 translate_ticket_state

=cut

sub translate_ticket_state {
    my $self   = shift;
    my $ticket = shift;

    $ticket->{created_at} =
        App::SD::Util::string_to_datetime($ticket->{created_at});
    $ticket->{updated_at} =
        App::SD::Util::string_to_datetime($ticket->{updated_at});

    return $ticket;
}

=head2 find_matching_tickets QUERY

Returns a array of all tickets found matching your QUERY hash.

=cut

sub find_matching_tickets {
    my $self                   = shift;
    my %query                  = (@_);
    my $last_changeset_seen_dt = $self->_only_pull_tickets_modified_after()
      || DateTime->from_epoch( epoch => 0 );
    my $issue = $self->sync_source->github->issue;
    my @updated = grep {
        App::SD::Util::string_to_datetime($_->{updated_at}) > $last_changeset_seen_dt }
      ( @{ $issue->list('open') }, @{ $issue->list('closed') } );
    return \@updated;
}

sub _only_pull_tickets_modified_after {
    my $self = shift;

    my $last_pull = $self->sync_source->upstream_last_modified_date();
    return unless $last_pull;
    my $before = App::SD::Util::string_to_datetime($last_pull);
    $self->log_debug( "Failed to parse '" . $self->sync_source->upstream_last_modified_date() . "' as a timestamp. That means we have to sync ALL history") unless ($before);
    return $before;

lib/App/SD/Replica/github/PullEncoder.pm  view on Meta::CPAN


=cut

sub find_matching_transactions {
    my $self     = shift;
    my %args     = validate( @_, { ticket => 1, starting_transaction => 1 } );
    my @raw_txns =
      @{ $self->sync_source->github->issue->comments( $args{ticket}->{number} ) };

    for my $comment (@raw_txns) {
        $comment->{updated_at} =
          App::SD::Util::string_to_datetime( $comment->{updated_at} );
        $comment->{created_at} =
          App::SD::Util::string_to_datetime( $comment->{created_at} );
    }

    my @txns;
    for my $txn ( sort { $a->{id} <=> $b->{id} } @raw_txns ) {
        my $txn_date = $txn->{updated_at}->epoch;

        # Skip things we know we've already pulled
        next if $txn_date < ( $args{'starting_transaction'} || 0 );

        # Skip things we've pushed
        next if (
            $self->sync_source->foreign_transaction_originated_locally(
                $txn_date, $args{'ticket'}->{number}
            )
          );

lib/App/SD/Replica/lighthouse/PullEncoder.pm  view on Meta::CPAN


=cut

sub find_matching_tickets {
    my $self                   = shift;
    my %args                   = (@_);
    my $last_changeset_seen_dt = $self->_only_pull_tickets_modified_after()
      || DateTime->from_epoch( epoch => 0 );
    my @tickets =
      $self->sync_source->lighthouse->tickets( query => $args{query} );
    my @updated = map { $_->load( $_->number ); $_ }
      grep { $_->{updated_at} ge $last_changeset_seen_dt } @tickets;
    return \@updated;
}

sub _only_pull_tickets_modified_after {
    my $self = shift;

    my $last_pull = $self->sync_source->upstream_last_modified_date();
    return unless $last_pull;
    my $before = App::SD::Util::string_to_datetime($last_pull);
    $self->log_debug( "Failed to parse '" . $self->sync_source->upstream_last_modified_date() . "' as a timestamp. That means we have to sync ALL history") unless ($before);
    return $before;

lib/App/SD/Replica/rt/PullEncoder.pm  view on Meta::CPAN


=cut

sub find_matching_tickets {
    my $self = shift;
    my %args = validate(@_,{query => 1});
    my $query = $args{query};
    # If we've ever synced, we can limit our search to only newer things
    if ( my $before = $self->_only_pull_tickets_modified_after ) {
       $query = "($query) AND LastUpdated >= '" . $before->ymd('-') . " " . $before->hms(':') . "'";
        $self->sync_source->log( "Skipping all tickets not updated since " . $before->iso8601 );
    }
    return [map {
        Prophet::CLI->end_pager();
        # squelch chatty RT::Client::REST "Unknown key" warnings unless debugging turned on
        local $SIG{__WARN__} = sub { $self->sync_source->log_debug(@_) };
        my $hash = $self->sync_source->rt->show( type => 'ticket', id => $_ );
        $hash->{id} =~ s|^ticket/||g;
        $hash
    } $self->sync_source->rt->search( type => 'ticket', query => $query )];
}

lib/App/SD/Replica/rt/PullEncoder.pm  view on Meta::CPAN

    dependedonby    => 'depended_on_by',
    hasmember       => 'members',
    memberof        => 'member_of',
    priority        => 'priority_integer',
    resolved        => 'completed',
    due             => 'due',
    creator         => 'creator',
    timeworked      => 'time_worked',
    timeleft        => 'time_left',
    timeestimated   => 'time_estimated',
    lastupdated     => '_delete',
    created         => 'created',
    queue           => 'queue',
    starts          => '_delete',
    started         => '_delete',
);

sub translate_status {
    my $self = shift;
    my $status = shift;

lib/App/SD/Replica/trac/PullEncoder.pm  view on Meta::CPAN


sub transcode_create_txn {
    my $self        = shift;
    my $txn         = shift;
    my $create_data = shift;
    my $final_data = shift;
    my $ticket      = $txn->ticket;
    # this sequence_no only works because trac tickets only allow one update
    # per ticket per second.
    # we decrement by 1 on the off chance that someone created and
    # updated the ticket in the first second
    my $changeset = Prophet::ChangeSet->new(
        {   original_source_uuid => $self->sync_source->uuid_for_remote_id( $ticket->id ),
            original_sequence_no => ( $ticket->created->epoch-1),
            creator => $self->resolve_user_id_to( email_address => $create_data->{reporter} ),
            created => $ticket->created->ymd ." ".$ticket->created->hms
        }
    );

    my $change = Prophet::Change->new(
        {   record_type => 'ticket',

lib/App/SD/Test.pm  view on Meta::CPAN

Updates the ticket #ID, passing ARGS along to the update command.

Returns nothing interesting.

=cut

sub update_ticket_ok {
    my ($id, @args) = (@_);
    local $Test::Builder::Level = $Test::Builder::Level + 1;
    run_output_matches( 'sd', [ 'ticket', 'update', $id, '--', @args ],
        [qr/ticket \d+\s+\([^)]*\)\s+updated\./i]
    );
}

=head2 create_ticket_comment_ok ARGS

Creates a new ticket comment, passing ARGS along to the creation command.

Returns a list of the luid and uuid of the newly created comment.

=cut

t/sd-attachments.t  view on Meta::CPAN

    ],
    [],
    "Found the attachment"
);
run_output_matches(
    'sd',
    [   qw/ticket attachment update --uuid/, $attachment_uuid,
        '--',
        qw/--name/,                          "plague_recipe.doc"
    ],
    [qr/Attachment \d+ \($attachment_uuid\) updated/],
    [],
    "updated the attachment"
);
run_output_matches(
    'sd',
    [ qw/ticket attachment show --batch --uuid/, $attachment_uuid ],
    [  
        qr/id: (\d+) \($attachment_uuid\)/, 
        "content: stub",
        "content_type: text/plain",
        qr/created: \d{4}-\d{2}-\d{2}.+/,
        qr/creator: /,

t/sd-comments.t  view on Meta::CPAN

    [],
    "Found the comment"
);

run_output_matches(
    'sd',
    [   qw/ticket comment update --uuid/, $comment_uuid,
        '--',
        qw/--content/,                    "I hate you"
    ],
    [qr/Comment \d+ \($comment_uuid\) updated/],
    [],
    "updated the comment"
);

run_output_matches(
    'sd',
    [ qw/ticket comment show --batch --uuid/, $comment_uuid ],
    [ qr/id: (\d+) \($comment_uuid\)/, 
        qr/I hate you/,
        qr/created: /i,
        qr/creator: /i,
        "original_replica: $replica_uuid",

t/sd-comments.t  view on Meta::CPAN

    [],
    "Found the comment $comment_uuid when we tried to search for all comments on a ticket by the ticket's uuid, $yatta_uuid"
);

run_output_matches(
    'sd',
    [   qw/ticket comment update --uuid/, $comment_uuid,
        '--',
        qw/--content/,                    "A\nmultiline\ncomment"
    ],
    [qr/Comment \d+ \($comment_uuid\) updated/],
    [],
    "updated the comment to a multiline content"
);

run_output_matches(
    'sd',
    [ qw/ticket comment show --batch --uuid/, $comment_uuid ],
    [ qr/id: (\d+) \($comment_uuid\)/, 
        qr/^content: A/,
        qr/^multiline$/,
        qr/^comment$/,
        qr/created: /i,

t/sd-dispatcher.t  view on Meta::CPAN

    [  qr/(\d+) YATTA new/]
);

run_output_matches( 'sd', [ 'list', 'ticket',  
    '--regex', '.' ],
    [  qr/(\d+) YATTA new/]
);

# test claim
run_output_matches( 'sd', [ 'ticket', 'claim', $yatta_id ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: new',
        'milestone: alpha',
        'component: core',
        'owner: ' . $ENV{PROPHET_EMAIL},
        qr/^created: \d{4}-\d{2}-\d{2}.+$/,
        qr/^creator: /,
        'reporter: ' . $ENV{PROPHET_EMAIL},
        "original_replica: " . replica_uuid,
    ]
);

# revert back the change so we can check the alias for claim, take
run_output_matches( 'sd', [ 'ticket', 'update', $yatta_id, '--', 'owner', '' ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: new',
        'milestone: alpha',
        'component: core',
        qr/^created: \d{4}-\d{2}-\d{2}.+$/,
        qr/^creator: /,
        'reporter: ' . $ENV{PROPHET_EMAIL},
        "original_replica: " . replica_uuid,
    ]
);

# test take
run_output_matches( 'sd', [ 'ticket', 'take', $yatta_id ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: new',
        'milestone: alpha',
        'component: core',
        'owner: ' . $ENV{PROPHET_EMAIL},
        qr/^created: \d{4}-\d{2}-\d{2}.+$/,
        qr/^creator: /,
        'reporter: ' . $ENV{PROPHET_EMAIL},
        "original_replica: " . replica_uuid,
    ]
);

# test resolve
run_output_matches( 'sd', [ 'ticket', 'resolve', $yatta_id ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: closed',
        'milestone: alpha',
        'component: core',
        'owner: ' . $ENV{PROPHET_EMAIL},
        qr/^created: \d{4}-\d{2}-\d{2}.+$/,
        qr/^creator: /,
        'reporter: ' . $ENV{PROPHET_EMAIL},
        "original_replica: " . replica_uuid,
    ]
);

# revert that change so we can test resolve's alias, close
run_output_matches( 'sd', [ 'ticket', 'update', $yatta_id, '--', 'status', 'new' ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: new',
        'milestone: alpha',
        'component: core',
        'owner: ' . $ENV{PROPHET_EMAIL},
        qr/^created: \d{4}-\d{2}-\d{2}.+$/,
        qr/^creator: /,
        'reporter: ' . $ENV{PROPHET_EMAIL},
        "original_replica: " . replica_uuid,
    ]
);

# test close
run_output_matches( 'sd', [ 'ticket', 'close', $yatta_id ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: closed',
        'milestone: alpha',
        'component: core',
        'owner: ' . $ENV{PROPHET_EMAIL},
        qr/^created: \d{4}-\d{2}-\d{2}.+$/,
        qr/^creator: /,
        'reporter: ' . $ENV{PROPHET_EMAIL},
        "original_replica: " . replica_uuid,
    ]
);

# test give
run_output_matches( 'sd', [ 'ticket', 'give', $yatta_id, 'jesse@bestpractical.com' ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: closed',
        'milestone: alpha',
        'component: core',
        'owner: jesse@bestpractical.com',
        qr/^created: \d{4}-\d{2}-\d{2}.+$/,
        qr/^creator: /,
        'reporter: ' . $ENV{PROPHET_EMAIL},
        "original_replica: " . replica_uuid,
    ]
);

run_output_matches( 'sd', [ 'ticket', 'assign', $yatta_id, 'spang@bestpractical.com' ],
    [ "Ticket $yatta_id ($yatta_uuid) updated." ]
);

run_output_matches( 'sd', [ 'ticket', 'basics', '--batch', '--id', $yatta_id ],
    [
        "id: $yatta_id ($yatta_uuid)",
        'summary: YATTA',
        'status: closed',
        'milestone: alpha',
        'component: core',
        'owner: spang@bestpractical.com',

t/sd-hm/update.t  view on Meta::CPAN

            [ 'clone', '--from', $sd_hm_url, '--non-interactive' ] );

    run_output_matches( 'sd', [qw(ticket list --regex .)], [qr/(.*?)(?{ $yatta_uuid = $1 }) YATTA (.*)/] );
    ( $ret, $out, $err ) = run_script( 'sd', [ qw(ticket show --batch --id), $yatta_uuid ] );
    diag($out);
    diag($err);
    ($yatta_id, $yatta_uuid) = ($1, $2) if $out =~ /^id: (\d+)\s*\((.*)\)/m;
}

is_script_output( 'sd', [ qw(ticket update --uuid), $yatta_uuid, qw(-- --summary BLABLA) ],
    [qr/ticket \d+ \(\Q$yatta_uuid\E\) updated./i], # stdout
    [undef],             # stderr
    "updated summary"
);
{
    my ( $ret, $out, $err ) = run_script( 'sd', [ 'push','--to', $sd_hm_url ] );

    my $task = BTDT::Model::Task->new( current_user => $GOODUSER );
    ok( $task->load_by_cols( summary => 'BLABLA' ), "loaded a task" );
    is( $task->id, $remote_id, "the same task" );
}

t/sd-log.t  view on Meta::CPAN

        qr/status: set to new/,
        qr/milestone: set to alpha/,
        qr/reporter: set to $ENV{PROPHET_EMAIL}/,
        qr/^$/,
    ], [], "log output is correct",
);
# change a prop
run_output_matches( 'sd', [ 'ticket',  
    'update', '--uuid', $log_uuid, '--', '--reporter', 'foo@bar.com',
    ],
    [qr/Ticket $log_id \($log_uuid\) updated/], #stdout
   [], # stderr
   "deleting a prop went ok",
);
# check the log
run_output_matches( 'sd', [ 'log', 'LATEST' ],
    [
        '',
        qr/^=+/,
        qr/^\d{4}-\d{2}-\d{2}.+ - $ENV{PROPHET_EMAIL} : \d+\@\Q$ENV{PROPHET_REPO}\E$/,
        qr/^Ticket \d+ \(logs rock!\)$/,

t/sd-redmine/basic.t  view on Meta::CPAN


diag "sd clone --from ${sd_redmine_url} --non-interactive";

my ( $ret, $out, $err )
    = run_script( 'sd',
        [ 'clone', '--from', $sd_redmine_url, '--non-interactive' ] );
is(count_tickets_in_sd(),5, "the total cloned tickets is 5.");

note "close one of them, push it to server.";
( $ret, $out, $err ) = run_script( 'sd', [ "ticket", "update", $tickets[0]->id, "--", "status=Closed" ] );
like( $out, qr/^Ticket(.*)updated/ );
diag($out);
diag($err);

( $ret, $out, $err ) = run_script( 'sd', [ 'push', '--to', $sd_redmine_url ] );
diag($out);
diag($err);

note "verify the update with Net::Redmine";
my $ticket = $r->lookup(ticket => { id => $tickets[0]->id });

t/sd-rt/basic.t  view on Meta::CPAN

    = run_script( 'sd',
    [ 'ticket', 'comment', $helium_id, '--content', 'helium is a noble gas' ] );
ok( $ret, $out );
like( $out, qr/Created comment/ );


{    # resolve a ticket
    ( $ret, $out, $err )
        = run_script( 'sd', [ 'ticket', 'resolve', $helium_id ] );
    ok( $ret, $out );
    like( $out, qr/Ticket .* updated/ );

    ( $ret, $out, $err ) = run_script( 'sd', [ 'push', '--to', $sd_rt_url ] );
    ok( $ret, $out );

    ( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_rt_url ] );
    ok( $ret, $out );

    my $fetched_ticket = RT::Client::REST::Ticket->new(
        rt => $rt,
        id => $ticket->id

t/sd-rt/rt-auto-open-conflict.t  view on Meta::CPAN

( $ret, $out, $err ) = run_script( 'sd', [ 'ticket', 'comment', $helium_id, '--content', 'helium is a noble gas' ] );
ok( $ret, $out );
like( $out, qr/Created comment/ );
diag($out);
diag($err);
{    # resolve a ticket

    diag("Resolve a ticket in SD");
    ( $ret, $out, $err ) = run_script( 'sd', [ 'ticket', 'resolve', $helium_id ] );
    ok( $ret, $out );
    like( $out, qr/Ticket .* updated/ );
    sleep(1);
    diag("Push to rt");
    ( $ret, $out, $err ) = run_script( 'sd', [ 'push', '--to', $sd_rt_url, '--prefer', 'source' ] );
    ok( $ret, $out );
    diag($err);
    sleep(1);
    ( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_rt_url, '--prefer', 'source'] );
    ok( $ret, $out );
    diag($err);
    my $fetched_ticket = RT::Client::REST::Ticket->new(

t/sd-rt/sd-rt-permission.t  view on Meta::CPAN

    ok($ret);

    run_output_matches( 'sd', [ 'ticket', 'list', '--regex', '.' ],
        [qr/(.*?)(?{ $flyman_id = $1 }) Fly Man new/] );
};

diag("without write rights, ensure that trying to push it gives a sane error");

as_alice {
    run_output_matches('sd', ['ticket', 'update', $flyman_id, '--', 'priority=20'],
        [qr/ticket .*$flyman_id.* updated/i],
    );

    ($ret, $out, $err) = run_script('sd', ['push', '--to',  $alice_rt_url]);
    ok($ret);
    like($err, qr/You are not allowed to modify ticket $ticket_id/);

    SKIP: {
        skip "test needs fixing", 1;

        # we should know exactly how many changesets there are.. used to be 1,

t/sd-rt/sd-rt-permission.t  view on Meta::CPAN

    TODO: {
        local $TODO = "we mark all changesets as merged even if some failed";
    }
};

$ticket = RT::Client::REST::Ticket->new(
    rt      => $root,
    id      => $ticket_id,
)->retrieve;

is($ticket->priority, 10, "ticket not updated");

diag("give write rights, try to push again");

$alice->PrincipalObj->GrantRight(Right => 'ModifyTicket', Object => $queue);

as_alice {
    ($ret, $out, $err) = run_script('sd', ['push', '--to',  $alice_rt_url]);
    ok($ret);
    TODO: {
        local $TODO = "Prophet thinks it already merged this changeset!";
    }
};

$ticket = RT::Client::REST::Ticket->new(
    rt      => $root,
    id      => $ticket_id,
)->retrieve;

TODO: {
    local $TODO = "ticket is NOT updated!";
    is($ticket->priority, 20, "ticket updated");
}

diag("move the ticket, ensure it doesn't just disappear");
$ticket = RT::Client::REST::Ticket->new(
    rt       => $root,
    id       => $ticket_id,
    queue    => $refuge->Id,
    status   => 'stalled',
)->store;

t/sd-rt/sd-rt-permission.t  view on Meta::CPAN

        [qr/Fly Man new/] );
};

diag("update the moved ticket");
$alice->PrincipalObj->GrantRight(Right => 'ModifyTicket', Object => $refuge);
$alice->PrincipalObj->GrantRight(Right => 'SeeQueue',     Object => $refuge);
$alice->PrincipalObj->GrantRight(Right => 'ShowTicket',   Object => $refuge);

as_alice {
    run_output_matches('sd', ['ticket', 'resolve', $flyman_id],
        [qr/ticket .*$flyman_id.* updated/i],
    );

    ($ret, $out, $err) = run_script('sd', ['push', '--to',  $alice_rt_url]);
    ok($ret);
};

$ticket = RT::Client::REST::Ticket->new(
    rt       => $root,
    id       => $ticket_id,
)->retrieve;

is($ticket->status, 'resolved', "ticket is updated");

t/sd-trac/basic.t  view on Meta::CPAN

# Update a ticket in trac
#

can_ok( $ticket, 'load' );
ok( $ticket->load(1) );
like( $ticket->state->{'summary'}, qr/pony/ );
like( $ticket->summary, qr/moose/, "The summary looks like a moose" );

sleep 2; # to make trac happy
ok( $ticket->update( summary => 'The product does not contain a pony' ),
    "updated!" );
unlike( $ticket->summary, qr/moose/, "The summary does not look like a moose" );

my ($fh, $filename) = File::Temp::tempfile(SUFFIX => '.txt', UNLINK => 1);
print $fh "TIMTOWTDI\n";
close $fh;
sleep 2; # to make trac happy
ok($ticket->attach( file => $filename ), "Attaching file.");

my $history = $ticket->history;
ok( $history, "The ticket has some history" );

t/sd-trac/basic.t  view on Meta::CPAN

like( $settings,
qr/statuses: \["new","accepted","assigned","reopened","closed","fixed","invalid","wontfix","duplicate","worksforme","test_resolution"\]/,
'statuses setting'
);


# 
# Modify the ticket we pulled from trac

( $ret, $out, $err ) = run_script( 'sd', [ "ticket", "update", $pony_id, "--", "status=closed" ] );
like( $out, qr/^Ticket(.*)updated/ );
diag($out);
diag($err);
( $ret, $out, $err ) = run_script( 'sd' => [ "ticket", "basics", $pony_id, "--batch" ] );

like( $out, qr/status: closed/ );
diag("The pony is $pony_id");
my $new_ticket = Net::Trac::Ticket->new( connection => $trac );
ok( $new_ticket->load(1) );
is( $new_ticket->status, 'new', "The ticket is new before we push to trac" );

t/sd-validation.t  view on Meta::CPAN

    ],
   [],  # stdout
    [qr/Validation error for 'component': 'awesome' is not a valid component/,
    qr/Validation error for 'status': 'super' is not a valid status/], # stderr
    "Despite the magic power phrase of 'yatta', super is not a valid bug status"
);

run_output_matches( 'sd', [ 'ticket',  
    'update', '--uuid', $yatta_uuid, '--', '--status', 'stalled'
    ],
   [qr/Ticket \d+ \($yatta_uuid\) updated./], # stdout
   [], # stderr
   "Setting the status to stalled went ok"

);

run_output_matches( 'sd', [ 'ticket',  
    'list', '--regex', '.' ],
    [ qr/(\d+) YATTA stalled/]
);

t/sd-validation.t  view on Meta::CPAN

run_output_matches( 'sd', [ 'ticket',  
    'list', '--regex', '.' ],
    [ qr/(\d+) YATTA stalled/]
);


# check to make sure that we can force-set props
run_output_matches( 'sd', [ 'ticket',  
    'update', '--uuid', $yatta_uuid, '--', '--status', 'super!'
    ],
    [qr/Ticket $yatta_id \($yatta_uuid\) updated/], #stdout
   [], # stderr
   "we can force-set an invalid prop"
);


1;



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