# PR Tools A set of command-line tools for managing descentralized git pull requests and code review workflows. These tools help with creating PR snapshots, sending notifications to Slack, tracking approvals, merging PRs, reviewing changes, and viewing annotated diffs. Please read the [motivation](https://copilot.microsoft.com/shares/pages/VKL8KZ8pMhsYY68x7TZsr) for a more in-depth info about the purpose of these tools. ## Features - **pr-snapshot**: Generate a Markdown snapshot of the PR including commits and diff summary. - **pr-send**: Send the PR snapshot to a Slack channel for review. - **pr-track**: Track PR approvals, status, and commit history. - **pr-merge**: Merge approved PRs with various strategies and update changelog. - **pr-review**: Interactive code review tool with comment management. - **pr-view**: View annotated diffs with review comments. - **pr-fix**: Fix comments received in a review. - **pr-init**: Interactively generate configuration file for pr-tools. ## Installation This project is built with Haskell and Cabal. To install: 1. Ensure you have [GHC](https://www.haskell.org/ghc/) and [Cabal](https://www.haskell.org/cabal/) installed. Use [GHCup](https://www.haskell.org/ghcup/) for easy installation. - For Windows, you can use the [Haskell Platform](https://www.haskell.org/platform/). - For macOS, you can install GHC and Cabal via Homebrew: ``` brew install ghc cabal-install ``` 2. Clone the repository: ``` git clone cd pr-tools ``` 3. Build and install the executables: ``` cabal update cabal install ``` This will install the binaries in `~/.cabal/bin` (or equivalent). Add this directory to your PATH if necessary. ## How to upgrade from source Update the source tree and reinstall: cd pr-tools git checkout master && git pull && cabal install --overwrite-policy=always ## Configuration ## Slack Configurations PR Tools supports two Slack integration methods: Incoming Webhooks for simple text messages and Slack API Tokens for advanced features like file attachments. Webhooks are easier to set up and sufficient for basic notifications, while API Tokens enable uploading detailed content as files, improving readability for long messages (e.g., reviews or snapshots). If both are configured, the tool prioritizes API Tokens for commands that benefit from attachments; otherwise, it falls back to webhooks. ### Webhook Configuration Webhooks allow posting plain text messages to a Slack channel. This is ideal for short notifications but may truncate or clutter long content. To obtain a webhook: 1. Go to [Slack Apps](https://api.slack.com/apps) and create a new app. 2. Enable "Incoming Webhooks" under "Add features & functionality". 3. Activate webhooks and add one to a channel, copying the generated URL (starts with `https://hooks.slack.com/services/`). Add to your `.pr-tools.yaml`: ```yaml slack-webhook: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" ``` If not set, commands like `pr-send` will fail, and others (e.g., `pr-merge`) will skip notifications. ### Slack API Token Configuration API Tokens enable file attachments, allowing detailed messages (e.g., from `pr-review send`, `pr-fix send`, `pr-send`) to be uploaded as .md files with a short summary message. This requires a bot token with `files:write` scope. To obtain a token: 1. Go to [Slack Apps](https://api.slack.com/apps) and create a new app. 2. Under "Add features & functionality", select "Bots" and create a bot user. 3. Under "OAuth & Permissions", add the `files:write` scope (and optionally `chat:write` for messages). 4. Install the app to your workspace, granting permissions. 5. Copy the "Bot User OAuth Token" (starts with `xoxb-`). 6. Find the channel ID: In Slack, right-click the channel, select "View channel details", and copy the ID (starts with `C` or `G`). 7. Invite the `pr-tools` bot to the channel: ``` /invite @pr-tools ``` Add to your `.pr-tools.yaml`: ```yaml slack-token: "xoxb-your-bot-token" slack-channel: "C0123456789" # Channel ID ``` ### Base Branch and Slack Configuration Use `pr-init` or manually create a `.pr-tools.yaml` file in the project root with: ```yaml base-branch: main # or your default base branch slack-webhook: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" # optional slack-token: "xoxb-your-bot-token" # optional for attachments slack-channel: "C0123456789" # required if using token ``` ### Recommended .gitignore Entries To avoid committing temporary files generated by pr-tools, add the following to your `.gitignore` file: ``` .pr-drafts/ .pr-reviews/ .pr-fixes/ .pr-state.yaml .pr-tools.yaml # Optional, if you don't want to commit the config ``` ## Usage ### pr-snapshot Generate a Markdown snapshot of the PR including commits and diff summary. The snapshot is saved in .pr-drafts/.md. If no message is provided, it opens an editor to enter the description. ``` pr-snapshot [BRANCH] [--base-branch BASE] [--message MESSAGE] ``` - `BRANCH`: The feature branch (default: current branch). - `--base-branch BASE`: Override the configured base branch. - `--message MESSAGE`, `-m MESSAGE`: Provide the PR description directly without opening an editor. ### pr-send Send the PR snapshot to a Slack channel for review. Requires slack-webhook configured. ``` pr-send [BRANCH] ``` - `BRANCH`: The feature branch (default: current branch). ### pr-track Track PR approvals and status. Subcommands: ``` pr-track approve [BRANCH] --by NAME pr-track status [BRANCH] pr-track record [BRANCH] pr-track update [BRANCH] pr-track list ``` - `approve [BRANCH] --by NAME`: Approve the PR by the given name. `BRANCH` defaults to current. - `status [BRANCH]`: Get the status, approvals, and merge status for the PR. Checks if commits are merged into the base branch. `BRANCH` defaults to current. - `record [BRANCH]`: Record or update the commit snapshot for the PR. Synonyms: update, u, r, rec. `BRANCH` defaults to current. - `list`: List all tracked PRs with status and approval counts. ### pr-merge Merge approved PRs with various strategies and update changelog. Optionally sends notification to Slack. ``` pr-merge [BRANCH] [--strategy {fast-forward|squash|rebase}] [--base-branch BASE] ``` - `BRANCH`: The feature branch (default: current). - `--strategy STRATEGY`: Merge strategy (default: fast-forward). - `--base-branch BASE`: Override the configured base branch. ### pr-review Interactive code review tool with comment management. Subcommands: ``` pr-review start [--base-branch BASE] pr-review next pr-review previous pr-review open pr-review files pr-review changes pr-review comment --file FILE --line LINE --text "COMMENT" pr-review resolve --id ID pr-review end pr-review list pr-review send pr-review comments [--with-context] ``` - `start [--base-branch BASE]`: Start or resume a review session. `--base-branch` overrides configured base. - `next`: Move to the next file and open in editor for commenting. - `previous`: Move to the previous file and open in editor. - `open`: Open the current file in editor for commenting. - `files`: List files with changes, indicating current. - `changes`: Show the git diff. - `comment --file FILE --line LINE --text "COMMENT"`: Add a comment via CLI. - `resolve --id ID`: Mark a comment as resolved. - `end`: End the review session. - `list`: List all review sessions. - `send`: Send the review comments to Slack. - `comments [--with-context]`: List comments, optionally with code context. ### pr-view View annotated diff or comments. Subcommands: ``` pr-view diff [BRANCH] [--base-branch BASE] [--full] pr-view comments [BRANCH] ``` - `diff [BRANCH] [--base-branch BASE] [--full]`: Show annotated diff with comments. `--full` shows complete files including unchanged areas. `BRANCH` defaults to current. - `comments [BRANCH]`: List all comments with context. `BRANCH` defaults to current. - `--base-branch BASE`: Override the configured base branch. ### pr-fix Manage fix sessions for review comments. Subcommands: ``` pr-fix start pr-fix comments [--with-context] pr-fix files pr-fix open pr-fix next pr-fix previous pr-fix resolve --id ID --status STATUS [--answer "Explanation"] pr-fix end pr-fix send ``` - `start`: Start a fix session by pasting review comments into an editor. - `comments [--with-context]`: Display comments, optionally with context. - `files`: List files with comments, indicating current. - `open`: Open current file with comments inserted for editing and updating status/answers. - `next`: Move to next file and open. - `previous`: Move to previous file and open. - `resolve --id ID --status STATUS [--answer "EXPLANATION"]`: Update comment status (e.g., solved, not-solved, will-not-solve) and optional answer via CLI. - `end`: End the fix session, requires changes to be committed. - `send`: Send fix summary to Slack. ### pr-init Interactively generate or update configuration file (.pr-tools.yaml) for pr-tools, prompting for base-branch, optional slack-webhook, slack-token, slack-channel, and stale-days (with current values as defaults if updating). Also updates .gitignore with recommended entries. ``` pr-init ``` No additional flags. ## Sample Workflow 1. **Create a Feature Branch**: Developer creates a branch, makes changes, and commits. 2. **Generate Snapshot**: Run `pr-snapshot` to create a Markdown description of the PR. 3. **Send to Slack**: Run `pr-send` to notify the team via Slack. 4. **Track Approvals**: Team members approve using `pr-track approve ` or Slack reactions. 5. **Conduct Review**: Reviewer runs `pr-review start`, navigates files with `next`/`open`, adds comments, then `pr-review send` to send compact review to Slack. 6. **Fix Comments**: Developer runs `pr-fix start`, pastes the Slack review message, navigates with `pr-fix next`/`open` to edit files and mark comments (solved/not-solved/will-not-solve), adds answers, or use `pr-fix resolve` for CLI updates, then `pr-fix end` to commit changes, and `pr-fix send` to report back via Slack. 7. **View Annotated Diff**: Anyone can run `pr-view ` to see changes with comments (use --full for full files or `pr-view comments` for comment list). 8. **Merge PR**: Once approved, run `pr-merge ` to merge and update changelog. This workflow enables collaborative reviews without committing review files to the repo, using Slack for communication. ## Contributing Contributions are welcome! Please open an issue or submit a pull request. ## License This project is licensed under the BSD-3-Clause License.