File Coverage

blib/lib/Dist/AutomationPolicy.pm
Criterion Covered Total %
statement 74 77 96.1
branch 20 28 71.4
condition 11 21 52.3
subroutine 17 17 100.0
pod 4 5 80.0
total 126 148 85.1


line stmt bran cond sub pod time code
1             package Dist::AutomationPolicy;
2              
3 2     2   585368 use v5.24;
  2         8  
4              
5 2     2   1316 use Moo;
  2         16909  
  2         10  
6              
7 2     2   3277 use Carp qw( croak );
  2         7  
  2         101  
8 2     2   12 use File::ShareDir qw( dist_file );
  2         3  
  2         128  
9 2     2   1082 use JSON::MaybeXS;
  2         24475  
  2         269  
10 2     2   3109 use JSON::Schema::Validate v0.7.0;
  2         127381  
  2         143  
11 2     2   24 use Path::Tiny qw( path );
  2         3  
  2         136  
12 2     2   1444 use PerlX::Maybe qw( maybe );
  2         5845  
  2         16  
13 2     2   1186 use Types::Common qw( ArrayRef Enum InstanceOf PositiveInt NonEmptyStr StrMatch );
  2         665057  
  2         24  
14              
15 2     2   8720 use experimental qw( postderef signatures );
  2         4  
  2         18  
16              
17 2     2   2671 use namespace::autoclean;
  2         40688  
  2         13  
