Compare commits

...

18 Commits
dummy ... main

Author SHA1 Message Date
Yanick Champoux 5b832b6477 fix: test was expecting to be in a git repo 2022-07-25 16:51:59 -04:00
Yanick Champoux 4c315f9a04 dzil setup 2022-07-25 14:01:04 -04:00
Yanick Champoux f012489e34 fix typo 2022-07-25 12:21:08 -04:00
Yanick Champoux ba2ba193cc updating the changelog 2022-07-25 12:19:32 -04:00
Yanick Champoux ffe113a10c Merge branch 'documentation' 2022-07-25 12:13:03 -04:00
Yanick Champoux 8952b38553 updating the changelog 2022-07-25 12:12:57 -04:00
Yanick Champoux 868e111930 docs for ::Version 2022-07-25 12:08:20 -04:00
Yanick Champoux 92d3e10756 docs for ::Validate 2022-07-25 12:02:24 -04:00
Yanick Champoux ec4fee9e69 docs for ::Schema 2022-07-25 11:58:17 -04:00
Yanick Champoux 3b4c019dcc docs for ::Init 2022-07-25 11:55:42 -04:00
Yanick Champoux 0fa5f2a9a4 docs for ::GitGather 2022-07-25 11:45:03 -04:00
Yanick Champoux 364ad6d587 doc for ::Bump 2022-07-25 11:40:56 -04:00
Yanick Champoux 615cc0f581 doc for ::Add 2022-07-25 11:34:24 -04:00
Yanick Champoux d555b10db9 add --no-next for prod render 2022-07-25 11:32:27 -04:00
Yanick Champoux dcc2f7192c make main changelord an alias for 'print' 2022-07-25 11:27:16 -04:00
Yanick Champoux ae29ae0ebf doc for ::Print 2022-07-25 11:21:03 -04:00
Yanick Champoux 3ff7bfd9f3 add a 'git-gather' command 2022-07-25 10:44:25 -04:00
Yanick Champoux 1ad1e9810c add stats to the changes 2022-07-20 14:28:52 -04:00
29 changed files with 692 additions and 244 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
.build
.perl-version
.pls_cache/
App-Changelord-*

17
.travis.yml Normal file
View File

@ -0,0 +1,17 @@
---
before_install:
- export HARNESS_OPTIONS=j10:c HARNESS_TIMER=1
- git config --global user.name "Dist Zilla Plugin TravisCI"
- git config --global user.email $HOSTNAME":not-for-mail@travis-ci.com"
install:
- cpanm --with-recommends --installdeps -n .
language: perl
matrix:
include:
- perl: '5.22'
- perl: '5.24'
- perl: '5.26'
- perl: '5.28'
- perl: '5.30'
script:
- prove -l t

13
AUTHOR_PLEDGE Normal file
View File

@ -0,0 +1,13 @@
# CPAN Covenant for App-Changelord
I, Yanick Champoux <yanick@babyl.ca>, hereby give modules@perl.org permission to grant co-maintainership
to App-Changelord, if all the following conditions are met:
(1) I haven't released the module for a year or more
(2) There are outstanding issues in the module's public bug tracker
(3) Email to my CPAN email address hasn't been answered after a month
(4) The requester wants to make worthwhile changes that will benefit CPAN
In the event of my death, then the time-limits in (1) and (3) do not apply.

View File

