This plugin is designed to work as an addon for Hubot. Its role is to make interactions possible between a chat room (irc, slack, gitter) and a phabricator instance.
When installed this plugin will check the channels where the bot lurks, to see if someone is talking about Phabricator objects (T32 or P156 or F1526) to complement the conversation with the name of the referred item.
It also makes available some commands to interact directly with Phabricator items, like create a task, assign a task to a user. This is a work in progress and more commands will be added with time.
This plugin is used in production internally at Gandi since 2016-07-13.
Check the Changelog for a precise history of the versions.
In your hubot directory:
npm install hubot-phabs --save
Then add hubot-phabs
to external-scripts.json
Next you need to create a bot
user in Phabricator and grab its api key.
By default every action is usable by any user. But you can follow the optional permission system by using the hubot-auth
module.
There are mainly 3 permissions groups:
admin
group, for which everything is permitted everywherephadmin
group, required for which everything is permitted on.phab
and.phad
commandsphuser
group, which cannot use- the
.phad
command except.phad projects
- the
.phab user = email
command
- the
- the 'not in any group' user, which cannot
- create new task
- create new paste
- change status or permission
- assign a task to someone
- set an email or check other users
If you set the variable PHABRICATOR_TRUSTED_USERS
to y
, then the 'not in any group' users can access all the features reserved for the phuser
group. Typically the phuser
role is designed to be used on public irc or gitter channels, but is not needed in closed slack channels.
PHABRICATOR_URL
- main url of your Phabricator instancePHABRICATOR_VERSION
- the version of phabricatior used, in the shape2017.24
so it'syear.week
and looks like a float easy to compare. This is used for handling breaking changes between versions of phabricator.PHABRICATOR_API_KEY
- api key for the bot userPHABRICATOR_LAST_TASK_LIFETIME
- how long the last task is remembered for each user (default 60 min). If set to "0" there is memory on the last task remembered. If set to "-" the memory is never expired.
If you use hubot-auth
HUBOT_AUTH_ADMIN
- hardcoded list of hubot adminsPHABRICATOR_TRUSTED_USERS
- if set to 'y', bypasses the requirement of belonging tophuser
group for commands restricted to users. Makes sense in places where all users are internal or invited-only and trustworthy.
You also should use hubot-restrict-ip
to limit the access to the web endpoints (api and feeds endpoints), or serve only on localhost (EXPRESS_BIND_ADDRESS=127.0.0.1
) and use a proxy to access those endpoints.
PHABRICATOR_ENABLED_ITEMS
- is used with featurehear
to limit what kind of objects are commonly used in your instance of PhabricatorPHABRICATOR_FEED_EVERYTHING
- if set to a value that is not '0' (like 1 or yes), then the feedall feature will not only announce tasks. Note that this option only applies to the.ph feedall to <room>
case, not to specific projects feeds.
The hubot-phabs
plugin has a lot of features, and some of them could be useless, or dangerous if activated under an unprotected environment. There are 2 environment variables that can be used to limit what features are loaded and active:
PHABS_ENABLED_FEATURES
can be a comma-separated list of the only plugins enabled.PHABS_DISABLED_FEATURES
is also a comma-separated list of features, to only restrict a few ones. It won't be any use if thePHABS_ENABLED_FEATURES
is declared, as it would take priority.
Typical examples of usage are:
PHABS_ENABLED_FEATURES="hear"
if you only want the bot to do automatic announcesPHABS_DISABLED_FEATURES="feeds,api"
if you don't want to expose http endpointsPHABS_DISABLED_FEATURES="admin,feeds"
if you don't usehubot-auth
. Note that you can do the setup with the admin feature at first, and then just disable it (and relaunch the bot in between).
Available features are loaded in that order:
events
api
commands
templates
admin
feeds
hear
There is some events available for interaction with other plugins, to chain actions or automate them. The specific use case we had was to use hubot-cron-events to create templated tasks are given times. It is making sense in our workflow. The principle is pretty useful, so there will be more events declared further on.
phab.createTask
payload:
- project (by name or alias)
- template (null if none)
- title
- description
- user (an object with at least a name property)
- assign (as a user name)
- announce (optional: the name of a room where to announce the task creation and id)
It will create a task from an event,
and talk on the logger when done or if it fails.
It may seem a little weird, but circumstances led us to use our hubot as an API endpoint for creating tasks from inside our internal network. Of course we could just use conduit and hit Phabricator directly but:
- we save the hassle of spreading the API key around
- we are inside a trusted network, and use hubot-restrict-ip
- we expose REST endpoints, with only very simplified payload description
To avoid exposure of that weak API endpoint, you should:
- set the env var PHABS_NO_API to any value, if it's defined, the api code is not loaded
- use hubot-restrict-ip to set up your own policy
- set your hubot to respond http calls through a well configured apache or nginx proxy
Currently the API only has one endpoint, that triggers the phab.createTask
event
POST /<robot.name>/phabs/api/:project/task
where :project can be a project name or an alias
that you have set with .phad
the content-type has to be application/json
and the payload should conform to the payload
for the phab.createTask event
Commands prefixed by .phab
are here taking in account we use the .
as hubot prefix, just replace it with your prefix if it is different. Also, phab
can be shortened to ph
in the commands.
Requests can be done on arbitrary projects. Their PHID will be retrieved at first call and cached in hubot brain. Those projects can use aliases, like short names, interchangeably, for convenience (set them up using the .phad
command).
.phab [all] [limit] <project> <search terms>
will grab the 3 newest matches in tasks matching search terms and included in project.
note that there are some special rules:
- non-alphanumeric chars will be mess up
- the match is done on full-words: test won't match tests
- if the 'all' prefix is used, it will also search in task that are not in status 'open'
- if the limit is specified, it has to be a number. without limit the default is 3
remember that phabricator search api has a hard limit of 100 in any case
(so '.phab 1000 <project> <term>' will only return 100 results anyways)
permission: all
.phab [all] [limit] search <search terms>
will grab the 3 newest matches in tasks matching search terms.
Same rules apply as the search per project/tag.
permission: all
.phab new <project> <task title>
.phab new <project> <task title> = <description>
creates a new task in an arbitrary project.
A project alias can also be used.
The new task will be created in the default column of the project board.
The issuer of the command will be added in the list of subscribers
for the newly created task.
The <description> is optional, and will be used as description if provided
NOTE: this call will record this Task id associated to you for 1 hour
permission: phuser
.phab new <project>:<template> <task title>
.phab new <project>:<template> <task title> = <description>
creates a new task using a template.
if a description is provided, it will prepend the template description
For the rest, it behaves like the .phab new command
permission: phuser
.phab paste <new paste title>
creates a new paste and provide the link to edit it
permission: phuser
.phab T123
.phab
gives the status, priority and owner of the task xxx
NOTE: this call will record this Task id associated to you for 1 hour
permission: all
.phab T123 + <some comment>
.phab + <some comment>
adds a comment to task Txxx (or the one in short memory).
permission: phuser
.phab T123 in tag1
.phab T123 not in tag1
.phab T123 in tag1 in tag2 not in tag3 in tag4
adds or remove tags from tasks. Tags are also known as projects
permission: phuser
.phab T123 is open
.phab T123 is broken
.phab is low
.phab low
.phab is low = this is a reason
.phab is low + this is a reason
Changes status or priority for task Txxx. the 'is' is optional.
If the optional '=' or '+' is used, it will add a comment to that change
Available statuses are:
- open, opened -> open
- resolved, resolve, closed, close -> resolved
- wontfix, noway -> wontfix
- invalid, rejected -> invalid
- spite, lame -> spite
Available priorities are
- broken, unbreak -> Unbreak Now!
- none, unknown, triage -> Needs Triage
- high, urgent -> High
- normal -> Normal
- low -> Low
- wish, wishlist -> Whishlist
NOTE: this call will record this Task id associated to you for 1 hour
permission: phuser
.phab T123 on <someone>
.phab for <someone>
assigns the given task to a user (or the given user to the task,
which is exactly the same).
The 'for' and 'on' conjunctions are inter-changeable.
You can use 'me' as username and it will substitute your username
NOTE: this call will record this Task id associated to you for 1 hour
permission: phuser
.phab T123 to <column>
.phab to <column>
.phab T123 to <column> + some comment
.phab T123 to <column> = some comment
moves the task on the board to the column matching the <column>
the matching will take the first match.
A comment can optionaly be added
permission: phuser
.phab T123 sub <user>
.phab sub <user>
.phab T123 sub <user> + some comment
.phab T123 unsub <user> = some comment
subscribes and unsubscribes users to tasks.
A comment can optionally be added.
You can use 'me' as username and it will substitute your username
permission: phuser
.phab T123 on <someone> is low is open to <column>
starting with `v2.2.0` it's possible to combine several commands to
change a task. It detects actions to be taken according to the conjunction used:
- on - change owner
- for - change owner (alias to on)
- is - change status or priority
- in - change tag/project (add a tag)
- not in - change tag/project (remove a tag)
- to - change column
- sub - subscribes user
- unsub - unsubscribes user
permission: phuser
.phab T123 next <term>
.phab T123 next
.phab next
This will return the first match in the Task T123 description
that begins with a [ ] (a checkbox)
if a <term> is provided, it will match the first line
that begins with '[ ] term'
the first word on the line, just after the checkbox, is used
as a keyword, but it's totally optional
permission: phuser
.phab T123 prev <term>
.phab T123 prev
.phab previous
.phab prev
This will return the last match in the Task T123 description
that begins with a [x] (a checked checkbox)
if a <term> is provided, it will match the last line
that begins with '[x] term'
permission: phuser
.phab T123 check <term>
.phab T123 check
.phab check
.phab check! <term>
.phab check!
.phab check! + <comment>
This will update the description of T123
and replace the checkbox line with a checked box '[x]'
If a term is provided, the first matching line will be the checked one
If the '!' is added, it will also return the next unchecked checkbox
If a '+' is added at the end of any above syntax, it will append a comment
in the modification
permission: phuser
.phab T123 uncheck <term>
.phab T123 uncheck
.phab uncheck
.phab uncheck! <term>
.phab uncheck!
.phab uncheck! + <comment>
This will update the description of T123
and replace the checked checkbox line with a checked box '[ ]'
If a term is provided, the last matching line will be the unchecked one
If the '!' is added, it will also return the previous checked checkbox
If a '+' is added at the end of any above syntax, it will append a comment
in the modification
permission: phuser
.phab user <someone>
will check is <someone> is linked to his Phabricator account
(using email address)
permission: phuser
.phab me as <email@example.com>
registers your email in the bot. You need to specify the email address
registered in Phabricator
permission: phuser
.phab user <someone> = <email@example.com>
registers email for another user, follows the same concept as
.phab me as ..
permission: phadmin
.phab count <project>
return the number of tasks in the given <project>
permission: all
.phab version
displays the version of hubot-phabs that is installed
permission: all
.phid <phid>
.phid <name>
When provided a PHID-*, gives the name and uri for a given PHID (mostly for arcanist use)
When provided an item name (ie. T123), returns the PHID
permission: all
There is also a way to specify a list of templates for creating new Tasks with prefilled descriptions. Any task can be used as a template, whatever the status, as far as they are readable by the bot user. Typically those can be relevant closed Tasks form the past that we fit for templating.
The management of those templates is done with the .pht
command:
.pht new <name> T123
creates a new template named <name>, using the task T123 as a template
permission: phadmin
.pht show <name>
.pht info <name>
shows what task is used as a template
permission: phuser
.pht search <term>
.pht list <term>
search through templates which names contain <term>
If <term> is omitted, it just retruns the whole list
of all templates
permission: phuser
.pht remove <name>
removes template named <name> from the brain memory
permission: phadmin
.pht update <name> T321
updated template named <name> with the new template task T321
permission: phadmin
.pht rename <name> <newname>
rename the template named <name> with <newname>
permission: phadmin
Some configuration variables are stored the brain. They are managed by the phabs_admin module, driven with the .phad
command. note the syntax changed in v1.5.1
.phad projects
lists projects listed in brain
permission: all
.phad delete <project>
.phad del <project>
removes information about <projects> from the brain
(useful when a project is deleted or renamed in phabricator)
permission: phadmin
.phad info <project>
.phad show <project>
gives info about <project>, including aliases, feeds and columns
permission: all
.phad info <parent> / <project>
.phad show <parent> / <project>
gives info about <project> given that it is a subproject or milestone of <parent>,
retunred information includes aliases, feeds and columns
permission: all
.phad refresh <project>
refresh info for <project> form phabricator
typically useful when there are new columns in a workboard
permission: all
.phad alias <project> as <alias>
adds an alias <alias> to <project>. Aliases are unique
permission: phadmin
.phad forget <alias>
removes the alias <alias>
permission: phadmin
.phad feed <project> to <room>
.phad feeds <project> to <room>
creates a feed for <project> to <room>.
Feeds are comming from feed.http-hooks. Only tasks are included in this feed.
permission: phadmin
.phad remove <project> from <room>
remove a feed
permission: phadmin
.phad feedall to <room>
creates a catchall feed to <room>.
Only tasks are included in this feed
unless the var PHABRICATOR_FEED_EVERYTHING is set and is not set to '0'
permission: phadmin
.phad removeall from <room>
remove a catchall feed
permission: phadmin
A http endpoint is open for receiving feeds from feed.http-hooks
as explained in https://secure.phabricator.com/T5462
You can use the .phad
commands to associate Projects to rooms. Each Feed Story will then be dispatched on one or several rooms according to the project the task belongs to. This only works with Tasks (for now).
Note that the tasks from a subprojects are also announced in the feed for the parent project.
The feed has an optional way to limit the IP of the sender, by setting the HUBOT_AUTHORIZED_IP_REGEXP env variable. If this variable is not set, there is not access control. It's a limited soft protection, if you really need a heavy secure protection, do something on your network for it.
Since 2.4.1, users can also set private alerts on tasks they own or are subscribed to.
.phab me set alerts
will send a private message for each task the caller owns or is subscribed to
(note: it only works on tasks for now)
permission: phuser
.phab <user> set alerts
same as with 'me' but with arbitrary user name, to enable their subscription to alerts
permission: phadmin
.phab me unset alerts
will disable alerts
permission: phuser
.phab <user> unset alerts
same as with 'me' but with arbitrary user name, to disable their subscription to alerts
permission: phadmin
There is a .hear
feature that also will give information about items that are cited on channel. It tries to do precise pattern matching but sometimes there are some unfortunate coincidences. For example, we work with level3 and talk about it under L3 often. Or one of our project involves a V5. It's kind of annoying to have the bot react on those specific case, so it' possible to blacklist them.
There is possibility to only react to certain item type too, by setting the PHABRICATOR_ENABLED_ITEMS
environment variable. For example PHABRICATOR_ENABLED_ITEMS="T,P,r"
will restrict reactions to only Tasks, Pastes and Commits items. If that env var is not declared, it will react to all known types.
something about https://phabricator.example.com/T2#17207
just talking about T123. did you see that one?
the plugin will watch if it sees
- T[0-9]+ for tasks (of Maniphest)
- P[0-9]+ for pastes
- D[0-9]+ for differential revisions
- F[0-9]+ for files
- M[0-9]+ for mocks (of Pholio)
- B[0-9]+ for builds (of Harbormaster)
- L[0-9]+ for legalpads
- V[0-9]+ for polls (of Slowvote)
- r[A-Z]+[a-f0-9]+ for commit (of Diffusion)
if it is in an url, it will reply with
T2 - <title of the task>
if it's not in an url it will reply with
<task url> - <task title>
NOTE: this call will record this Task id associated to you for 5 minutes
it will just say nothing if the pattern matched is in the blacklist
permission: all
.phab bl T123
this will add T123 to the blacklist
permission: phuser
.phab unbl T123
this will remove T123 from the blacklist
permission: phuser
All changes are listed in the CHANGELOG
npm install
# will run make test and coffeelint
npm test
# or
make test
# or, for watch-mode
make test-w
# or for more documentation-style output
make test-spec
# and to generate coverage
make test-cov
# and to run the lint
make lint
# run the lint and the coverage
make
Feel free to open a PR if you find any bug, typo, want to improve documentation, or think about a new feature.
Gandi loves Free and Open Source Software. This project is used internally at Gandi but external contributions are very welcome.
- @mose - author
- @baptistem - maintainer
This source code is available under MIT license.
Copyright (c) 2016 - Gandi - https://gandi.net