App-Gitc

 view release on metacpan or  search on metacpan

bin/gitc-promote  view on Meta::CPAN

    to_undo { git "checkout $target" };
    git "branch -D $target" if not $integration_branch_existed;
    to_undo { git "branch $target $integrate" };
    git "push origin $integrate:$target @tag_refs";
};

# integrate with Eventum.  failing here is not worth rolling back
if (@new_tags) {
    my $tag_name = pop @new_tags;
    my @changesets = map { m{^cs/([^/]+)/to-} ? $1 : () } @new_tags;
    my $all = join ', ', @changesets;
    my $project = project_name();
    my %seen;
    for my $cs (@changesets) {
        my $its = its_for_changeset($cs);
        if ($its) {
            my $its_name = $its->label_service;
            my $issue = $its->get_issue($cs) or next;
            # only update each issue once
            next if $seen{ $its->issue_number($issue) }++;
            eval {
                my $what_happened = $its->transition_state({
                    command   => 'promote',
                    issue     => $issue,
                    target    => $target,
                    message   => "Promoted $project#$cs to $target "
                              .  "($tag_name) along with $all",
                    changeset => $cs,
                });
                warn $what_happened;
            };
            warn "$its_name Error: ".$@ if $@;
        }
    }

    # prevent trivial conflicts for the next 'gitc pass'
    if ( $cherry_pick and $target eq project_config()->{ open_onto } ) {
        git "fetch origin";
        git "checkout master" if $original_branch ne 'master';
        git "reset --hard origin/master";
        git "merge -s ours origin/$target";
        git "push origin master";
        git "checkout -f $original_branch" if $original_branch ne 'master';
    }
}

# reinstate any changes present when we started
git "stash apply $stash" if $stash;


########################## helper subs ###########################

# determine what we're promoting and where
sub parse_command_line {
    my @argv = @_;

    # extract structure from the command line
    my $target = pop @argv;
    my @changesets = grep { !/^-/ } @argv;

    # validate the promotion target
    die "You must specify a promotion target\n" if not $target;
    die "Invalid promotion target '$target'\n"
        if not defined environment_preceding($target);

    # validate changesets
    my $refs = validate_changesets( $target, @changesets );
    return ( $target, $refs, \@changesets );
}

# checks a list of changeset names for sanity. dies on anything bad.
# if the changesets are ok, it returns an arrayref of Git refs for
# those changesets
sub validate_changesets {
    my ( $target, @changesets ) = @_;
    return ( $target, [] ) if not @changesets;
    die "You may not cherry pick promote to prod\n"
        if !$force and $target eq 'prod' and @changesets;

    warn "Validating changesets\n";
    my @refs;
    my @already_promoted;
    my %seen;
    for my $changeset (@changesets) {
        die "You may not cherry pick '$changeset' to $target\n"
            if $changeset =~ m/^(master|test|stage|prod)$/;
        die   "You asked to promote '$changeset' twice.  Did you mean\n"
            . "to list it once or did you mistype some other changeset?\n"
            if $seen{$changeset}++;
        push @refs, full_changeset_name($changeset);
        push @already_promoted, $changeset
            if is_valid_ref("cs/$changeset/to-$target");
    }
    if (@already_promoted) {
        my $msg = "These changesets have already been promoted to $target:\n";
        $msg .= "  - $_\n" for @already_promoted;
        die $msg;
    }
    return \@refs;
}

# quickly locate any changeset dependencies that were not explicitly listed.
# takes a promotion target and a list of refs to promote.
# returns a list of the refs for those dependencies
sub find_missing_dependencies {
    my ( $target, @wanted ) = @_;
    my @extras = map { full_changeset_name($_) }
        unpromoted( \@wanted, "origin/$target" );

    # find refs that weren't explicitly listed
    my %extras = map { ( $_ => 1 ) } @extras;
    delete @extras{@wanted};
    return keys %extras;
}

# given a list of requested changeset refs and a list of missing dependency
# refs, prompts the user what to do and returns a new list of requested
# changeset refs
sub handle_missing_dependencies {
    my ( $wanted, $missing ) = @_;

    my @pretty = map { short_ref_name($_) } @$missing;
    sort_changesets_by_name(\@pretty);
    warn "The following changeset dependencies are missing:\n";
    warn "  - $_\n" for @pretty;
    die "Exiting promotion because of missing dependencies\n" if not -t STDIN;
    print STDERR 'What do you want to do? '
        . '(p)romote these too, e(x)it, see (d)etails: ';
    chomp ( my $choice = <STDIN> );
    if ( $choice eq 'p' ) {
        return ( @$wanted, @$missing );
    }
    elsif ( $choice eq 'd' ) {
        warn "\n";



( run in 0.644 second using v1.01-cache-2.11-cpan-39bf76dae61 )