@ -1,89 +0,0 @@
---
project:
name: App::Changeman
homepage: https://git.babyl.ca/yanick/App-Changelord
releases:
- version: v3.0.2
date: 2022-06-17
changes: ~
- version: v3.0.1
date: 2022-06-17
changes: ~
- version: v3.0.0
date: 2022-06-17
changes: ~
- version: v2.0.0
date: 2022-06-17
changes: ~
- version: v1.2.3
date: 2022-01-02
changes:
- desc: doing the thing
type: feat
- |
## [2.0.0](https://github.com/yanick/json-schema-shorthand/compare/v1.0.0...v2.0.0) (2020-08-24)
### BREAKING CHANGES
* things should continue to work as normal, but since to
typescript is kinda of a big deal, I'm taking no chance.
### Features
* move project to typescript ([ca3429d](https://github.com/yanick/json-schema-shorthand/commit/ca3429db04ebc183d2b5c000e8d3d2b297a1e001))
## [1.0.0](https://github.com/yanick/json-schema-shorthand/compare/v0.3.2...v1.0.0) (2020-07-30)
### Features
* add allOf, anyOf, oneOf, not shorthands ([b47ee27](https://github.com/yanick/json-schema-shorthand/commit/b47ee27671a4861756a74f4ad6b0dc10d10f1a3c))
### [0.3.2](https://github.com/yanick/json-schema-shorthand/compare/v0.3.1...v0.3.2) (2020-01-31)
### Bug Fixes
* remove shrinkwrap.yaml from repo ([baf6ca5](https://github.com/yanick/json-schema-shorthand/commit/baf6ca5c27f9f7723afa48796da0627160579839))
## 0.3.1 (https://github.com/yanick/json-schema-shorthand/compare/v0.3.0...v0.3.1) (2020-01-31)
### Bug Fixes
* bump dependency versions to latest (685e13e (https://github.com/yanick/json-schema-shorthand/commit/685e13eba976fda5ba956a105ac2fb039e232860))
## v0.3.0 2018-02-14
## Improvements
* New shortcut: '$foo' expands to be `$ref: foo`.
* New 'range' shortcut.
* New shortcut functions for types `object`, `array`, `number`,
`integer`, and `string`.
* Add `add_definition` helper function.
### Bug Fixes
* `shorthand()` deals gracefully with `null` argument.
## 0.2.0 2017-01-03
* Properties can be made required via a '!' suffix.
* Drop Mocha and Chai for TAP for testing.
- version: 0.1.0
date: 2016-08-01
changes:
- "Recurse down 'allOf', 'oneOf', 'anyOf', 'not'."
- Add 'install' and 'synopsis' sections in doc.
- version: 0.0.1
date: 2016-07-31
changes:
- Initial release
change_types:
- feat:
level: minor
title: Features
keywords: []
- fix:
level: patch
title: Bug fixes
keywords: []

View File

@ -1,59 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [2.0.0](https://github.com/yanick/json-schema-shorthand/compare/v1.0.0...v2.0.0) (2020-08-24)
### ⚠ BREAKING CHANGES
* things should continue to work as normal, but since to
typescript is kinda of a big deal, I'm taking no chance.
### Features
* move project to typescript ([ca3429d](https://github.com/yanick/json-schema-shorthand/commit/ca3429db04ebc183d2b5c000e8d3d2b297a1e001))
## [1.0.0](https://github.com/yanick/json-schema-shorthand/compare/v0.3.2...v1.0.0) (2020-07-30)
### Features
* add allOf, anyOf, oneOf, not shorthands ([b47ee27](https://github.com/yanick/json-schema-shorthand/commit/b47ee27671a4861756a74f4ad6b0dc10d10f1a3c))
### [0.3.2](https://github.com/yanick/json-schema-shorthand/compare/v0.3.1...v0.3.2) (2020-01-31)
### Bug Fixes
* remove shrinkwrap.yaml from repo ([baf6ca5](https://github.com/yanick/json-schema-shorthand/commit/baf6ca5c27f9f7723afa48796da0627160579839))
## 0.3.1 (https://github.com/yanick/json-schema-shorthand/compare/v0.3.0...v0.3.1) (2020-01-31)
### Bug Fixes
* bump dependency versions to latest (685e13e (https://github.com/yanick/json-schema-shorthand/commit/685e13eba976fda5ba956a105ac2fb039e232860))
## v0.3.0 2018-02-14
## Improvements
* New shortcut: '$foo' expands to be `$ref: foo`.
* New 'range' shortcut.
* New shortcut functions for types `object`, `array`, `number`,
`integer`, and `string`.
* Add `add_definition` helper function.
### Bug Fixes
* `shorthand()` deals gracefully with `null` argument.
## 0.2.0 2017-01-03
* Properties can be made required via a '!' suffix.
* Drop Mocha and Chai for TAP for testing.
## 0.1.0 2016-08-01
* Recurse down 'allOf', 'oneOf', 'anyOf', 'not'.
* Add 'install' and 'synopsis' sections in doc.
## 0.0.1 2016-07-31
* Initial release

31
CHANGELOG.yml Normal file
View File

@ -0,0 +1,31 @@
---
project:
name: App::Changelord
homepage: https://git.babyl.ca/yanick/App-Changelord
with_stats: 1
releases:
- version: NEXT
date: ~
changes:
- commit: b25e98fc57307fbede9382b31fd85f3cbbc72cf7
desc: ' test was expecting to be in a git repo'
type: fix
- version: v0.0.1
date: 2022-06-25
changes:
- Initial release
- desc: 'code churn: 27 files changed, 1281 insertions(+)'
type: stats
change_types:
- keywords:
- feat
level: minor
title: Features
- keywords:
- fix
level: patch
title: Bug fixes
- keywords:
- stats
level: patch
title: Statistics

128
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
yanick@babyl.ca.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

15
Changes
View File

@ -1,5 +1,14 @@
Revision history for App-Changeman
# Changelog for [App::Changelord][homepage]
{{$NEXT}}
[homepage]: https://git.babyl.ca/yanick/App-Changelord
## v0.0.1, 2022-06-25
* Initial release
### Statistics
* code churn: 27 files changed, 1281 insertions(+)
- First version, unleashed on an unsuspecting world.

39
MANIFEST Normal file
View File

@ -0,0 +1,39 @@
AUTHOR_PLEDGE
CHANGELOG.yml
CODE_OF_CONDUCT.md
CONTRIBUTORS
Changes
INSTALL
LICENSE
MANIFEST
META.json
META.yml
Makefile.PL
README.mkdn
SIGNATURE
bin/changelord
cpanfile
doap.xml
lib/App/Changelord.pm
lib/App/Changelord/Command/Add.pm
lib/App/Changelord/Command/Bump.pm
lib/App/Changelord/Command/GitGather.pm
lib/App/Changelord/Command/Init.pm
lib/App/Changelord/Command/Print.pm
lib/App/Changelord/Command/Schema.pm
lib/App/Changelord/Command/Validate.pm
lib/App/Changelord/Command/Version.pm
lib/App/Changelord/Command/changelog-schema.yml
lib/App/Changelord/Role/ChangeTypes.pm
lib/App/Changelord/Role/Changelog.pm
lib/App/Changelord/Role/Render.pm
lib/App/Changelord/Role/Stats.pm
lib/App/Changelord/Role/Versions.pm
t/00-compile.t
t/00-report-prereqs.dd
t/00-report-prereqs.t
t/basic.t
t/render.t
t/stats.t
t/versions.t
xt/release/unused-vars.t

View File

@ -1,4 +1,6 @@
#!/usr/bin/env perl
# PODNAME: changelord
# ABSTRACT: cli tool for App::Changelord
use App::Changelord;

41
cpanfile Normal file
View File

@ -0,0 +1,41 @@
# This file is generated by Dist::Zilla::Plugin::CPANFile v6.025
# Do not edit this file directly. To change prereqs, edit the `dist.ini` file.
requires "CLI::Osprey" => "0";
requires "Git::Repository" => "0";
requires "JSON" => "0";
requires "JSON::Schema::Modern" => "0";
requires "List::AllUtils" => "0";
requires "Moo" => "0";
requires "Moo::Role" => "0";
requires "Path::Tiny" => "0";
requires "PerlX::Maybe" => "0";
requires "Version::Dotted::Semantic" => "0";
requires "YAML" => "0";
requires "YAML::XS" => "0";
requires "feature" => "0";
requires "perl" => "v5.36.0";
requires "warnings" => "0";
on 'test' => sub {
requires "ExtUtils::MakeMaker" => "0";
requires "File::Spec" => "0";
requires "IO::Handle" => "0";
requires "IPC::Open3" => "0";
requires "Test2::V0" => "0";
requires "Test::More" => "0";
requires "strict" => "0";
};
on 'test' => sub {
recommends "CPAN::Meta" => "2.120900";
};
on 'configure' => sub {
requires "ExtUtils::MakeMaker" => "0";
};
on 'develop' => sub {
requires "Test::More" => "0.96";
requires "Test::Vars" => "0";
};

View File

@ -1,7 +1,20 @@
name = App-Changeman
author = Yanick Champoux <yanick@babyl.dyndns.org>
name = App-Changelord
author = Yanick Champoux <yanick@babyl.ca>
license = Perl_5
copyright_holder = Yanick Champoux
copyright_year = 2022
[@YANICK]
version = v0.0.1
homepage=https://git.babyl.ca/yanick/App-Changelord
[@Filter]
-bundle=@YANICK
-remove=GithubMeta
-remove=ReadmeFromPod
-remove=Test::PAUSE::Permissions
-remove=PreviousVersion::Changelog
-remove=NextVersion::Semantic
-remove=ChangeStats::Git
-remove=CheckChangesHasContent
-remove=RunExtraTests
dev_branch=main

View File

@ -1,39 +1,45 @@
package App::Changelord;
# version next latest
# ABSTRACT: cli-based changelog manager
use 5.36.0;
use Moo;
use CLI::Osprey;
use CLI::Osprey
desc => 'changelog manager';
use YAML;
use List::AllUtils qw/ pairmap partition_by /;
use App::Changelord::Role::ChangeTypes;
option source => (
is => 'ro',
format => 's',
doc => 'changelog yaml file',
default => 'CHANGELOG.yml',
);
has changelog => ( is => 'lazy' );
sub _build_changelog($self) {
return YAML::LoadFile($self->source)
}
with 'App::Changelord::Role::ChangeTypes';
with 'App::Changelord::Role::Render';
sub run($self) {
no warnings 'utf8';
print $self->as_markdown;
App::Changelord::Command::Print->new(
parent_command => $self,
)->run;
}
subcommand $_ => 'App::Changelord::Command::' . ucfirst $_
for qw/ schema validate version bump init add/;
subcommand $_ => 'App::Changelord::Command::' . ucfirst $_ =~ s/-(.)/uc $1/er
for qw/ schema validate version bump init add git-gather print /;
1;
__END__
=head1 DESCRIPTION
C<App::Changelord> offers a collection of cli commands to
interact with a YAML-based CHANGELOG file format, from which
a Markdown CHANGELOG fit for general comsumption can be generated.
See the original blog entry in the C<SEE ALSO> section for the full
motivation.
For a list of the commands, C<changelord --help>, then to
get information on the individual commands C<changelord *subcommand* --man>.
=head1 SEE ALSO
L<Changelord, registrar of deeds extraordinaire|https://techblog.babyl.ca/entry/changelord> - the introducing blog entry.

View File

@ -3,15 +3,17 @@ package App::Changelord::Command::Add;
use 5.36.0;
use Moo;
use CLI::Osprey desc => 'add a change to the changelog';
use CLI::Osprey
desc => 'add a change to the NEXT release',
description_pod => <<'END';
Add a change entry to the NEXT release.
END
use PerlX::Maybe;
use Path::Tiny;
use App::Changelord::Command::Init;
has changelog => ( is => 'lazy' );
sub _build_changelog ($self) { $self->parent_command->changelog }
with 'App::Changelord::Role::Changelog';
# TODO validate the type
option type => (
@ -48,7 +50,7 @@ sub next_release($self) {
}
sub save_changelog($self) {
my $src = $self->parent_command->source;
my $src = $self->source;
path($src)->spew( App::Changelord::Command::Init::serialize_changelog($self) );
}
@ -63,6 +65,8 @@ sub run ($self) {
};
$self->save_changelog;
say "change added to the changelog";
}
'end of App::Changelog::Command::Add';

View File

@ -3,7 +3,11 @@ package App::Changelord::Command::Bump;
use 5.36.0;
use Moo;
use CLI::Osprey desc => 'bump next version';
use CLI::Osprey desc => 'bump next version',
description_pod => <<'END';
Set a version for the NEXT release based on the types of its changes.
Also set the release date of that release to today.
END
use Path::Tiny;
use JSON;
@ -11,13 +15,10 @@ use YAML qw/ Bless /;
use List::AllUtils qw/ first min uniq /;
use Version::Dotted::Semantic;
with 'App::Changelord::Role::Changelog';
with 'App::Changelord::Role::ChangeTypes';
has changelog => ( is => 'lazy' );
with 'App::Changelord::Role::Versions';
sub _build_changelog ($self) { $self->parent_command->changelog }
with 'App::Changelord::Role::GitRepo';
sub run ($self) {
my $bump = shift @ARGV;
@ -50,6 +51,12 @@ sub run ($self) {
$self->changelog->{releases}[0]{date} = sprintf "%d-%02d-%02d",
$time[5] + 1900, $time[4], $time[3];
if( $self->changelog->{project}{with_stats} ) {
push $self->changelog->{releases}[0]{changes}->@*, {
type => 'stats', desc => $self->stats
};
}
my $change = $self->changelog;
Bless($change)->keys(
[ uniq qw/
@ -66,7 +73,7 @@ sub run ($self) {
Bless($_)->keys( [ uniq qw/ version date changes /, sort keys %$_ ] );
}
path( $self->parent_command->source )->spew( YAML::Dump($change) );
path( $self->source )->spew( YAML::Dump($change) );
say "new version minted: $version";
}

View File

@ -0,0 +1,122 @@
package App::Changelord::Command::GitGather;
use v5.36.0;
use Moo;
use CLI::Osprey
desc => 'gather changes from git commit messages',
description_pod => <<'END_POD';
Inspects the git log of the current branch for commit
messages looking like change entries. If any are found, add them to the
changelog.
=head2 Lower bound of the git log
C<git-gather> will inspect the git log from the most recent of those
three points:
=over
=item The last change in the NEXT release having a C<commit> property.
=item The last tagged version.
=item The beginning of time.
=back
=head2 Change-like git message
Git messages are compared to the regular expression
configured at `project.commit_regex`. If none is found, it
defaults to
^(?<type>[^: ]+):(?<desc>.*?)(\[(?<ticket>[^\]]+)\])?$
The regular expression must capture a C<desc> field, and may
capture a C<type> and C<ticket> as well.
END_POD
use Path::Tiny;
with 'App::Changelord::Role::Changelog';
with 'App::Changelord::Role::Versions';
with 'App::Changelord::Role::ChangeTypes';
with 'App::Changelord::Role::GitRepo';
has commit_regex => (
is => 'lazy'
);
sub _build_commit_regex($self) {
my $regex = $self->changelog->{project}{commit_regex};
my $default = '^(?<type>[^: ]+):(?<desc>.*?)(\[(?<ticket>[^\]]+)\])?$';
if(!$regex) {
warn "project.commit_regex not configured, using the default /$default/\n";
$regex = $default;
}
return $regex;
}
sub lower_bound($self) {
# either the most recent commit in the current release
my @sha1s = grep { $_ } map { $_->{commit} } grep { ref } $self->next_release->{changes}->@*;
return pop @sha1s if @sha1s;
return $self->latest_version;
}
sub get_commits($self,$since=undef) {
return reverse $self->repo->run( 'log', '--pretty=format:%H %s', $since ? "$since.." : () );
}
sub munge_message($self,$message) {
my $regex = $self->commit_regex;
$message =~ s/(\S+) //;
my $commit = $1;
return () unless $message =~ qr/$regex/;
return { %+, commit => $commit };
}
sub save_changelog($self) {
my $src = $self->source;
path($src)->spew( App::Changelord::Command::Init::serialize_changelog($self) );
}
sub run ($self) {
say "let's check those git logs...";
# figure out lower bound
my $from = $self->lower_bound;
say "checking since ", ( $from || 'the dawn of time' );
my @messages = map { $self->munge_message($_) } $self->get_commits($from);
unless(@messages) {
say "\nno change detected";
return;
}
print "\n";
say " * ", $_->{desc} for @messages;
print "\n";
push $self->next_release->{changes}->@*, @messages;
$self->save_changelog;
say $self->source, " updated";
}
1;
__END__

View File

@ -12,13 +12,9 @@ use List::AllUtils qw/ first min uniq /;
use Version::Dotted::Semantic;
with 'App::Changelord::Role::ChangeTypes';
has changelog => ( is => 'lazy' );
with 'App::Changelord::Role::Changelog';
with 'App::Changelord::Role::Versions';
sub _build_changelog ($self) { $self->parent_command->changelog }
sub serialize_changelog($self, $changelog = undef) {
$changelog //= $self->changelog;
@ -42,13 +38,16 @@ sub serialize_changelog($self, $changelog = undef) {
}
sub run ($self) {
my $src = $self->parent_command->source;
my $src = $self->source;
die "file '$src' already exists, aborting\n" if -f $src;
my $change = {
project => {
name => undef,
homepage => undef,
with_stats => 'true',
ticket_url => undef,
commit_regex => q/^(?<type>[^: ]+):(?<desc>.*?)(\[(?<ticket>[^\]]+)\])?$/,
},
change_types => $self->change_types,
releases => [

View File

@ -0,0 +1,39 @@
package App::Changelord::Command::Print;
use 5.36.0;
use Moo;
use CLI::Osprey
desc => 'print the changelog',
description_pod => <<'END';
Render the full changelog. The default is to render the changelog
in markdow, but the option C<--json> can be used to have a JSON
version instead.
To generate the changelog without the NEXT release, uses the
C<--no-next> option.
END
with 'App::Changelord::Role::Changelog';
with 'App::Changelord::Role::ChangeTypes';
with 'App::Changelord::Role::Render';
option json => (
is => 'ro',
default => 0,
doc => 'output schema as json',
);
option next => (
is => 'ro',
default => 1,
negatable => 1,
doc => 'include the NEXT release. Defaults to true.',
);
sub run($self) {
no warnings 'utf8';
print $self->as_markdown( $self->next );
}
'end of App::Changelog::Command::Print';

View File

@ -4,7 +4,14 @@ package App::Changelord::Command::Schema;
use 5.36.0;
use Moo;
use CLI::Osprey;
use CLI::Osprey
doc => 'print JSON schema for the changelog format',
description_pod => <<'END';
Print the JSON schema describing the data format used by changelord.
By defaults prints the schema in YAML. Can also be printed as JSON
via the C<--json> option.
END
use Path::Tiny;
use JSON;

View File

@ -3,13 +3,19 @@ package App::Changelord::Command::Validate;
use 5.36.0;
use Moo;
use CLI::Osprey;
use CLI::Osprey
doc => 'validate the changelog yaml',
description_pod => <<'END';
Validate the changelog against the JSON Schema used by changelord.
END
use Path::Tiny;
use JSON;
use YAML::XS;
use JSON::Schema::Modern;
with 'App::Changelord::Role::Changelog';
option json => (
is => 'ro',
default => 0,
@ -24,7 +30,7 @@ sub run($self) {
my $result = JSON::Schema::Modern->new(
output_format => 'detailed',
)->evaluate(
$self->parent_command->changelog,
$self->changelog,
YAML::XS::Load($schema),
);

View File

@ -13,38 +13,9 @@ use YAML::XS;
use List::AllUtils qw/ first min /;
use Version::Dotted::Semantic;
with 'App::Changelord::Role::Changelog';
with 'App::Changelord::Role::ChangeTypes';
has changelog => (
is => 'lazy'
);
sub _build_changelog($self){ $self->parent_command->changelog }
sub latest_version($self){
first { $_ } grep { $_ ne 'NEXT' } map { eval { $_->{version} } } $self->changelog->{releases}->@*;
}
sub next_version($self) {
my $version = Version::Dotted::Semantic->new($self->latest_version // '0.0.0');
my $upcoming = $self->changelog->{releases}[0];
if( $upcoming->{version} and $upcoming->{version} ne 'NEXT') {
$upcoming = { changes => [] };
}
my %mapping = map {
my $level = $_->{level};
map { $_ => $level } $_->{keywords}->@*
} $self->change_types->@*;
my $bump =min 2, map { $_ eq 'major' ? 0 : $_ eq 'minor' ? 1 : 2 } map { $mapping{$_->{type}} || 'patch' } $upcoming->{changes}->@*;
$version->bump($bump);
return $version->normal;
}
with 'App::Changelord::Role::Versions';
sub run($self) {
my $param = shift @ARGV;

View File

@ -21,6 +21,8 @@ properties:
examples:
- s!GH(\d+)!https://github.com/yanick/App-Changelord/issue/$1/
- /^\d+$/ ? "https://.../$_" : undef
with_stats:
description: if true, add git statistics when bumping the version.
change_types:
type: array
items:
@ -40,15 +42,18 @@ properties:
- type: object
additionalProperties: false
properties:
version: { type: string }
version: { type: [ 'null', string ] }
date: { type: ['null',string] }
changes: { type: 'array', items: { $ref: '#/$defs/change' } }
$defs:
change:
type: object
required: [ desc ]
additionalProperties: false
properties:
desc: { type: string }
ticket: { type: [ string, 'null' ] }
type: { type: [ string, 'null' ] }
oneOf:
- type: string
- type: object
required: [ desc ]
additionalProperties: false
properties:
desc: { type: string }
ticket: { type: [ string, 'null' ] }
type: { type: [ string, 'null' ] }
commit: { type: [ string, 'null' ] }

View File

@ -18,6 +18,7 @@ sub _build_change_types($self) {
{ title => 'Features' , level => 'minor', keywords => [ 'feat' ] } ,
{ title => 'Bug fixes' , level => 'patch', keywords => [ 'fix' ] },
{ title => 'Package maintenance' , level => 'patch', keywords => [ 'chore', 'maint', 'refactor' ] },
{ title => 'Statistics' , level => 'patch', keywords => [ 'stats' ] },
]
}

View File

@ -0,0 +1,21 @@
package App::Changelord::Role::Changelog;
use v5.36.0;
use Moo::Role;
use CLI::Osprey;
option source => (
is => 'ro',
format => 's',
doc => q{changelog yaml file. Defaults to the env variable $CHANGELOG, or 'CHANGELOG.yml'},
default => $ENV{CHANGELOG} || 'CHANGELOG.yml',
);
has changelog => ( is => 'lazy' );
sub _build_changelog($self) {
return YAML::LoadFile($self->source)
}
1;

View File

@ -0,0 +1,49 @@
package App::Changelord::Role::GitRepo;
use v5.36.0;
use Git::Repository;
use Moo::Role;
use feature 'try'; no warnings qw/ experimental /;
requires 'changelog';
# stolen from Dist::Zilla::Plugin::ChangeStats::Git
has repo => (
is => 'lazy',
default => sub {
Git::Repository->new( work_tree => '.' )
},
);
has stats => ( is => 'lazy' );
sub _build_stats ($self) {
my $comparison_data = $self->_get_comparison_data or return;
my $stats = 'code churn: ' . $comparison_data;
return $stats =~ s/\s+/ /gr;
}
sub _get_comparison_data($self) {
# HEAD versus previous release
# What are we diffing against? :)
my $previous = $self->changelog->{releases}->@* > 1
? $self->changelog->{releases}[1]{version}
: '4b825dc642cb6eb9a060e54bf8d69288fbee4904'; # empty tree
my $output = eval {
$self->repo->run( 'diff', '--shortstat', $previous, 'HEAD')
};
warn "could not gather stats: $@\n" if $@;
return $output;
}
1;

View File

@ -40,14 +40,18 @@ sub render_refs ( $self, %links ) {
return $output . "\n";
}
sub as_markdown ($self) {
sub as_markdown ($self, $with_next = 1) {
my $changelog = $self->changelog;
my $output = $self->render_header;
my $n = 0;
$output .= join "\n",
map { $self->render_release( $_, $n++ ) } $changelog->{releases}->@*;
map { $self->render_release( $_, $n++ ) }
grep {
$with_next ? 1 : ( $_->{version} && $_->{version} ne 'NEXT' )
}
$changelog->{releases}->@*;
return $output;
}

View File

@ -12,7 +12,7 @@ use feature 'try';
requires 'changelog';
sub latest_version($self){
first { $_ } grep { $_ ne 'NEXT' } map { eval { $_->{version} } } $self->changelog->{releases}->@*;
first { $_ } grep { $_ ne 'NEXT' } map { eval { $_->{version} || '' } } $self->changelog->{releases}->@*, { version => 'v0.0.0' };
}
sub next_version($self) {
@ -29,11 +29,35 @@ sub next_version($self) {
map { $_ => $level } $_->{keywords}->@*
} $self->change_types->@*;
my $bump =min 2, map { $_ eq 'major' ? 0 : $_ eq 'minor' ? 1 : 2 } map { $mapping{$_->{type}} || 'patch' } $upcoming->{changes}->@*;
no warnings;
my $bump =min 2, map { $_ eq 'major' ? 0 : $_ eq 'minor' ? 1 : 2 } map { $mapping{$_->{type}} || 'patch' }
map { ref ? $_ : { desc => $_ } }
$upcoming->{changes}->@*;
$version->bump($bump);
return $version->normal;
}
sub is_next($self,$release) {
my $version = $release->{version};
return !$version || $version eq 'NEXT';
}
sub next_release($self) {
my $changelog = $self->changelog;
my $release = $changelog->{releases}[0];
unless( $self->is_next($release) ) {
unshift $changelog->{releases}->@*,
$release = {
version => 'NEXT',
changes => [],
};
}
return $release;
}
1;

View File

@ -2,9 +2,9 @@ use 5.36.0;
use Test2::V0;
use App::Changelord;
use App::Changelord::Command::Print;
my $change = App::Changelord->new(
my $change = App::Changelord::Command::Print->new(
changelog => {
project => { name => 'Foo' },
}

37
t/stats.t Normal file
View File

@ -0,0 +1,37 @@
use Test2::V0;
use v5.36.0;
package TestMe {
use Moo;
has changelog => (
is => 'ro',
default => sub {{
project => { ticket_url => undef },
releases => [
{ },
]
}}
);
with 'App::Changelord::Role::GitRepo';
with 'App::Changelord::Role::ChangeTypes';
}
package TestRepo {
use Moo;
sub run(@args) {
return 'blah blah';
}
}
my $test = TestMe->new(
repo => TestRepo->new,
);
like $test->stats => qr/code churn: /;
done_testing;