Skip to main content

CollabyBot

Chat Application 📨​

The chat application (Discord or Slack) is the platform through which users will interact with CollabyBot. After CollabyBot is added to a server/workspace, it will run as a bot user that will post messages and respond to user interaction. User interaction will be implemented using slash commands built with the applications' respective libraries. Limited UI design will be done using the tools offered by each application: in Discord, commands can be added to the slash command menu and messages can be formatted as embeds using Pycord; in Slack, messages can be formatted using Block Kit.

CollabyBot :robot:​

The central component of the CollabyBot system is CollabyBot itself, which is a chat bot that resides on our web server and runs as a user in a chat application's server/workspace. It will be represented by a class (one for each supported chat application) that will interact with every other part of the system through various APIs. Users will interact with it in the chat application using a set of commands that be implemented as methods in the CollabyBot class using the appropriate API. The integration with the different chat applications (Discord and Slack are the target platforms) will be accomplished using pre-existing libraries (pycord and Python Slack SDK, respectively).

CollabyBot will have webhooks configured to listen for events from a GitHub repository. The bot will then parse these events and use the chat applications' APIs to post formatted notifications in the server where it is running. Each type of event will have a webhook endpoint and an event handler created using FastAPI.

Web Server 🔑🔒​

Our web server will be a DigitalOcean Linux machine. Our domain will be collabybot.com, and webhook endpoints will be created from this domain. The bot instance will be running on the server, and the server will route HTTPS requests/responses from GitHub and Jira to the bot. A FastAPI app will be run alongside the bot instance using the uvicorn ASGI, which will be listening for GitHub payloads over its webhooks.

Jira API🎫​

CollabyBot will call the Jira API using the Python Jira library, which is a wrapper for the Jira API for Python development. Before CollabyBot can use the API to access a Jira workspace, a user must authenticate using an access token generated in their Jira account's settings. They will then register this token with CollabyBot using the chat client. Only one user in the server will need to register a token for a given Jira workspace.

CollabyBot will call the Jira API to get information about sprints, projects, and tickets in a Jira workspace.

GitHub API​

To use CollabyBot with a GitHub repository, users will add CollabyBot's webhooks to it via the repository's settings. GitHub's API will then send JSON payloads over the webhooks whenever a pull request, issue, or commit (push) event is triggered in the repository.

When CollabyBot needs to call the GitHub API it will do so using the PyGitHub library, which is a wrapper for the GitHub API for Python development.

Class Diagram

Class Diagram

Figure 1. UML Class Diagram​

1. Webhook​

Webhook is the main script for running CollabyBot. When run, it does the following:

  • Creates and runs the FastAPI app that exposes CollabyBot to GitHub using webhooks
  • Creates and runs an instance of DiscordCollabyBot, initializing the Discord bot

The three handler methods are registered with FastAPI endpoints to create webhooks that can be added to a GitHub repository and to receive event payloads.

Fields​

  • app: A FastAPI application instance. Run using uvicorn when the script is executed.
  • discordBotToken: The bot token needed to run the DiscordCollabyBot instance. Loaded from a .env file.
  • discordBot: An instance of DiscordCollabyBot i.e. the Discord bot process. Run as an asyncio task to prevent blocking (see startup_event).

Methods​

  • root(): A webhook method for the root of the domain. Does nothing, but required by FastAPI.
  • payload_handler_commit(): Method for the /webhook/commits endpoint. Executes when a commit event arrives from GitHub.
  • payload_handler_pr(): Method for the /webhook/pull-request endpoint. Executes when a pull request event arrives from GitHub.
  • payload_handler_issues(): Method for the /webhook/issues endpoint. Executes when an issues event arrives from GitHub.
  • startup_event: Runs before the FastAPI application is initialized. Since discordCollabyBot.run() is a blocking method, it must be run as an asyncio task in order for the FastAPI application to start and receive incoming payloads.

2. DiscordCollabyBot​

