Devel-Cover-Report-Coveralls

 view release on metacpan or  search on metacpan

lib/Devel/Cover/Report/Coveralls.pm  view on Meta::CPAN

use strict;
use warnings;
use 5.020;
our $VERSION = "1.0.0";

our $CONFIG_FILE = '.coveralls.yml';
our $API_ENDPOINT_STEM = '/api/v1/jobs';
our $API_ENDPOINT = 'https://coveralls.io';
our $SERVICE_NAME = 'coveralls-perl';

use Devel::Cover::DB;
use HTTP::Tiny;
use JSON::PP;
use YAML;
use Data::Dumper;

sub get_source {
    my ($file, $callback) = @_;

    my $source = '';
    my @coverage;

    open my $fh, '<', $file or warn("Unable to open $file: $!\n"), return;

    while (defined(my $l = <$fh>)) {
        chomp $l;
        my $n = $.;

        $source .= "$l\n";
        push @coverage, $callback->($n);
    }

    close($fh);

    $file =~ s!^blib/!!;

    return +{
        name => $file,
        source => $source,
        coverage => \@coverage,
    };
}

sub git_log {
    my $format = shift;

    my $text = '';

    # No quotes around the format: cmd.exe on Windows does not take single quotes as quotes, so git
    # would print them. The formats used here have no spaces and no characters a shell changes.
    my $command = "git log -1 --encoding=UTF-8 --pretty=format:$format";
    if (open(my $fh, '-|:encoding(UTF-8)', $command)) {
        $text = do { local $/; <$fh> };
        close $fh;
    }

    return $text;
}

# Turn the output of `git remote -v` into the list of remotes to send.
# Each remote is listed once (its fetch URL), and credentials are removed
# from the URL.
sub parse_git_remotes {
    my $text = shift;

    my @remotes;
    for my $line (split /\n/, defined $text ? $text : '') {
        # "<name>\t<url> (fetch)". The URL may contain spaces (a local path).
        next unless $line =~ /^(\S+)\t(.*) \(fetch\)\r?$/;
        push @remotes, +{ name => $1, url => strip_url_credentials($2) };
    }

    return \@remotes;
}

# Remove the user information from a URL with a scheme
# (https://user:pass@host/path -> https://host/path).
# scp-like URLs (git@host:path) cannot hold a password and are kept as they are.
sub strip_url_credentials {
    my $url = shift;
    $url =~ s!^([A-Za-z][A-Za-z0-9+.-]*://)[^/?#]*@!$1!;
    return $url;
}

sub get_git_info {
    my $git = {
        head => {
            id              => git_log('%H'),
            author_name     => git_log('%aN'),
            author_email    => git_log('%ae'),
            committer_name  => git_log('%cN'),
            committer_email => git_log('%ce'),
            message         => git_log('%s')
        },
        remotes => parse_git_remotes(scalar `git remote -v`),
    };
    my ($branch,) = grep { /^\* / } split( "\n", `git branch` );
    $branch =~ s/^\* //;
    $git->{branch} = $branch;

    if ($ENV{BUILD_SOURCEBRANCHNAME}) {
        $git->{branch} = $ENV{BUILD_SOURCEBRANCHNAME};
    }

    return $git;
}

# A switch in an environment variable (COVERALLS_PARALLEL, COVERALLS_NO_FAIL) is on unless it is
# unset, empty, "false" or "0", as COVERALLS_PARALLEL is in the official coverage-reporter.
sub is_enabled {
    my $value = shift;
    return defined $value && $value ne '' && $value ne 'false' && $value ne '0';
}

# Reads the response of the jobs API (an HTTP::Tiny response). Returns the URL of the job, or
# undef and the error to show.
sub parse_response {
    my $response = shift;
    my $content = $response->{content} // '';
    my $res = eval { decode_json $content };
    my $status = "$response->{status} $response->{reason}";
    if (!$res || ref $res ne 'HASH') {
        # HTTP::Tiny puts its own error (e.g. a failed connection) into the content, with status 599.
        # An error page from a proxy can be long, so only its start is shown.
        $content =~ s/\s+\z//;
        $content = substr($content, 0, 200) . '...' if length $content > 200;
        return (undef, "$status: $content");
    }
    # A job that was registered always has its URL.
    return ($res->{url}, undef) if $response->{success} && $res->{url};
    return (undef, $res->{message} || $status);
}

# The number of the pull request in the event payload of GitHub Actions, or undef.
sub github_event_pull_request {
    my $path = shift;
    return undef unless $path;
    open my $fh, '<:raw', $path or return undef;
    my $event = eval { local $/; decode_json scalar <$fh> } or return undef;



( run in 0.736 second using v1.01-cache-2.11-cpan-3f962061493 )