The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

Introduction To Bif

Bif is a command-line project management tool, with a focus on distributed bug tracking.

This is an introduction to bif version 0.1.5_1 (2015-08-04) based on situations typically encountered by software developers. It is assumed that you are comfortable working with command line programs and your operating system shell (e.g. bash).

Terminology

Repository

A bif repository is usually a configuration file and an SQLite database inside a .bif/ directory. The database contains the history, status and relationships of a set of topics. All bif commands find the "current working" repository by searching upwards through the file-system for such a directory. The terms repository and database are often used interchangeably.

Topic

Topic is is a catch-all term for a task, issue, bug, feature, etc. Topics are identified by an integer ID which is unique to the local repository. They also have a hexidecimal UUID which is globally unique. Some topic types (issues for example) can be associated with multiple projects in which case they have multiple IDs and multiple status values.

Project

A project is a topic that comes with the extra functionality of grouping tasks and issues together. Multiple projects can be managed within a repository, and sub-projects can be defined hierarchically. Projects are identified by their "path" the same way directories in a filesystem are.

Often a top-level project will actually represent an organisation rather than a specific project, so some care should be taken when naming them to ensure they are globally unique, or at least unique amongst all the other projects they may interact with. See bif-new-project for details.

Hub

A bif hub is a remote repository established for the purpose of exchanging updates. A hub is referred to as hub.name@host.location. Typically the hub name is either a project name or an organisation name.

Initialization

Bif commands that make changes to a repository need to know your identity. Bif stores your name and email address in a special user repository which will be created the first time you run bif-init.

    bif init
    # Initialising repository: $HOME/.bifu (v323)
    # Creating "self" identity:
    #   Name: [Your Name] 
    #   Contact Method: [email] 
    #   Contact Email: [your@email.adddr] 
    # Identity created: 1
    # Initialising repository: $PWD/.bif (v323)
    # Importing identity from $HOME/.bifu

An initialized repository always starts out empty - there is no bif equivalent of the git-clone command.

You generally do not have to remember the location of a repository as it is automatically discovered when you are working in a subdirectory.

Creating your user identity

Bif needs to know who you are when you make changes. You create your identity in a special user repository (typically $HOME/.bifu) when you pass the --user-repo option to the bif-init command:

    $ bif init --user-repo

You only need to do this once.

Initialize a repository

A repository must be initialized before you can create any topics:

    bif init

The very first time that bif-init runs it also prompt the user for various identity details and creates the user repository .bifu, before continuing with the original action.

Create, List And Modify Topics

Create a project, identified by a name and a title. You will also be prompted to add an initial change message.

    bif new project todo Things to do

Create some tasks and issues. Use the --message|-m option to prevent your $EDITOR from being invoked.

    bif new task Take out the rubbish
    bif new issue I need more spare time -m "meh!"

Retrieve the lists of things you have created:

    bif list projects
    bif list topics

Change the status of some things using the change command, but first you might want to know which status types are valid:

    bif list task-status
    bif update 16 closed

View the history of changes to a particular topic:

    bif log 16

Not giving an ID argument to log will display the entire history of the repository.

Share An Issue Between Two Projects

    bif new project other Someone elses problem
    bif push 17 other

But recognise that their status can be individually modified:

    bif update 45 closed

So how do we see all the current statuses of an issue?

    bif show 45

Fork An Existing Project

Say you are managing a software project, and you are releasing a new version but are also continuing to work on your development branch. Rather than having to push each issue separately from the old project to the new we can just fork the old one.

    bif new project v2 --fork devel

And notice that the new project has exactly the same issues as the original:

    bif list topics

Collaborating With Others

Need to import the project details from an organisation's hub somewhere.

    bif pull hub organisation@hub.com

Then, most likely, someone else already created the project, and you just want to work on it too:

    bif import todo organisation
    bif list projects

Then to exchange changes you make and get changes others have made, just call sync:

    bif sync

Scenario 1 - Standalone Project Management

The first scenario we present is for an individual wanting to keep track of their personal activities.

    + - - - - - - - - - -+
    ' Local Repository   '
    '                    '
    ' +----------------+ '
    ' |     issues     | '
    ' +----------------+ '
    ' +----------------+ '
    ' |    projects    | '
    ' +----------------+ '
    ' +----------------+ '
    ' |     tasks      | '
    ' +----------------+ '
    '                    '
    + - - - - - - - - - -+

Creating Projects

The bif-new-project command asks for a project path (like a name for identification), a title, and an initial comment. That information can be given on the command line if desired, otherwise it will be prompted for.

    bif new project

    # Path: [] todo
    # Title: [] Things to do
    # An editor is invoked for the comment

Projects can be nested by defining them with a parent path and a "/":

    bif new project

    # Path: [] todo/today
    # Title: [] Things to do today
    # An editor is invoked for the comment

Apart from visual organisation, the main impact of having nested projects is that child projects are included when importing or exporting them to hubs. Also, child projects will not be displayed in list commands if the parent project will not be displayed.

A project has three different types of status associated with it. Project status is for the status of the project itself. Task and issue status is obviously for the status of tasks and issues associated with the project. New projects can be created using different status templates, given specific initial status, or copied/forked from other projects.

Creating Tasks and Issues

Tasks and issues are created similarly to projects, with a summary and a comment. As they exist only in the context of a project they may also require a project path if more than one project exists in the repository.

    bif new task

    # Project: [todo] todo/today
    # Title: Take out the rubbish
    # editor invoked - describe the task in more detail

A task or an issue, like a project, is created with the default status for that type according to the project. An different initial status can be set with the --status option:

    bif new issue --status needinfo

    # Project: [todo] todo/today
    # Title: Don't feel like taking out the rubbish
    # editor invoked - describe the task in more detail

A comment can be provided directly with the --message option if desired instead of having the editor invoked.

Template Projects

Do you have repeatable projects?

Retrieving Information

Tasks and issues can be viewed, commented on and updated with the appropriate commands:

Updating Topics

You can add comments to a topic with the bif-update command.

    bif update ID [--message MESSAGE]
    

If the --message option is not used an editor will be invoked. A second argument can also be used to change the status of the topic, and a --title option can be used to modify the topic summary.

    bif update ID [STATUS] [--title TITLE]

Comments on a topic can also be nested. That is, you can use bif-reply to respond to a previous update (or a previous reply).

    bif reply UPDATE_ID [--message MESSAGE]

The UPDATE_ID argument is actually a full ID.UPDATE_ID value that you see with the bif-log command. bif-reply cannot modify a topic's status or title.

Editing

There is no mechanism for editing available in bif at this time. Be as wild in your comments as you like, but as with the rest of the internet, once your changes have been shared, you most likely can't alter them or take them back. First rule of commenting is: take a deep breath first.

Deletion

Of course, even after taking a deep breath you may anyway make a change to your repository that you didn't mean to. You are not alone; this happens to all of us. As long as you have not already synchronised your changes with a hub, they can be removed[1].

The bif-drop command can be used to remove a particular comment, or an entire topic.

[1] There is nothing magical or otherwise to stop you from dropping any change. However you will find that as soon as you re-synchronise with a hub that has those changes they will return to haunt you like the undead.

Scenario 2 - Distributed Project Team

The above scenario only uses local operations. However the real value of bif comes from its collaboration capabilities with others via the internet. The second scenario presents the

Project team members probably want to know about every issue and task in a project.

    + - - - - - - +     + - - - - - - - - - - - - - - - - - -+
    ' Local       '     ' Remote                             '
    '             '     '                                    '
    ' +---------+ '     ' +--------+     +----------+        '
    ' |  issue  | ' --- ' | issues | --- | projects | ---+   '
    ' +---------+ '     ' +--------+     +----------+    |   '
    '             '     '                                |   '
    '             '     + - - - - - - - - - - - - - -    |   '
    '   |         '                        |         '   |   '
    '   |         '                        |         '   |   '
    '   |         '                        |         '   |   '
    ' +---------+ '                        |         '   |   '
    ' | project | '------------------------+         '   |   '
    ' +---------+ '                                  '   |   '
    '   |         '                                  '   |   '
    '   |         '                                  '   |   '
    '   |         '                                  '   |   '
    '             '     + - - - - - - - - - - - - - -    |   '
    '             '     '                                |   '
    ' +---------+ '     ' +--------+                     |   '
    ' |  task   | ' --- ' | tasks  | --------------------+   '
    ' +---------+ '     ' +--------+                         '
    '             '     '                                    '
    + - - - - - - +     + - - - - - - - - - - - - - - - - - -+

