Devel-Cover-Report-Coveralls
view release on metacpan or search on metacpan
CHANGELOG.md view on Meta::CPAN
## [1.0.0] - 2026-11-07
- Update the usage examples for GitHub Actions (with parallel builds), Travis CI and the other CI services, and document `COVERALLS_NO_FAIL` and `COVERALLS_PERL_SERVICE_NAME` (#58)
- Do not wrap the commit ID, names, e-mail addresses and message from `git log` in single quotes on Windows (#54)
- **Breaking:** `cover -report coveralls` exits with a non-zero status when the upload to Coveralls fails, so the CI job fails. Set `COVERALLS_NO_FAIL=1` to exit 0, which also covers a missing repo token, e.g. on pull requests from forks (#56)
- **Breaking:** On GitHub Actions, report as `github` with the values of the official coverage-reporter: the build number is the run (`GITHUB_RUN_ID`) instead of the commit, pull requests send their number and source branch instead of `<number>/merge...
- **Breaking:** Travis CI also needs `COVERALLS_REPO_TOKEN` (or `repo_token` in `.coveralls.yml`), as Coveralls requires it there too (#53)
- Support GitLab CI, read `BUILD_NUMBER` on Jenkins, treat `COVERALLS_PARALLEL=false` and `0` as off, and send the branch, commit and pull request that CircleCI, Jenkins and Azure Pipelines give (#53)
- Require Perl 5.20 or later, the version the current Devel::Cover needs (#57)
- Do not send credentials in git remote URLs, and send each remote once with its fetch URL (#51)
## [0.32.1] - 2023-05-19
- Fix test (thanks chylli-deriv)
## [0.32] - 2023-04-25
- Decode git log output (thanks voegelas)
- Some bug fix (thanks voegelas)
lib/Devel/Cover/Report/Coveralls.pm view on Meta::CPAN
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'),
t/01_basic.t view on Meta::CPAN
like $out, qr/^error: /m, 'still prints the error';
local $ENV{COVERALLS_NO_FAIL} = 'false';
$response = { success => 1, status => 200, reason => 'OK',
content => '{"url":"https://coveralls.io/jobs/1"}' };
($ok, $err, $out) = $run->();
ok $ok, 'returns on success';
like $out, qr{^register: https://coveralls.io/jobs/1$}m, 'prints the job';
};
subtest 'strip_url_credentials' => sub {
my %cases = (
'https://gitlab-ci-token:SECRET@gitlab.example.com/x/y.git' => 'https://gitlab.example.com/x/y.git',
'https://user@github.com/x/y.git' => 'https://github.com/x/y.git',
'https://user:p@ss@github.com/x/y.git' => 'https://github.com/x/y.git',
'ssh://git@github.com/x/y.git' => 'ssh://github.com/x/y.git',
'https://github.com/x/y.git' => 'https://github.com/x/y.git',
'https://github.com/x/y@z.git' => 'https://github.com/x/y@z.git',
'https://github.com?x=a@b' => 'https://github.com?x=a@b',
'git@github.com:x/y.git' => 'git@github.com:x/y.git',
'/path/to/repo.git' => '/path/to/repo.git',
);
for my $url (sort keys %cases) {
is Devel::Cover::Report::Coveralls::strip_url_credentials($url), $cases{$url}, $url;
}
};
subtest 'parse_git_remotes' => sub {
my $text = join '', map { "$_\n" }
"origin\thttps://gitlab-ci-token:SECRET\@gitlab.example.com/x/y.git (fetch)",
"origin\thttps://gitlab-ci-token:SECRET\@gitlab.example.com/x/y.git (push)",
"upstream\tgit\@github.com:x/y.git (fetch)",
"upstream\tgit\@github.com:x/y.git (push)",
"local\tC:/Users/John Doe/repo (fetch)\r",
"local\tC:/Users/John Doe/repo (push)\r";
is_deeply Devel::Cover::Report::Coveralls::parse_git_remotes($text), [
{ name => 'origin', url => 'https://gitlab.example.com/x/y.git' },
{ name => 'upstream', url => 'git@github.com:x/y.git' },
{ name => 'local', url => 'C:/Users/John Doe/repo' },
], 'one fetch URL per remote, without credentials';
is_deeply Devel::Cover::Report::Coveralls::parse_git_remotes(''), [], 'no remotes';
is_deeply Devel::Cover::Report::Coveralls::parse_git_remotes(undef), [], 'git not available';
};
subtest 'get_git_info remotes' => sub {
my $inside = `git rev-parse --is-inside-work-tree 2>&1`;
plan skip_all => 'not in a git work tree' unless defined $inside && $inside =~ /^true/;
my @names = split /\n/, `git remote`;
( run in 2.314 seconds using v1.01-cache-2.11-cpan-3f962061493 )