Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: Enhance log to include Github PR Numbers and state #5442

Open
hessjcg opened this issue Jan 23, 2025 · 2 comments
Open

FR: Enhance log to include Github PR Numbers and state #5442

hessjcg opened this issue Jan 23, 2025 · 2 comments

Comments

@hessjcg
Copy link

hessjcg commented Jan 23, 2025

Is your feature request related to a problem? Please describe.

I want to see in the commit log which commits have a bookmark associated to a Github PR, and is that PR up to date.

Right now, I have to do jj log to read the branch name, then go to the Github PR page in my browser
and list the PRs, then carefully read the list and match the names to PR numbers in my head.

This could be automated. I use JJ to manage my local commit history, and then create stacks of PRs in github. I often need to ping team members about reviewing these PRs. Using jj log I can easily see the stack of PRs in the correct order.

Describe the solution you'd like
jj log should print the Github PR number (or any other forge) in the log summary line.

GIVEN

  • A local JJ repo with Github as the remote origin
  • The JJ repo has bookmarks associated Git branches in the origin repo
  • The Github repo has PRs associated with those branches

WHEN the user runs jj log
THEN jj will match the git commit and bookmarks for a commit to the appropriate remote refs from the Github origin repo.

I created a prototype python script to demonstrate the logic (see attached). Here is the output:

$~/p/c/jj-java-connector jj log-pr                                                                                                                                                                            10:42:55
○  sxptnunm [email protected] 2025-01-23 09:40:24 gh-2043-update-on-dns-change* 10dde303 #2056 (out of date)
│  feat: Automatically reset DNS-configured connections on DNS change
@  kqzvmskn [email protected] 2025-01-23 09:40:24 gh-2043-configure-with-dns* 3cd89b15 #2047
│  feat: Automatically configure connections using DNS. Part of #2043.
○  yxzqswyk [email protected] 2025-01-17 11:58:36 gh-2043-use-r2dbc-host c389387c #2103
│  chore: Use domain name from R2DBC connections when configuring the connector.

Describe alternatives you've considered

The full Github Integration sounds like it could work (See #4555). But this is a much larger scope. Also, I just want to see the Github PRs in the jj log output without requiring that I use Github and JJ in an opinionated way.

I created a jj utility in Python to do this, but it is brittle because it depends on the output format of jj log.

Additional context

I wrote a prototype python script to demonstrate the logic. This can be done entirely with git ls remote. There is
no need to call the Github API.

#!/usr/bin/env python3
import subprocess
import os
import re


def remove_color_codes(text):
  """Removes terminal color escape codes from a string.

  Args:
    text: The string containing color escape codes.

  Returns:
    The string with color escape codes removed.
  """
  # Regular expression to match ANSI escape codes
  ansi_escape = re.compile(r'\x1b\[[0-9;]*[mG]')
  return ansi_escape.sub('', text)


def git_ls_remote_prs():
  """
  Lists remote refs for PRs
  :return: dict[ commit_id | branch_name ] = pr_number
  """
  my_env = os.environ.copy()
  my_env['GIT_DIR'] = ".jj/repo/store/git"

  proc_git = subprocess.Popen(
      ['git', 'ls-remote', 'origin', 'pull/*', 'heads/*'],
      stdout=subprocess.PIPE,
      env=my_env)

  branches = {}
  git_prs = {}

  lines = proc_git.stdout.readlines()
  for line in lines:
    (commit_id, pr_ref) = line.decode().strip().split("\t")
    ref_parts = pr_ref.split('/')
    if ref_parts[1] == "pull":
      git_prs[commit_id[0:8]] = ref_parts[-2]
    if ref_parts[1] == "heads":
      branches[ref_parts[2]] = commit_id[0:8]
  proc_git.wait()

  for branch, cid in branches.items():
    if cid in git_prs:
      git_prs[branch] = git_prs[cid]

  return git_prs


def jj_log(git_prs):
  my_env = os.environ.copy()
  proc_jj_log = subprocess.Popen(
      ['jj', 'log', '--color=always'],
      stdout=subprocess.PIPE,
      env=my_env)
  clean_branch_name = re.compile(r'\*$')

  lines = proc_jj_log.stdout.readlines()
  for line in lines:
    line = line.decode().strip()
    txt_line = remove_color_codes(line)

    # Split the string by spaces
    line_parts = txt_line.split()

    # Get the last two elements of the split string
    if len(line_parts) >= 2:
      bookmark = line_parts[-2]
      bookmark = clean_branch_name.sub("",bookmark)
      commit_id = line_parts[-1]

      if commit_id in git_prs:
        print(line, "#%s" % git_prs[commit_id])
      elif bookmark in git_prs:
        print(line, "\033[91m#%s (out of date)\033[0m" % git_prs[bookmark])
      else:
        print(line)

  proc_jj_log.wait()


if __name__ == '__main__':
    prs = git_ls_remote_prs()
    jj_log(prs)
@senekor
Copy link
Contributor

senekor commented Jan 24, 2025

I created a jj utility in Python to do this, but it is brittle because it depends on the output format of jj log.

You can make your script less brittle and probably simpler by supplying an explicit template to jj log. (see the docs for the templating language) The flag jj log --no-graph may also be useful.

@PhilipMetzger
Copy link
Contributor

I think this is requesting something similar to Googles internal hg xl or Saplings ISL, for which we already have some issues (#4702 , #2765).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants