Ubiquity DAO's GitHub Bot to automate DevPool management.
#!/bin/bash
git clone https://github.com/ubiquity/ubiquibot.git
cd ubiquibot
yarn
yarn build
yarn start:watch- Copy 
.env.exampleto.env - Update 
.envwith the following fields: SUPABASE_URL: Add your Supabase project URL.SUPABASE_KEY: Add your Supabase project API key.LOGDNA_INGESTION_KEY: Get it from Memzo by creating an account, adding an organization, and copying the ingestion key on the next screen.FOLLOWUP_TIME: (optional) Set a custom follow-up time (default: 4 days).DISQUALIFY_TIME: (optional) Set a custom disqualify time (default: 7 days).OPENAI_API_HOST: (optional) Set OpenAI host url (default: https://api.openai.com).OPENAI_API_KEY: Set OpenAI key.CHATGPT_USER_PROMPT_FOR_IMPORTANT_WORDS: (optional) Set a custom user prompt for finding important words (default: "I need your help to find important words (e.g. unique adjectives) from github issue below and I want to parse them easily so please separate them using #(No other contexts needed). Please separate the words by # so I can parse them easily. Please answer simply as I only need the important words. Here is the issue content.\n").CHATGPT_USER_PROMPT_FOR_MEASURE_SIMILARITY: (optional) Set a custom user prompt for measuring similarity (default: 'I have two github issues and I need to measure the possibility of the 2 issues are the same content (No other contents needed and give me only the number in %).\n Give me in number format and add % after the number.\nDo not tell other things since I only need the number (e.g. 85%). Here are two issues:\n 1. "%first%"\n2. "%second%"').SIMILARITY_THRESHOLD: (optional) Set similarity threshold (default: 80).MEASURE_SIMILARITY_AI_TEMPERATURE: (optional) Set ChatGPT temperature for measuring similarity (default: 0).IMPORTANT_WORDS_AI_TEMPERATURE: (optional) Set ChatGPT temperature for finding important words (default: 0).
APP_ID and PRIVATE_KEY are here for internal developers to use.
If you are an external developer, APP_IDand PRIVATE_KEY are automatically generated when you install the app on your repository.
Note: When setting up the project, please do not rename the .env.example file to .env as it will delete the environment example from the repository.
Instead, it is recommended to make a copy of the .env.example file and replace the values with the appropriate ones.
- This bot is designed to exist as a GitHub Action.
 - The code must be compiled using 
@vercel/nccbecause all the dependencies (e.g.node_modules) must be included and committed on the repository for the GitHub Actions runner to use. 
- Go to the UbiquiBot App Marketplace
 - Choose a plan and install UbiquiBot on your repository
 - Congratulations! You can now use the UbiquiBot to manage your bounties.
 
To test the bot, you can:
- Create a new issue
 - Add a time label, ex: 
Time: <1 Day - Add a priority label, ex: 
Priority: 0 (Normal) - At this point the bot should add a price label.
 
evm-network-id is ID of the EVM-compatible network that will be used for payouts.
price-multiplier is a base number that will be used to calculate bounty price based on the following formula: price = price-multiplier * time-label-weight * priority-label-weight * 100
time-labels are labels for marking the time limit of the bounty:
nameis a human-readable namevalueis number of seconds that corresponds to the time limit of the bounty
priority-labels are labels for marking the priority of the bounty:
nameis a human-readable name
command-settings are setting to enable or disable a command
nameis the name of the commandenabledis atrueorfalsevalue to enable or disable a command
default-labels are labels that are applied when an issue is created without any time or priority labels.
assistive-pricing to create a new pricing label if it doesn't exist. Can be true or false.
disable-analytics can be true or false that disables or enables weekly analytics collection by Ubiquity.
payment-permit-max-price sets the max amount for automatic payout of bounties when the issue is closed.
comment-incentives can be true or false that enable or disable comment incentives. These are payments generated for comments in the issue by contributors, excluding the assignee.
issue-creator-multiplier is a number that defines a base multiplier for calculating incentive for the creator of the issue.
comment-element-pricing defines how much is a part of the comment worth. For example text: 0.1 means that any text in the comment will add 0.1
incentives defines incentive rewards:
commentdefines comment rewards:elementsdefines reward value for HTML elements such asp,img,a.totals:worddefines reward for each word in the comment
max-concurrent-assigns is the maximum number of bounties that can be assigned to a bounty hunter at once. This excludes bounties with delayed or approved pull request reviews.
register-wallet-with-verification can be true or false. If enabled, it requires a signed message to set wallet address. This prevents users from setting wallet address from centralized exchanges, which would make payments impossible to claim.
promotion-comment is a message that is appended to the payment permit comment.
- Create a new project at Supabase. Add 
Project URLandAPI Keyto the.envfile: 
SUPABASE_URL="XXX"
SUPABASE_KEY="XXX"
- Create a new organization at Memzo. Add 
LOGDNA_INGESTION_KEYto the.envfile: 
LOGDNA_INGESTION_KEY ="XXX"
- Add 
FOLLOW_UP_TIMEandDISQUALIFY_TIMEto the.envfile if you don't want to use default ones. 
FOLLOW_UP_TIME="4 days" // 4 days
DISQUALIFY_TIME="7 days" // 7 days
yarn install- Open 2 terminal instances:
- in one instance run 
yarn build --watch(compiles the Typescript code) - in another instance run 
yarn start:watch(runs the bot locally) 
 - in one instance run 
 - Open 
localhost:3000and follow instructions to add the bot to one of your repositories. 
At this point the .env files auto-fill the empty fields (PRIVATE_KEY and APP_ID) if it is not previously filled.
Now you can make changes to the repository on GitHub (e.g. add a bounty) and the bot should react.
You can, for example:
- Create a new issue
 - Add a time label, ex: 
Time: <1 Day - Add a priority label, ex: 
Priority: 0 (Normal) - At this point the bot should add a price label, you should see event logs in one of your opened terminals
 
Bounty bot is built using the probot framework so initially the bot is a github app. But thanks to the probot/adapter-github-actions you can also use the bot as a github action.
You can use the bounty bot as a github app.
When using as a github app the flow is the following:
- Bounty bot is added to a repository as a github app
 - You run the bot "backend" (for example on your local machine)
 - Some event happens in a repository and the bot should react somehow (for example: on adding a time label to an issue the bot should add a price label)
 - Event details are sent to your deployed bot instance (to a webhook URL that was set in github app's settings)
 - The bot handles the event
 
For payment to work in your local instance, ubiquibot must be set up in a Github organization. It will not work for a ubiquibot instance set up in a personal account. Once, you have an ubiquibot instance working in an organization, follow the steps given below:
- 
Create a new private repository in your Github organization with name
ubiquibot-config - 
Add your ubiquibot app to
ubiquibot-configrepository. - 
Create a file
.github/ubiquibot-config.ymlin it. Fill the file with contents from this file. - 
Go to https://pay.ubq.fi/keygen and generate X25519 public/private key pair. Fill private key of your wallet's address in
PLAIN_TEXTfield and clickEncrypt. - 
Copy the
CIPHER_TEXTand append it to your repoubiquibot-config/.github/ubiquibot-config.ymlasprivate-key-encrypted: "PASTE_YOUR_CIPHER_TEXT_HERE" - 
Copy the
X25519_PRIVATE_KEYand append it in your local ubiquibot repository.envfile asX25519_PRIVATE_KEY=PASTE_YOUR_X25519_PRIVATE_KEY_HERE 
Make sure you have your local instance of ubiquibot running.
- Fork the ubiquibot repo and add your local instance of ubiquibot to the forked repository.
 - Enable Github action running on the forked repo and allow 
issueson the settings tab. - Create a QA issue similar to this where you show the feature working in the forked repo.
 - Describe carefully the steps taken to get the feature working, this way our team can easily verify.
 - Link that QA issue to the pull request as indicated on the template before requesting a review.
 
- Update the version in package.json: 
yarn version --new-version x.x.x - Commit and create a new tag: 
git commit -am x.x.x && git tag -am x.x.x - Push tags: 
git push origin v"x.x.x" - The Github action will create a release by recognizing the version tag
 
Bounty bot is built using the probot framework so initially the bot is a github app
<root> ├── bin: Binary file and action file compiled by `@vercel/ncc` ├── docs: Documentations ├── src : Main source code ├── supabase: Supabase migrations and configuration file
<src> ├── adapters: A set of interaces to interact with 3rd party libraries such as Telegraf, supabase-js.
It consists of a set of small functions bulit on top of a specific library.
Every adapter needs to be for calling a specific method of the library. | ├── bindings: A set of listeners to bind/process requests emitted by GitHub.
It also has a function to load a project configuration. | ├── configs: Constants and default config values used to create a bot configuration
in case we're missing any needed configuration parameters from both .env and config file. | ├── handlers: A set of event-based processors.
Each handler processes a specific request and it may consist of pre, action and post handlers.
A pre handler would be running in prior to the main action which needs to be shorter not to affect the main handler's process.
A post handler would be running as soon as the main handler gets completed.
It has no limitation on its completion time.
For example, it could be an example of pre-handler to create missing price labels
because if we don't have necessary labels created already on the repo, labeling non-exists labels would definitely throw. | ├── types A set of schema and type definitions.
Why do we need schema? because we want to validate the unknown input and throw the error before the main execution. | ├── utils A set of utility functions
We can't use a jsonc file due to limitations with Netlify. Here is a snippet of some values with notes next to them.
Search
PG_CRONand Enable it.
-- Runs everyday at 03:00 AM to cleanup logs that are older than a week
-- Use the cron time format to modify the trigger time if necessary
select
  cron.schedule (
    'logs-cleaner', -- Job name
    '0 3 * * *', -- Everyday at 03:00 AM
    $$DELETE FROM logs WHERE timestamp < now() - INTERVAL '1 week'$$
  );
-- Cancel the cron job
select cron.unschedule('logs-cleaner');
{ "payment-permit-max-price": 9007199254740991, // Number.MAX_SAFE_INTEGER "max-concurrent-assigns": 9007199254740991, // Number.MAX_SAFE_INTEGER "comment-element-pricing": { /* https://github.com/syntax-tree/mdast#nodes */ "strong": 0 // Also includes italics, unfortunately https://github.com/syntax-tree/mdast#strong /* https://github.com/syntax-tree/mdast#gfm */ } }