orgmine-mode
is a minor mode for org-mode with Redmine integration.
In a orgmine-mode
buffer, you can retrieve the issues from Redmine,
edit the entries locally, and submit the changes to Redmine.
orgmine
depends on the following emacs lisp packages, which are
available from MELPA. Install these packages as well.
- elmine — Redmine API access via elisp.
- s — The long lost Emacs string manipulation library.
- markdown-mode — Emacs Major mode for Markdown-formatted text files.
- request — Compatible layer for URL request in Emacs.
orgmine
was developed and tested on the following environment:
- GNU Emacs 24.3.1
- Org-mode 8.3.2
The latest version of orgmine.el
is available from:
https://github.com/kametoku/orgmine
Add the following lines to your ~/.emacs
file so that the orgmine minor mode
is activated when the “om_project” property is defined as the file-wide
property.
Note that “om_project” property is a mandatory property to use orgmine.
(require 'orgmine)
(add-hook 'org-mode-hook
(lambda () (if (assoc "om_project" org-file-properties)
(orgmine-mode))))
If you prefer to visiting Redmine tickets by web browser via the org
links, add the link abbreviations to org-link-abbrev-alist
as follows:
(setq org-link-abbrev-alist
'(("redmine" . "http://redmine.example.com/")
;;...
))
Setup orgmine-servers
for your environments.
Prior to do this, please get the API key of the redmine REST API.
(setq orgmine-servers
'(("redmine" ; server name for this entry
(host . "http://redmine.example.com")
(api-key . "blabblabblab")
(issue-title-format . "[[redmine:issues/%{id}][#%{id}]] %{subject}")
(journal-title-format . "[[redmine:issues/%{id}#note-%{count}][V#%{id}-%{count}]] %{created_on} %{author}")
(version-title-format . "[[redmine:versions/%{id}][V#%{id}]] %{name}")
(tracker-title-format . "%{name}")
(project-title-format . "[[redmine:projects/%{identifier}][%{identifier}]] %{name}")
(user-name-format . "%{firstname} %{lastname}")
(default-todo-keyword . "NEW"))))
Key | variable to define default | Description |
---|---|---|
host | elmine/host | URL of redmine |
api-key | elmine/api-key | API Key for the redmine |
issue-title-format | orgmine-issue-title-format | Issue title format |
journal-title-format | orgmine-journal-title-format | Journal title format |
version-title-format | orgmine-version-title-format | Version title format |
tracker-title-format | orgmine-tracker-title-format | Tracker title format |
project-title-format | orgmine-project-title-format | Project title format |
user-name-format | orgmine-user-name-format | User Name format |
custom-fields | NA | custom fields |
The basic structure of org-mode file for orgmine minor mode is as follows:
You can run M-x orgmine-insert-template to retrieve basic settings for orgmine mode.
This is up to the statuses of the Redmine.
#+SEQ_TODO: New(n) Open(o) Resolved(r) Feedback(f) | Closed(c)
orgmine
determines the headline types by its tags.
#+TAGS: { UPDATE_ME(u) CREATE_ME(c) REFILE_ME(r) }
- UPDATE_ME: locally updated entry and need to be submitted to the redmine.
- CREATE_ME: a new entry to be submitted to the redmine.
- REFILE_ME: TBD
#+TAGS: { project(p) tracker(t) version(v) issue(i) description(d) journals(J) journal(j) }
Also, the following tags specify the headline types.
Tag | Description |
---|---|
project | project entry |
tracker | tracker entry |
version | fixed version entry |
issue | issue entry |
description | description entry of an issue or project |
journals | journals subtree entry that consists of journal entries |
journal | journal entry of an issue |
attachment | attachment entry of an issue |
You can change the tag names by orgmine-tags
variable.
The following is an example of orgmine-tags
setting.
(setq orgmine-tags '((update-me . "UPDATE_ME")
(create-me . "CREATE_ME")
(refile-me . "REFILE_ME")
(project . "project")
(tracker . "tracker")
(versions . "versions")
(version . "version")
(issue . "issue")
(description . "description")
(journals . "journals")
(journal . "journal")
(attachments . "attachments")
(wiki . "wiki")))
This setting is a very important part of settings in the org-mode file.
#+PROPERTY: om_server redmine
#+PROPERTY: om_project 1:MyProject
#+PROPERTY: om_assigned_to_ALL 1:Tokuya\ Kameshima 2:Pooh\ Winnie
#+PROPERTY: om_done_ratio_ALL 0 10 20 30 40 50 60 70 80 90 100
#+PROPERTY: om_tracker_ALL 1:Defect 4:Task 8:Milestone
#+PROPERTY: om_me 1:Tokuya\ Kameshima
#+PROPERTY: om_cf_12_resolution_ALL fixed declined deferred obsolete documentation
Property | Must | Description |
---|---|---|
om_server | Must | redmine server name |
om_project | Want | default project ID followed by “:” and its name |
om_assigned_to_ALL | Wish | users of the project |
om_done_ratio_ALL | Wish | done_ratio values 0 to 100 stepped by 10 |
om_tracker_ALL | Wish | tracker IDs with their names |
om_me | Wish | my user ID followed by “:” and its name |
The property om_server
determines which server setting in
orgmine-server-list
should be used.
#+COLUMNS: %50ITEM(Task) %9om_assigned_to(Assigned) %8om_tracker(Tracker) %5Effort(Est.){:} %CLOCKSUM(Clock) %SCHEDULED %DEADLINE %TAGS
Run M-x orgmine-insert-issue (or press C-c m I) and enter an issue id to insert the issue entry.
This operation is not usual but just for demonstration. As usual, the issue entries are placed under project, version or tracker subtree and maintained there.
The following is an example of issue entry. Notice that the issue attributes are inserted as properties of the entry, the issue description, attachments, journals (comments) are inserted as child entry of the issue entry. They are located by the tags (:issue:, :description:, :attachments: :journals:, and :journal: in this example).
Note that the start date and due date attributes of the Redmine issue are converted to SCHEDULE and DEADLINE properties of org-mode entry, and the status attribute of the Redmine issue is converted to the TODO keywords of org-mode entry.
* New [[redmine:issues/24]] Implement orgmine-xxx function :issue:
SCHEDULED: <2015-09-11 Fri>
:PROPERTIES:
:om_id: 24
:om_tracker: 4:Task
:om_created_on: 2015-09-11T14:01:25Z
:om_updated_on: 2015-09-19T18:30:18Z
:om_status: 1:New
:om_fixed_version: 3:Test
:om_start_date: [2015-09-11 Fri]
:om_done_ratio: 0
:om_project: 1:SandBox
:END:
** Description :description:
#+begin_src gfm
This is a hard part.
#+end_src
** Attachments :attachments:
- [[http://redmine.example.org/attachments/download/12/a.jpg][a.jpg]] (25370 bytes) Tokuya Kameshima [2015-09-14 Mon 01:13]
abcdefg
** Journals :journals:
*** [[redmine:issues/24#note-2]] [2015-09-20 Sun 03:30] Tokuya Kameshima :journal:
:PROPERTIES:
:om_count: 2
:END:
#+begin_src gfm
This is a note...
#+end_src
*** [[redmine:issues/24#note-1]] [2015-09-14 Mon 01:15] Tokuya Kameshima :journal:
:PROPERTIES:
:om_count: 1
:END:
:DETAILS:
- attachment_11: ADDED -> "naorio.JPG"
:END:
Now, we are going to edit the issue entry and send the changes to Redmine.
You can edit the issue entry in orgmine buffer to update the issue. The following updates are supported.
- Change the issue attributes.
—
orgmine-set-entry-property
(C-c m ; ;) - Change the issue status.
—
org-todo
(C-c C-t) - Change the start date.
—
org-schedule
(C-c C-s) - Change the due date.
—
org-deadline
(C-c C-d) - Change or add the description.
—
orgmine-add-description
(C-c m d) - Add a journal note.
—
orgmine-add-journal
(C-c m j) - Add attachments to the issue.
—
orgmine-add-attachment
(C-c m a)
If you edit description note by hand, you need add :UPDATE_ME: tag to the description headline.
local changes when submitting the change to Redmine.** Description :UPDATE_ME:description:
#+begin_src gfm
This is a hard part. <-- Not really...
#+end_src
To submit the changes to Redmine, move the cursor to the issue headline and run M-x orgmine-submit (C-c m c).
If there are no problems, the changes are sent to Redmine and the local issue entry is updated by new contents and attributes.
If someone else has updated the issue while you are editing the issue entry, you will get the following error when submitting the changes.
#24: entry has been updated by other user.
In this case, you can run M-x orgmine-ediff (C-c m ?) to run ediff on the Redmine’s latest issue contents and your local entry. And you can investigate the differences of them and merge the update to your entry.
Move the cursor to the issue headline and run M-x orgmine-fetch (C-c m f) to fetch the latest contents of the issue from Redmine and update the local entry.
You can run M-x orgmine-add-issue (C-c m i) to add a new issue entry.
* New :issue:CREATE_ME:
:PROPERTIES:
:om_start_date: [2015-10-16 Fri]
:END:
After editing the entry (e.g., adding title, description, attributes and due date), run M-x orgmine-submit (C-c m c) to submit the new issue to Redmine. The contents are sent to Redmine and the local entry is updated with the issue created.
The following is an example of issue entry just after creation.
* New [[redmine:issues/25][#25]] write document about orgmine :issue:
DEADLINE: <2015-10-23 Fri> SCHEDULED: <2015-10-16 Fri>
:PROPERTIES:
:om_id: 25
:om_tracker: 4:Task
:om_created_on: 2015-10-16T07:58:51Z
:om_updated_on: 2015-10-16T07:58:51Z
:om_status: 1:New
:om_fixed_version: 5:Documentation
:om_start_date: [2015-10-16 Fri]
:om_due_date: [2015-10-23 Fri]
:om_done_ratio: 0
:om_project: 1:SandBox
:END:
The following table summarizes the org mode properties and redmine attributes for an issue entry.
Org-mode Property | Redmine Attribute | Comment |
---|---|---|
om_id | issue id | |
om_tracker | tracker | id + “:” + tracker name |
om_created_on | creation date&time | w/timezone format |
om_updated_on | last updated date&time | w/timezone format |
om_status | issue status | converted to TODO keywords |
om_fixed_version | fixed version | id + “:” + version name |
om_start_date | issue start date | converted to SCHEDULE property |
om_due_date | issue due date | converted to DEADLINE property |
om_done_ratio | issue done ratio | |
om_project | issue’s project | id + “:” + project name |
Note that if both of a property and the corresponding special keyword exist for a single issue entry, the special keyword is preferred.
Now, you are ready to retrieve the entries from the redmine.
In the orgmine buffer run M-x orgmine-insert-project (or press C-c m P),
and you will be prompted to specify the project id to insert.
Enter the project id and press enter key, and then orgmine
retrieves
the project properties and insert the project entry with the headline.
The following is an example of the result. Notice the project properties are inserted as the entry’s properties and the project description is inserted as a sub entry and quoted in src block.
* SandBox ([[redmine:projects/sandbox]]) :project:
:PROPERTIES:
:om_project: 1:SandBox
:om_created_on: 2015-07-31T06:40:56Z
:om_updated_on: 2015-08-18T05:42:26Z
:om_status: 1
:om_identifier: sandbox
:END:
** Description :description:
#+begin_src gfm
This is a sandbox project. Feel free to play with this project.
#+end_src
Move the cursor on the line of project headline and run
M-x orgmine-sync-subtree-recursively
(C-c m s
) to retrieve all the issues
of the project.
The issue entries are inserted as the child entries of the project entry.
You can maintain the issue entries of a certain version in a subtree.
The following is an example of Version subtree
* [[redmine:versions/3]] Sprint-001 :version:
DEADLINE: <2015-09-04 Fri>
:PROPERTIES:
:om_fixed_version: 3:Sprint-001
:om_created_on: 2015-08-02T14:18:41Z
:om_updated_on: 2015-08-04T16:12:22Z
:om_status: open
:om_due_date: [2015-09-04 Fri]
:om_project: 1:SandBox
:END:
As well as versions, you can put the issues of a certain tracker in a subtree.
The following piece of org-mode file demonstrates a tracker subtree. You can put the issue entries of Milestone tracker in the “* Milestone” tree.
* Milestone :tracker:
:PROPERTIES:
:om_tracker: 8:Milestone
:END:
** [[redmine:issue/1]] New Code Freeze :issue:
DEADLINE: <2015-09-30 Wed> SCHEDULED: <2015-09-30 Wed>
:PROPERTIES:
:om_id: 123
:om_tracker: 8:Milestone
:om_created_on: 2015-09-04T00:56:07Z
:om_updated_on: 2015-10-01T08:57:24Z
:om_status: 1:New
:om_start_date: [2015-09-30 Wed]
:om_due_date: [2015-09-30 Wed]
:om_done_ratio: 0
:om_project: 84:VIS14.0SP1
:END:
So far, we used M-x orgmine-sync-subtree-recursively (C-c m s) to synchronize the entries with Redmine. You can use M-x orgmine-sync-buffer (C-c m S) to synchronize entries of whole the buffer with Redmine.
- Not enough error handling.
orgmine
useselmine.el
to communicate with Redmine butelmine.el
does not raise the errors even when Redmine returns some error code.
You can customize orgmine
with M-x customize.
See the docstring of each customizable variables of orgmine
.