Notice

Beta quality stuff, which hasn't seen production use, and is pretty hackily thrown together.

Introduction

Pull Reqer is grab bag of tools, both client and server side for setting implementing a pull request like feature usable on the command line and conversion of repo manifests to locally hosted repositories.

Important this project works with the alibaba git-repo client not the google repo-tool.

After setting everything up you'll have a locally hosted repository to which you can make pull requests to. usable either the normal git checkouts, or a git-repo multi-repository manifest.

Most of this is driven by the alibaba git-repo client utility

Pull Reqer provides the needed hooks, and some utilities for converting git-repo checkouts into locally usable variants.

Client components

For mirroring remote git-repo repositories,

Externally provided utilities:

Server components

A git hook implementing the pull request protocol.

Externally provided requirements:

  • git (at least version 2.29)
  • an ssh daemon.

There is not currently any web interface available.

Container

Scripts for building a container with everything needed on the server.

External dependencies:

Installation

Installation steps,

  1. Build the container
  2. Run the container
  3. Build the client utilities
  4. Client ssh setup

Step 1

Building the container.

pullreqr_container/mk_pullreqr_container

Step 2

Running the container.

build/host_scripts/git_start.sh

To stop it:

build/host_scripts/git_stop.sh

Optionally enable it to start via systemd

install -D -t ~/.config/systemd/user/ build/host_scripts/pullreqr.service
systemctl --user enable pullreqr.service --now

Step 3

Client installation

installation:

Step 4

Client setup:

  • Add keys to ~/.ssh/config
cat <<"EOF" | envsubst '${PWD}' >>~/.ssh/config
Host localhost 
    HostName localhost 
    User git
    Port 2222
    IdentityFile ${PWD}/persistent/keys/user_key
EOF

Initial Testing

Check that you can ssh into the container, and create a repository. Next We'll use this test repostory in single repostory

ssh localhost create_pr_repo test

Single repository usage

Now that the server and client are built and running, create a test repository, and commit to it, and make a pull request.

  • Client setup for a single repository

Previously we created an empty repository on the server which we can push to, before we can make a pull request, we need to add an initial commit.

git init
cd test
echo "foo" >README.md
git add README.md
git commit -m "An initial commit"
git remote add origin ssh://localhost/~/test.git
git push --set-upstream origin main

Now create a pull request:

echo "test 1" >>README.md
git add README.md
git commit -m "a test pull-request"
git pr

This should launch your editor, after filling in the form and exiting you should see:

$ git pr
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 252 bytes | 252.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To ssh://localhost:2222/~/test.git
 * [new branch]      master -> for/master/pr1

----------------------------------------------------------------------

Check out the pull-request to a local branch:

git fetch origin for/master/pr1:pr1
git checkout pr1

Multi repository

After successfully testing everything works with a single repository we'll mirror a repo manifest, and set up a mirror so that our pull-requests will go our local system.

It is best to do this on a repository with no review url to ensure that you aren't accidentally sending bogus pull-requests upstream.


mirroring a multi-repository repo checkout

Has a few steps,

  1. Setting up a local mirror
    • Download the repositories git repo using the --mirror flag.
    • Create repositories for these on our local server
    • Push the downloaded repositories to our local server
  2. Using the local mirror with git repo
    • Repo init the repository again without the --mirror flag.
    • Make a modified manifest, putting that in the local_manifests directory.
    • Use git repo sync to make a clone which fetches and pulls from out local repository.
  3. Using git repo upload, to make changes manifest-tool is a tool which helps with the above steps 2 and 4.

Configuring manifest-tool for step 1.

Add the following to your ~/.config/manifest-tool/projects/default.env

ssh localhost create_pr_repo ${remote_name}/${project_name} </dev/null
GIT_DIR="$(basename -s .git ${project_name}).git" git remote add mine ssh://localhost/~/${remote_name}/${project_name}
GIT_DIR="$(basename -s .git ${project_name}).git" git push --all mine

Rather than performing a checkout into a work tree, --mirror will just download the repositories. We use manifest-tool to:

  • Create a repo for the local mirror
  • Add a remote the cloned repository git repo
  • Push the repository to our mirror.

We want to run this for every project in the manifest.

Step 1

Setting up a local mirror:

mkdir mirror
cd mirror
git repo init -u https://example.com/foo/example.git --mirror
git repo sync
manifest-tool --projects | sh

Configuring manifest-tool for step 2.

Add the following to ~/.config/manifest-tool/convert/default.env

push_url=ssh://localhost/~git/${remote_name}/
review_url=ssh://localhost/~/
fetch_url=ssh://localhost/~git/${remote_name}/
review_proto=agit

Unlike --projects which just emitted a shell script, the --convert flag, reads the manifest performs substitutions, and then writes a new manifest to the local_manifests directory.

We run manifest tool in between git repo init, and git repo sync. In the process git repo sync should now be checking out from and pushing to localhost.

Step 2

Using the local mirror with git repo:

mkdir work
cd work
git repo init -u https://example.com/foo/example.git
manifest-tool --convert
git repo sync

Step 3

Using git repo upload, to make changes:

cd test/
git repo start pull-test
echo "test" > test.txt
git add test.txt
git commit -m "test commit for multi-repo"
git repo upload

Containers build process

Here is a general overview of the container building process. There are 3 containers

TODO This could use a lot more explanation.

  1. build_env
  2. build
  3. run

build_env

  • Install development tools for git
  • Install development tools for rust

build

  • Compile git & pullreqr_hook

run

  • Generate user keys & account to push to, using git-shell.
  • Copy public key into a mounted volume.
  • installs git and the hook, and ssh daemon.
  • Configures the ssh daemon