The DiscordCollabyBot class will contain all of the methods and fields required for the Discord implementation of CollabyBot. It will extend the Bot class from the Pycord library. Its methods fall into three categories:

  • Methods that override methods from the Bot class that are required for basic functionality of the Discord bot
  • Utility methods that facilitate interaction between the bot and other parts of the CollabyBot system
  • Methods for implementing slash commands that are decorated with the @commands.commands decorator from Pycord

Fields​

  • pr_subscribers: A dictionary of repositories and channels IDs in Discord servers that are subscribed to pull request notifications from said repository
  • commit_subscribers: A dictionary of repositories and channels IDs in Discord servers that are subscribed to commit notifications from said repository
  • issue_subscribers: A dictionary of repositories and channels IDs in Discord servers that are subscribed to issue notifications from said repository
  • jira_subscribers: A dictionary of users and authentication information that have registered a Jira workspace in a server.

Methods​

  • on_mention(): Handles mention event in a Discord server, fired when the bot is mentioned by a user. Overrides on_mention() from Pycord's Bot class.
  • on_message(): Handles message event in a Discord server, fired whenever a message is sent by a user. Main purpose is to parse slash commands using Pycord's Bot.process_commands() method. Overrides on_message() from Pycord's Bot class.
  • send_payload_message(): Utility method used by the main application script to send event notifications to the bot. Directs notifications to the correct channels.
  • get_commands(): Implements the/commands slash command, which responds with a list of slash commands and their descriptions.
  • ping(): Implements the /ping slash command, which provides a simple way to test the bot from Discord by responding with "pong."
  • pull_requests(): Implements the /pull-requests slash command, which subscribes the channel it was sent from to pull request notifications.
  • commits(): Implements the /commits slash command, which subscribes the channel it was sent from to commit notifications.
  • issues(): Implements the /issues slash command, which subscribes the channel it was sent from to issue notifications.
  • add(): Implements the /add command, which adds a repository to CollabyBot's list of repositories that notifications can be received from.
  • get_repos(): Implements the /get-repos command, which returns a list of repositories added to CollabyBot's list of repositories that notifications can be received from.
  • open_pull_requests(): Implements the /open-pull-requests command, which returns a list of open pull requests in a specified GitHub repository.
  • jira_setup_token(): Implements the /jira-setup-token command, which will register a Jira workspace with CollabyBot so that users can interact with it using Discord commands.
  • jira_get_issue(): Implements the /jira command, which returns a summary of a specified Jira ticket.
  • jira_assign_issue(): Implements the /jira-assign command, which assigns/reassigns a ticket to a user.
  • jira_unassign_issue(): Implements the /jira-unassign command, which unassigns a ticket to a user.
  • jira_get_sprint(): Implements the /sprint command, which gets information about the active sprint for a Jira project.
  • add_all_commands(): Utility method for registering all slash commands with the DiscordCollabyBot instance in the main application script. Only run once, when the application script is run.

3. Commit​

Class for representing a GitHub commit event.

Fields​

  • commit_message: The event's commit message.
  • action: The action that triggered the event.
  • body: The body of the commit that triggered the event.
  • repo: The repository that the event came from.
  • timestamp: The time that the event was triggered.
  • url: The URL of the repository that triggered the event.
  • user: The username of the user that triggered the event.

Methods​

  • object_string(): Return a string representation of the event to be used as a notification.

4. Issue​

Class for representing a GitHub issue event.

Fields​

  • action: The action that triggered the event.
  • body: The body of the issue that triggered the event.
  • repo: The repository that the event came from.
  • timestamp: The time that the event was triggered.
  • url: The URL of the repository that triggered the event.
  • user: The username of the user that triggered the event.

Methods​

  • object_string(): Return a string representation of the event to be used as a notification.

5. PullRequest​

Class for representing a GitHub pull request event.

Fields​

  • action: The action that triggered the event.
  • body: The body of the pull request that triggered the event.
  • repo: The repository that the event came from.
  • timestamp: The time that the event was triggered.
  • url: The URL of the repository that triggered the event.
  • user: The username of the user that triggered the event.
  • reviewer_requested: Indicates whether a reviewer has been requested for the pull request that triggered the event.
  • reviewer: The name of the reviewer requested, if applicable.
  • review_body: The body of the review if a review action triggered the event.
  • pr_state: The status of the pull request that triggered the event.

Methods​

  • object_string(): Return a string representation of the event to be used as a notification.

Sequence Diagrams

Sequence Diagram #1​

usecase1

Figure 2.1 Use Case #1 Sequence Diagram: As a user, I want to be able to track multiple repositories in the same server/workspace, so I can track all of my teams' project in one place.​

This diagram shows the process of adding different GitHub repositories to different channels within a server.

  1. The user sends /add owner/repo command to add a repository in the #repo1 channel
  2. Messaging app requests to add the repo1 to the CollabyBot
  3. CollabyBot responds with "repo1 has been added"
  4. User sends the commands /pull-requests repo1, /commits repo1, and /issues repo1 in the #repo1 channel to receive notifications from the repository repo1 in a dedicated channel
  5. CollabyBot responds with: "#repo1 channel is now subscribed to pull requests for repo1"
  6. CollabyBot responds with: "#repo1 channel is now subscribed to commits for repo1"
  7. CollabyBot responds with: "#repo1 channel is now subscribed to issues for repo1"
  8. User sends /add owner/repo command to add a repository in the #repo2 channel
  9. CollabyBot responds with "repo2 has been added"
  10. User sends the commands /pull-requests repo2, /commits repo2, and /issues repo2 in the #repo1 channel to receive notifications from the repository repo2 in a dedicated channel
  11. CollabyBot responds with: "#repo2 channel is now subscribed to pull requests for repo2"
  12. CollabyBot responds with: "#repo2 channel is now subscribed to commits for repo2"
  13. CollabyBot responds with: "#repo2 channel is now subscribed to issues for repo2"
  14. GitHub API sends pull request, commit or issue JSON payload for repo1 activate GitHub API
  15. CollabyBot posts formatted message with pull request, commit or issue description in repo1 channel
  16. GitHub API sends pull request, commit or issue JSON payload for repo2 activate GitHub API
  17. CollabyBot posts formatted message with pull request, commit or issue description in repo2 channel

Sequence Diagram #2​

usecase4updpicture

Figure 2.2 Use Case #2 Sequence Diagram: As a user, I want to be able to subscribe certain channels in my chat server to certain types of GitHub events, so that a single channel doesn't get clogged with every notification.​

This diagram shows the process of subscribing a channel within a server to a specific type of GitHub event.

  1. The user downloads the CollabyBot app from a chat application's app directory
  2. CollabyBot is installed in the messaging application
  3. User sends /add owner/repo command to add a repository in messaging app
  4. Messaging app requests to add the repo to the CollabyBot
  5. CollabyBot reponds with "repo has been added" in the messaging app
  6. User sends /pull-requests repo command to subscribe current channel to this pull requests notifications
  7. Messaging app sends a request to subscribe current channel in messaging app to pull requests' notifications to CollabyBot
  8. CollabyBot responds with: "channel is now subscribed to pull requests for repo" to the messaging app
  9. GitHub API sends pull request payload to CollabyBot webhook
  10. CollabyBot posts formatted message with pull request description, date/time was opened, user, URL, etc. in the messaging app.

Sequence Diagram #3​

UseCase3Sequence

Figure 2.3 As a user, I want to be able to see all of the open pull requests in my repository, so I can see what needs to be reviewed without opening GitHub.​

This diagram shows the process of a user requesting a list of open pull requests in a repository called DemoOwner/DemoRepo.

  1. The user sends the message "/open-pull-requests DemoOwner/DemoRepo" in the chat application
  2. The chat application fires a message event which is received by CollabyBot
  3. CollabyBot handles the message with the on_message method
  4. CollabyBot parses the message for commands with the parse_commands method
  5. open_pull_requests("DemoOwner/DemoRepo") is called after CollabyBot parses the /open-pull-requests command from the message
  6. open_pull_requests calls Github.get_repo("DemoOwner/DemoRepo") to request the DemoOwner/DemoRepo repository from the GitHub API
  7. The GitHub API responds with the repository information which is stored in the repo object
  8. open_pull_requests calls GitHub.get_pulls(repo) to request a list of pull requests open in DemoRepo from the GitHub API
  9. The GitHub API responds with a list of pull requests open in DemoRepo
  10. open_pull_requests loops over the lists and each PR's name title and URL to a response message
  11. open_pull_requests calls send to send the message to the chat client
  12. The client displays the message containing the formatted list of pull requests to the user

