~tcarrio/git-mirror

12651b62f86c3af38052a6d9961cebb81c6c8e0a — Tom Carrio 3 years ago
Initial commit of example SourceHut -> GitHub git mirroring
3 files changed, 97 insertions(+), 0 deletions(-)

A .builds.yml
A README.md
A git-mirror.sh
A  => .builds.yml +27 -0
@@ 1,27 @@
image: archlinux
packages:
  - git
sources:
  - https://git.sr.ht/~tcarrio/git-mirror
  - https://git.sr.ht/~tcarrio/build-helpers
environment:
  PROJECT_DIR: git-mirror
  HELPERS_DIR: build-helpers
secrets:
  - 1228fb70-1962-40d9-b1c8-941e56c6a8a1
tasks:
  - mirror-any: |
      git-mirror/git-mirror.sh $PROJECT_DIR

  - mirror-master-only: |
      source $HELPERS_DIR/all.sh
      pushd $PROJECT_DIR

      if ! compare_branch master
      then
        echo "Skipping mirror task for non-master branch"
        exit 0
      fi
      popd

      git-mirror/git-mirror.sh $PROJECT_DIR
\ No newline at end of file

A  => README.md +23 -0
@@ 1,23 @@
# GitHub Mirror

This is an example repository of how you can integrate git mirroring into the SourceHut build pipelines. Git is essentially built with this functionality, you simply need write access to the target repository. Here we will use an SSH token to push the latest master branch to a GitHub repository.

This solution is meant to tie in easily with the build tools provided by SourceHut, but another means of doing this could be an OAuth app you have given write access to your repositories. The build tooling itself may be useful for propogating the initial event to a third-party server with the access to push code to your repository. That flow is not covered here, but if I care to do an example app for that functionality in the future, I'll make a point to update this repo with a reference to it.

**Note:** this will work for any Git project, it isn't specific to GitHub, I'm just doing a demo of it using GitHub as the target.

## Getting Started

1. Generate an SSH token and add it to your GitHub account
2. Generate a file secret on https://builds.sr.ht/secrets to load at `~/git_ssh_token`
3. Update your `.builds.yml` pipeline with the following:
  - Include the secret reference under the `secrets`
  - Include this repository under the `sources`
  - Include the `build` stage of the example pipeline in your pipeline
  - Include the target repository as the environment variable `GIT_TARGET_URL`

## What's happening

Repositories listed under `sources` are cloned to the current working directory, so you will have directories per repo that you can reference using `./repo-name`. This repository includes a simple shell script that will use your SSH token at `~/git_ssh_token` to push your current branch to the target git repository's branch. Simple stuff.

**Warning:** This forces the push, taking into consideration that the target should be a downstream mirror, it will overwrite the state there should it have a diverged git history from your SourceHut repo.
\ No newline at end of file

A  => git-mirror.sh +47 -0
@@ 1,47 @@
#!/usr/bin/env sh

SSH_TOKEN_PATH=${SSH_TOKEN_PATH:-~/.ssh/git_ssh_token}
GIT_LOCAL_REPO=${1:-${PWD}}
GIT_TARGET_REPO=${GIT_TARGET_REPO}
GIT_TARGET_REMOTE=downstream
GIT_SSH_COMMAND="ssh -i \"${SSH_TOKEN_PATH}\""

if [ ! -d "${GIT_LOCAL_REPO}" ]
then
  echo "No local repo found! Exiting"
  exit 1
fi

if [ -z "${GIT_TARGET_REPO}" ]
then
  echo "No target repo configured! Exiting"
  exit 1
fi

if [ ! -f "${SSH_TOKEN_PATH}" ]
then
  echo "No SSH token configured! Exiting"
  exit 1
fi

if ! which git
then
  echo "Git command was not found! Exiting"
  exit 1
fi

pushd "${GIT_LOCAL_REPO}"

set -x
git remote add ${GIT_TARGET_REMOTE} ${GIT_TARGET_REPO}
git branch | grep -E '^\* ' | sed 's/* //' | xargs git push --force --mirror ${GIT_TARGET_REMOTE}

set +x
if [ $? -eq 0 ]
then
  echo "Successfully pushed to mirror"
else
  echo "Failed to push to mirror"
fi

popd
\ No newline at end of file