Signing up with a provider

As previously mentioned, a remote repository known as a hub is the mechanism for exchanging updates with others. You can either self host a hub on a server you control, or you can use a commercial provider. Regardless of who is hosting, the communication with the server is via ssh, for which you will want your own ssh keypair.

Read the ssh-keygen(1) manpage for how to create a keypair, and ssh-copy-id(1) for how to transfer the public key to your own server. Hub providers will probably use another method for transfering the public key during their signup process.

Registering With A Hub

The reason for registering with a hub is to obtain the list of projects hosted there.

    bif pull hub my.org@provider.com

By default the my.org part of the provider address can be used as the hub name in other commands. To view the list of projects we give the hub alias to the bif-list-projects command:

    bif list projects my.org

Registering a project brings in a shallow copy - only the project and its status types are visible. The local user can create issues against this project just as if the project was local.

Importing Projects

A developer must also sign up and register a hub as described previously. They can then import an entire project into their local repository using the bif-pull-project command.

    bif pull project devel@bifax.org

Importing a project is a one-time activity. Updates to a project that occur after an import have occured are exchanged with the bif-sync command. Any new issues or tasks added to the project anywhere will now synchronise locally. Likewise, any topics added locally will be distributed to the hub.

The nice thing about pulling projects is that you only get the data that you want to see locally. As time goes on and projects are created and then completed, their relevance becomes less and less. New team members are not forced to download the entire project history to work on the current project.

Exporting Projects

How did a project get up to a hub in the first place? Well the inverse of bif-pull-project is bif-push-project. To mirror the todo project from the local repository to the bifax.org hub for example we would run the following:

    bif push project todo bifax.org

As with importing, exporting a project is a one-off activity; further updates are exchanged with the bif-sync command.

Synchronising & Reviewing Updates

Updates such as new topics or updates to existing topics are not exchanged until you run the bif-sync command.

    bif sync [ID] [HUB]

By default all topics will be synchronised to all relevant hubs, but you can limit that as desired.

    bif sync -p unstable   # ignore all other projects

[TODO: describe the merge algorithm for meta data]