Sequence Diagram #4​

usecase4jiraticket

Figure 2.4 Use Case #4 Sequence Diagram: As a user, I want to be able get information about a specific ticket on demand, so that I can check its status without having to open Jira.​

This diagram shows the process of getting information about a specific Jira ticket on demand.

  1. The user downloads the CollabyBot app from a chat application's app directory
  2. CollabyBot is installed in the messaging application
  3. User sends /jira-setup-token your-team-jira-host token in the messaging applications
  4. CollabyBot receives a request to authorize token to be able to access JiraAPI
  5. CollabyBot sends token and your-team-jira-host credentials to JiraAPI
  6. JiraAPI gets credentials and responds with success to the CollabyBot
  7. CollabyBot sends message "Token registered" upon success to the messaging app
  8. Now user can retrieve information about specific ticket in the messaging app by sending /jira ticketID in the messaging app
  9. CollabyBot receives request for /jira ticketID command
  10. CollabyBot sends a request to retrieve data for ticketID to JiraAPI
  11. JiraAPI sends ticket's summary, description, status, assignee, parent epic to the CollabyBot
  12. CollabyBot posts message formatted as embed in the messaging app with the ticketID information

Sequence diagram #5

Screenshot20221109223426

Figure 2.5 Use Case #5 Sequence Diagram: As a user, I want to be able to view the active sprint's backlog from a chat server/workspace, so that I can see what work needs to be done without opening Jira.​

This diagram shows the process of getting Jira's active sprint information.

  1. The user downloads the CollabyBot app from a chat application's app directory
  2. CollabyBot is installed in the messaging application
  3. User sends /jira-setup-token your-team-jira-host token in the messaging applications
  4. CollabyBot receives a request to authorize token to be able to access JiraAPI
  5. CollabyBot sends token and your-team-jira-host credentials to JiraAPI
  6. JiraAPI gets credentials and responds with success to the CollabyBot
  7. CollabyBot sends message "Token registered" upon success to the messaging app
  8. Now user can retrieve sprint data by sending /sprint command in the messaging app
  9. CollabyBot receives request for /sprint command
  10. CollabyBot sends a request to retrieve data for active sprint to JiraAPI
  11. JiraAPI sends current active sprint data to the CollabyBot
  12. CollabyBot sends data about current sprint to messaging app posts this data as a message

Sequence Diagram #6​

Screenshot20221109230207

Figure 2.7 As s user, I want to be able to assign a Jira ticket to a team member using a bot command, so that I can quickly assign tickets without having to open Jira.​

This diagram shows the process of assigning/reassigning a team member to a Jira ticket.

  1. The user downloads the CollabyBot app from a chat application's app directory
  2. CollabyBot is installed in the messaging application
  3. User sends /jira-setup-token your-team-jira-host token in the messaging applications
  4. CollabyBot receives a request to authorize token to be able to access JiraAPI
  5. CollabyBot sends token and your-team-jira-host credentials to JiraAPI
  6. JiraAPI gets credentials and responds with success to the CollabyBot
  7. CollabyBot sends message "Token registered" upon success to the messaging app
  8. User sends sends /jira-assign ticket number command in the messaging app
  9. Messaging app sends request for /jira-assign ticket command to CollabyBot
  10. CollabyBot sends request to JiraAPI to retrieve data for the available assignees
  11. JiraAPI responds with current available assignees for the requested ticket
  12. CollabyBot receives the data and posts current available assignees to choose from in messaging app
  13. User sends /jira-assign assignee to the messaging app
  14. Messaging app sends a request to assign ticket to CollabyBot
  15. CollabyBot makes a request to assign ticket to assignee to JiraAPI
  16. JiraAPI responds with success and ticket info along with assignee to the CollabyBot
  17. CollabyBot posts ticket with updated assignee to the messaging app