diff --git a/Changes b/Changes index b23bf5e541dbb4c6e302bd5d031bfde2f4abbcef..1ad2701a1251739e80cd6eaeeb1be78d95d95942 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for Perl extension WebService::Redmine (initially RedMiner::API). -Please see full revision history at https://github.com/igelhaus/redminer/releases +Please see full revision history at https://github.com/igelhaus/perl-WebService-Redmine/releases 0.01 Wed Apr 9 07:44:27 2014 - original version; created by h2xs 1.23 with options diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index b1a5fcef0aa0737c606e05ed785335ebc8fd0ca2..f0dfb242650a5de9d43ada5557133f7c852ff582 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -1,5 +1,3 @@ -config-samples xt .gitignore README.md -redminer diff --git a/README.md b/README.md index 419279e9a54139d9a7e80be6234370a3da4aace2..8068b6a6cac3a06f8b7ab2bf810e99891f34a8e6 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,16 @@ -# redminer +# WebService::Redmine -Automating routine [RedMine](http://www.redmine.org) tasks with Perl 5.10+. +[Redmine REST API](http://www.redmine.org/projects/redmine/wiki/Rest_api) for Perl 5.10+. -Currently the project consists of two parts: - -1. `redminer` script itself. For now it supports only creating projects with subprojects -from a given layout, but in the future it's aimed for various RedMine automation tasks -2. `WebService::Redmine` module, a Perl binding to [RedMine REST API](http://www.redmine.org/projects/redmine/wiki/Rest_api). -Please refer to [built-in POD documentation](../master/lib/WebService/Redmine.pm) for more details - -## Installation - -`ExtUtils::MakeMaker` style: +## Installation from CPAN ```shell -$ perl Makefile.PL -$ make -$ make test -$ make install +$ cpan -i WebService::RedMiner ``` +## Documentation + +For more details, please refer to [CPAN](https://metacpan.org/pod/WebService::Redmine) or [built-in POD documentation](../master/lib/WebService/Redmine.pm). -## Non-core Dependencies +## Related Projects -1. [LWP::UserAgent](https://metacpan.org/pod/LWP::UserAgent) -2. [URI](https://metacpan.org/pod/URI) -3. [URI::QueryParam](https://metacpan.org/pod/URI::QueryParam) -4. [JSON::XS](https://metacpan.org/pod/JSON::XS) -5. [Config::IniFiles](https://metacpan.org/pod/Config::IniFiles) (`redminer` only) +1. [redminer](https://github.com/igelhaus/redminer), a console tool for automating Redmine. diff --git a/config-samples/default-layout.conf b/config-samples/default-layout.conf deleted file mode 100644 index e55bd0f63d7485c91fb8a48fe196374ead338348..0000000000000000000000000000000000000000 --- a/config-samples/default-layout.conf +++ /dev/null @@ -1,26 +0,0 @@ -# -# Default layout should be located at $HOME/.redminer/default-layout.conf -# Custom path may be specified as -# perl redminer.pl --layout /path/to/layout.conf -# - -[project] -description=<<DESCRIPTION -Description of the master project -DESCRIPTION - -# Copy permission from the project with ID 42 -perm_source=42 - -# Subproject suffix is the rest of the section name after the 'subproject-'part: -[subproject-development] -name_suffix=Development -description=<<DESCRIPTION -Subproject for development tasks -DESCRIPTION - -[subproject-management] -name_suffix=Management -description=<<DESCRIPTION -Subproject for generic management tasks -DESCRIPTION diff --git a/config-samples/redminer.conf b/config-samples/redminer.conf deleted file mode 100644 index 8b908b80bc11d680be14565c7d2fbe2cb5a8e499..0000000000000000000000000000000000000000 --- a/config-samples/redminer.conf +++ /dev/null @@ -1,28 +0,0 @@ -# -# Default config should be located at $HOME/.redminer/redminer.conf -# Custom path may be specified as -# perl redminer.pl --conf /path/to/redminer.conf -# - -[redmine] - -host=redmine.example.com -# Host could also include a path and/or schema prefix ('http' is the default value), e.g.: -# * example.com/redmine -# * http://example.com/redmine -# * https://example.com/redmine -# etc. - -key=xxx -# How to obtain an API key: -# http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication -# You can find your API key on your account page ( /my/account ) when logged in, on the right-hand pane of the default layout. - -# Impersonation settings: -work_as=real_user - -# User+Password auth is also possible: -# [redmine] -# host=redmine.example.com -# user=redmine-robot -# pass=p@s$w0rD diff --git a/redminer b/redminer deleted file mode 100755 index c459fcda56ef52005cede269c9719098ed383f62..0000000000000000000000000000000000000000 --- a/redminer +++ /dev/null @@ -1,149 +0,0 @@ -#/usr/bin/env perl - -use 5.010; -use strict; -use warnings; - -use FindBin; -use lib "$FindBin::Bin/lib"; - -use Encode qw/encode/; -use Getopt::Long; -use Config::IniFiles; - -use WebService::Redmine; - -my $conf_fname = $ENV{HOME} . '/.redminer/redminer.conf'; -my $layout_fname = $ENV{HOME} . '/.redminer/default-layout.conf'; -my $project_id = ''; -my $project_name = 'ClientName.domain'; - -GetOptions( - 'conf=s' => \$conf_fname, - 'layout=s' => \$layout_fname, - 'id=s' => \$project_id, - 'name=s' => \$project_name, -); - -my $conf = Config::IniFiles->new( -file => $conf_fname ); -if (!$conf) { - die 'Unable to access master config'; -} - -if (!$project_id) { - if ($project_name =~ /^[a-z.\-]+$/i) { - $project_id = $project_name; - $project_id =~ s/\./-/g; - } else { - die 'Invalid --id parameter'; - } -} - -my $layout = Config::IniFiles->new( -file => $layout_fname ); -if (!$layout) { - warn 'Unable to access layout config'; -} - -my $redminer = WebService::Redmine->new( - host => $conf->val('redmine', 'host') // '', - user => $conf->val('redmine', 'user') // '', - pass => $conf->val('redmine', 'pass') // '', - key => $conf->val('redmine', 'key') // '', - work_as => $conf->val('redmine', 'work_as') // '', - no_wrapper_object => 1, -); - -my $description = $layout? $layout->val('project', 'description') // '' : ''; - -say 'Creating a new project ' . $project_name; - -my $project = $redminer->createProject({ - identifier => $project_id , - name => $project_name, - description => $description , -}); - -if (!$project) { - say STDERR 'Project was not created'; - say STDERR render_errors($redminer->errorDetails); - exit 255; -} - -my $pid = $project->{id}; -say 'Project created with ID ' . $pid; - -$redminer->updateProject($pid, { - inherit_members => 1, -}); - -if ($layout) { - my @sections = $layout->Sections; - foreach my $section (@sections) { - next if $section !~ /^subproject(-.+)$/; - my $subproject_data = { - identifier => $project_id . $1, - name => $project_name . ': ' . ($layout->val($section, 'name_suffix') // 'Subproject'), - description => $layout->val($section, 'description') // '', - }; - - say 'Creating a new subproject ' . $subproject_data->{name}; - - my $subproject = $redminer->createProject($subproject_data); - if (!$subproject) { - say STDERR 'Subproject was not created'; - say STDERR render_errors($redminer->errorDetails); - next; - } - - say 'Subproject created with ID ' . $subproject->{id}; - $redminer->updateProject($subproject->{id}, { - parent_id => $pid, - inherit_members => 1, - }); - } -} - -# FIXME: handle limit/offset issue -my $perm_source = $layout? $layout->val('project', 'perm_source') : 0; -if ($perm_source) { - my $memberships = $redminer->projectMemberships($perm_source); - if ($memberships) { - say 'Copying project permissions from a template project...'; - foreach my $membership (@{ $memberships->{memberships} }) { - my $type = ''; - if (exists $membership->{group}) { - $type = 'group'; - } elsif (exists $membership->{user}) { - $type = 'user'; - } - next if !length $type; - - my $new_membership = { - user_id => $membership->{$type}{id}, - role_ids => [], - }; - for my $role (@{$membership->{roles}}) { - next if $role->{inherited}; - push @{ $new_membership->{role_ids} }, $role->{id}; - } - if ($new_membership->{user_id} && @{ $new_membership->{role_ids} }) { - $redminer->createProjectMembership($pid, $new_membership); - } - } - say 'Permissions copied'; - } -} - -say 'Bye'; -exit; - -sub render_errors -{ - my $errors = shift; - if (ref $errors ne 'HASH' && ref $errors->{errors} ne 'ARRAY') { - return 'Unknown server errors'; - } - return join "\n", 'Following error(s) reported:', map { - "\t* " . Encode::encode('UTF-8', $_) - } @{ $errors->{errors} }; -}