What is useful after a bif-sync call is to review what updates were transfered from the hub to the local repository. The bif-log command (an alias for bif-log-repo does just that.

    bif log repo

Actions that were transferred into the local repository during the last sync are marked in the output of the log and list commands. New topics are prefixed with a "+". Updated topics are prefixed with a "+-".

Advanced Topic Management

Inter-Project Issue Collaboration

There are occasions when an issue reported in a project is also, or perhaps only in the domain of another project. Bif therefore has the ability to fork/copy/move individual issues.

The bif-push-issue command is the way to manually ask another project for support on a particular issue. The bif-push-issue command asks for (or can be given) an update message the same way that a bif-update command does:

    bif push issue 13 todo2 \
        --action fork \
        --message "also present in todo v2"

The --action option determines the relationship between the issue and its old and new projects. Note that this command is still local - the change will be propagated during the next bif-sync call.

As was mentioned in the introduction, issue status is tracked on a per-project basis. This means one project can consider the issue solved and another project can still consider the issue to be blocking. When an issue is pushed somewhere it therefore gains an extra topic ID, and can show up in multiple times in the output of the bif-list-topics command. The bif-show-issue command reveals the details:

    bif show issue 13

Task Collaboration?!?

It does not make sense to distribute tasks across projects the same way issues can be. A single task cannot have multiple status: it is either done or it is not, regardless of which projects are interested in the outcome.

There are however reasons for migrating tasks from one project to another. The obvious one is simply that they can be defined (by accident or circumstance) in the wrong place. The default bif-push-task action therefore results in a move.

Alternatively the --action copy option to bif-push-task does what it says on the label, which can be useful if you have a template task in a project that you regularly want to use in other projects. Once again however, bif-new-project probably has more interesting mechanisms for copying template-style projects.

Making A New Release

Consider what happens when a software team makes a new stable release from their development version. This is effectively an internal fork - a new project that kicks off as the first project continues along the same path. At the time of the fork both projects will have exactly the same set of issues. From that point on the issue status may diverge based on project activities, but the issues they have in common have themselves not inherently changed.

The --dup option to the bif-new-project command lets us deal with the above situation, which specifies an existing project from which to copy the project title and status names from. We can also specify that issues should be copied, moved, or forked with the --copy-issues, --move-issues and --fork-issues options, each of which takes a status argument and can be called multiple times.

    bif new project v2 \
        --dup devel \
        --fork-issues open,stalled \
        --move-issues closed

There are similar copy/move options for tasks. In contrast to a copy, comments made on forked issues in one project will propagate to other projects, as if there was only a single issue, which is in fact the case.

Inter-hub Collaboration

There are times when an issue may be reported to one organisation, but should actually be resolved by a different organisation. This situation is often encountered by operating system distributors and also occurs when software has external dependencies. To address this bif makes it possible (under certain conditions) to collaborate on an issue across multiple hubs. [to be implemented]

External Collaboration

Imagine the situation where a (non-team-member) user has an issue they want to report to a project team.

    + - - - - - - - - - -+     +- - - - - - - +
    ' Local Repository   '     ' Remote Hub   '
    '                    '     '              '
    ' +----------------+ '     ' +----------+ '
    ' |     issue      | ' --> ' | project  | '
    ' +----------------+ '     ' +----------+ '
    '                    '     '              '
    + - - - - - - - - - -+     +- - - - - - - +

Repository Administration

New versions of bif will necessarily require changes to the database structure, and possibly the data itself. The bif-upgrade command exists to advance the database status to match that required by the bif software version. It is safe (but pointless) to run bif-upgrade when the versions already match. When and how this command is run should be described in the release notes of newer versions of bif.

One other command which is more about the repository than project management is bif-sql. This is more of a developer or debugging aide for querying the database directly. This is needed as the bif software architecture prevents the SQLite command-line tool sqlite3 from working for some statements.

Hub Administration

Bif is also used to create and manage hub repositories hosted by a hub provider.

Quickstart

If you want to create a new hub and already know the provider's plan & host(s) you wish to use, you can get up and running with the following command inside an initialized repository:

    bif signup --create hub.name bifhub.com:plan host

This is equivalent to the following:

    bif pull provider bifhub.com
    bif new hub hub.name
    bif signup hub.name plan
    bif push hub hub.name host

Importing a providers plans and locations

The second step is to register a hub provider, in order to see their hosts and/or availabe plans.

    bif pull provider bifhub.com

Listing the offers (plans) and locations (hosts) is possible with the appropriate list command:

    bif list hosts

    bif list plans

Signing up for a plan

    bif signup my.org bifhub.com:plan2

This will do a check with the provider to ensure that the name has not been already taken. If successful you should be able to see the invoice:

    bif list invoices

Initializing A Hub

The bif-init command is also used to create a hub repository when given the appropriate arguments.

    bif init [NAME] [LOCATION]

The first argument to the init command is the name of your hub. The name is representative of your project organisation, and should be globally unique. We generally recommend to use something similar to a DNS zone.

When the LOCATION specified matches one of the hosts from a provider than the initialization happens remotely.

Team communication

After a push your hub will be available on the designated hosts, and you can inform your team how to register their bif repositories with the hub:

    Hi team,

    Our collaboration hub has been created at the following location:

        your.org@zrh.bifhub.com
    
    To access the hub send us your identity from a local bif
    repository:
        bif init
        bif push identity 1 your.org@zrh.bifhub.com

    Once we have enabled the permissions you can register the hub:
        bif pull hub your.org@zrh.bifhub.com

    And then import the "devel" project to work on straight away.
        
        bif pull project devel

        # bif new issue/task etc...

    Don't forget to sync regularly.
        bif sync

    Thanks,
    PM

Managing the hub

You can at any time confirm the hub and its status:

    bif list hubs

    bif show hub ID

At some point in the future there will be actions that a hub manager can take, such as allowing access, defining roles & permissions, paying invoices and so on.

See Also

bif-doc

Author

Mark Lawrence <nomad@null.net>

Copyright and License

Copyright 2013-2015 Mark Lawrence <nomad@null.net>

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.