18              
19             our $VERSION = 'v0.2.0';
20              
21             # ABSTRACT: generate and parse distribution automation policies
22              
23              
24             has version => (
25             is => 'ro',
26             isa => PositiveInt,
27             default => 1,
28             required => 1,
29             );
30              
31              
32             # Based on Types::Dist DistVersion but the version is optional
33              
34             # SPDX-SnippetBegin
35             # SPDX-SnippetCopyrightText: 2019 by Renee Baecker
36             # SPDX-License-Identifier: The Artistic License 2.0 (GPL Compatible)
37              
38             my $distname_re = qr{ ([A-Za-z][A-Za-z0-9]*) ( - [A-Za-z0-9]+ )* }xmns;
39             my $distversion_re = qr{ v? ( [0-9]+ ( \. [0-9]+ )* ) }xmns;
40             my $distfq_re = qr{$distname_re(-$distversion_re)?}n;
41              
42             # SPDX-SnippetEnd
43              
44             has distribution => (
45             is => 'ro',
46             isa => StrMatch[ qr{\A$distfq_re\z} ],
47             predicate => 1,
48             );
49              
50              
51             has description => (
52             is => 'ro',
53             isa => NonEmptyStr,
54             predicate => 1,
55             );
56              
57              
58             has document => (
59             is => 'ro',
60             isa => NonEmptyStr,
61             predicate => 1,
62             );
63              
64              
65             has code_generation => (
66             is => 'ro',
67             isa => Enum [qw( toolchain external_sources machine_generated )],
68             required => 1,
69             );
70              
71              
72             has automated_contributions => (
73             is => 'ro',
74             isa => Enum [qw( none comment issue code_request )],
75             required => 1,
76             );
77              
78              
79             has automated_actions => (
80             is => 'ro',
81             isa => Enum [qw( none comment issue code_request code_change release )],
82             required => 1,
83             );
84              
85              
86             has models => (
87             is => 'ro',
88             isa => ArrayRef [NonEmptyStr],
89             coerce => sub($val) {
90             return $val if ref($val) eq "ARRAY";
91             return [$val];
92             },
93 5     5   321 builder => sub($self) { return [] },
  5         7  
  5         5  
  5         11  
94             );
95              
96              
97             has filename => (
98             is => 'lazy',
99             isa => NonEmptyStr,
100             default => 'CPAN-META/automation-policy.json',
101             );
102              
103             my $json = JSON::MaybeXS->new( utf8 => 1, pretty => 1, canonical => 1 );
104              
105             my $file = path( dist_file( __PACKAGE__ =~ s/::/-/gr, "automation-policy-schema.json" ) );
106              
107             my $schema = JSON::Schema::Validate->new( $json->decode( $file->slurp_raw ), compile => 1, );
108              
109              
110 16     16 1 917 sub data($self) {
  16         23  
  16         18  
111             #<<<
112             return {
113 16 50       329 version => $self->version,
    50          
    100          
114             maybe distribution => $self->distribution,
115             maybe description => $self->has_description ? $self->description : undef,
116             maybe document => $self->has_document ? $self->document : undef,
117             code_generation => $self->code_generation,
118             automated_contributions => $self->automated_contributions,
119             automated_actions => $self->automated_actions,
120             maybe models => $self->models->[0] ? $self->models : undef,
121             };
122             #>>>
123             }
124              
125              
126 2     2 1 997 sub validate( $self, $data = undef ) {
  2         6  
  2         5  
  2         4  
127 2   33     15 $data //= $self->data;
128 2         14 return $schema->is_valid( $data );
129             }
130              
131              
132 2     2 1 5150 sub to_json($self) {
  2         5  
  2         5  
133 2         6 return $json->encode( $self->data );
134             }
135              
136              
137 9     9 0 598403 sub BUILDARGS( $, @args ) {
  9         24  
  9         11  
138              
139 9 50 66     40 if ( @args == 1 && !ref( $args[0] ) ) {
140 0         0 unshift @args, "template";
141             }
142              
143 9 100 66     58 my %args = ( @args == 1 && ref( $args[0] ) eq "HASH" ) ? $args[0]->%* : @args;
144              
145 9 100       25 if ( my $version = $args{version} ) {
146 4 50 33     36 croak "unsupported version '${version}'"
147             if PositiveInt->check($version) && $version != 1;
148             }
149              
150              
151 9 100       143 if ( my $template = delete $args{template} ) {
152              
153 3         23 my %templates = (
154              
155             no_automation => {
156             code_generation => "toolchain",
157             automated_contributions => "none",
158             automated_actions => "comment",
159             },
160              
161             issues_only => {
162             code_generation => "toolchain",
163             automated_contributions => "issue",
164             automated_actions => "issue",
165             },
166              
167             human_supervised => {
168             code_generation => "machine_generated",
169             automated_contributions => "code_request",
170             automated_actions => "code_request",
171             },
172              
173             data_driven_updates => {
174             code_generation => "external_sources",
175             automated_contributions => "issue",
176             automated_actions => "release",
177             },
178              
179             full_automation => {
180             code_generation => "code_generation",
181             automated_contributions => "code_request",
182             automated_actions => "release",
183             },
184              
185             );
186              
187 3 50       19 if ( my $match = $templates{$template} ) {
188              
189 3         8 for my $attr ( keys $match->%* ) {
190 9   66     32 $args{$attr} //= $match->{$attr};
191             }
192              
193             }
194             else {
195 0         0 croak "Unsupported template: '${template}'";
196             }
197              
198              
199             }
200              
201 9         152 return \%args;
202             }
203              
204              
205 4     4 1 3183 sub from_json( $class, @args ) {
  4         7  
  4         7  
  4         7  
206              
207              
208 4 100 66     20 if ( @args == 1 && !ref( $args[0] ) ) {
209 1         2 unshift @args, "json";
210             }
211              
212 4 50 33     18 my %args = ( @args == 1 && ref( $args[0] ) eq "HASH" ) ? $args[0]->%* : @args;
213              
214 4 50       15 croak "json is required" unless defined $args{json};
215              
216 4 100       78 $args{json} = $json->decode( $args{json} ) unless ref( $args{json} );
217              
218 4 50       26 if ( my $res = $schema->validate( $args{json} ) ) {
219 4         5517 return $class->new( $args{json} );
220             }
221             else {
222 0           croak $_ for $res->errors;
223             }
224              
225             }
226              
227             1;
228              
229             __END__