Compare commits
18 Commits
Author | SHA1 | Date |
---|---|---|
Yanick Champoux | 5b832b6477 | |
Yanick Champoux | 4c315f9a04 | |
Yanick Champoux | f012489e34 | |
Yanick Champoux | ba2ba193cc | |
Yanick Champoux | ffe113a10c | |
Yanick Champoux | 8952b38553 | |
Yanick Champoux | 868e111930 | |
Yanick Champoux | 92d3e10756 | |
Yanick Champoux | ec4fee9e69 | |
Yanick Champoux | 3b4c019dcc | |
Yanick Champoux | 0fa5f2a9a4 | |
Yanick Champoux | 364ad6d587 | |
Yanick Champoux | 615cc0f581 | |
Yanick Champoux | d555b10db9 | |
Yanick Champoux | dcc2f7192c | |
Yanick Champoux | ae29ae0ebf | |
Yanick Champoux | 3ff7bfd9f3 | |
Yanick Champoux | 1ad1e9810c |
|
@ -2,3 +2,4 @@
|
|||
.build
|
||||
.perl-version
|
||||
.pls_cache/
|
||||
App-Changelord-*
|
||||
|
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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: []
|
|
@ -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
|
|
@ -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
|
|
@ -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
15
Changes
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,6 @@
|
|||
#!/usr/bin/env perl
|
||||
# PODNAME: changelord
|
||||
# ABSTRACT: cli tool for App::Changelord
|
||||
|
||||
use App::Changelord;
|
||||
|
||||
|
|
|
@ -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";
|
||||
};
|
21
dist.ini
21
dist.ini
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
@ -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 => [
|
||||
|
|
|
@ -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';
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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' ] }
|
||||
|
|
|
@ -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' ] },
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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' },
|
||||
}
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue