Skip to content

Commit

Permalink
feat: add support for source/destination ssh keys (#22)
Browse files Browse the repository at this point in the history
* add support for source/destination ssh keys

* update readme

* revert to SSH_PRIVATE_KEY by default

* release: bump to v3

Co-authored-by: Wei He <[email protected]>
  • Loading branch information
homerjam and wei authored Jan 18, 2021
1 parent c81b9ea commit 55c6b63
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 38 deletions.
79 changes: 58 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,93 @@
# Git Sync

A GitHub Action for syncing between two independent repositories using **force push**.

A GitHub Action for syncing between two independent repositories using **force push**.

## Features
* Sync branches between two GitHub repositories
* Sync branches to/from a remote repository
* GitHub action can be triggered on a timer or on push
* To sync with current repository, please checkout [Github Repo Sync](https://github.com/marketplace/actions/github-repo-sync)

- Sync branches between two GitHub repositories
- Sync branches to/from a remote repository
- GitHub action can be triggered on a timer or on push
- To sync with current repository, please checkout [Github Repo Sync](https://github.com/marketplace/actions/github-repo-sync)

## Usage

Always make a full backup of your repo (`git clone --mirror`) before using this action.
> Always make a full backup of your repo (`git clone --mirror`) before using this action.
### GitHub Actions
- Either generate different ssh keys for both source and destination repositories or use the same one for both, leave passphrase empty (note that GitHub deploy keys must be unique)

```sh
$ ssh-keygen -t rsa -b 4096 -C "[email protected]"
```
# File: .github/workflows/repo-sync.yml

- In GitHub, either:

- add the unique public keys (`key_name.pub`) to _Repo Settings > Deploy keys_ for each repository respectively and allow write access for the destination repository

or

- add the single public key (`key_name.pub`) to _Personal Settings > SSH keys_

- Add the private key(s) to _Repo > Settings > Secrets_ for the repository containing the action (`SSH_PRIVATE_KEY` or `SOURCE_SSH_PRIVATE_KEY` and `DESTINATION_SSH_PRIVATE_KEY`)

### GitHub Actions

```yml
# .github/workflows/repo-sync.yml

on: push
jobs:
repo-sync:
runs-on: ubuntu-latest
steps:
- name: repo-sync
uses: wei/git-sync@v2
with:
source_repo: ""
source_branch: ""
destination_repo: ""
destination_branch: ""
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: repo-sync
uses: wei/git-sync@v3
with:
source_repo: "username/repository"
source_branch: "main"
destination_repo: "[email protected]:org/repository.git"
destination_branch: "main"
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} # optional
source_ssh_private_key: ${{ secrets.SOURCE_SSH_PRIVATE_KEY }} # optional, will override `SSH_PRIVATE_KEY`
destination_ssh_private_key: ${{ secrets.DESTINATION_SSH_PRIVATE_KEY }} # optional, will override `SSH_PRIVATE_KEY`
```
##### Alternative using https
The `ssh_private_key`, `source_ssh_private_key` and `destination_ssh_private_key` can be omitted if using authenticated https urls.

```yml
source_repo: "https://username:[email protected]/username/repository.git"
```
`ssh_private_key` can be omitted if using authenticated HTTPS repo clone urls like `https://username:[email protected]/username/repository.git`.

#### Advanced: Sync all branches

To Sync all branches from source to destination, use `source_branch: "refs/remotes/source/*"` and `destination_branch: "refs/heads/*"`. But be careful, branches with the same name including `master` will be overwritten.

```yml
source_branch: "refs/remotes/source/*"
destination_branch: "refs/heads/*"
```

#### Advanced: Sync all tags

To Sync all tags from source to destination, use `source_branch: "refs/tags/*"` and `destination_branch: "refs/tags/*"`. But be careful, tags with the same name will be overwritten.

### Docker
```yml
source_branch: "refs/tags/*"
destination_branch: "refs/tags/*"
```
docker run --rm -e "SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)" $(docker build -q .) \

### Docker

```sh
$ docker run --rm -e "SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)" $(docker build -q .) \
$SOURCE_REPO $SOURCE_BRANCH $DESTINATION_REPO $DESTINATION_BRANCH
```

## Author
[Wei He](https://github.com/wei) _[email protected]_

[Wei He](https://github.com/wei) [email protected]_

## License

[MIT](https://wei.mit-license.org)
16 changes: 12 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
name: Git Sync Action
author: Wei He <[email protected]>
description: 🔃 Sync between two independent repositories
description: 🔃 Sync between two independent repositories
branding:
icon: 'git-branch'
color: 'gray-dark'
inputs:
source_repo:
description: GitHub repo slug or full clone url
description: GitHub repo slug or full url
required: true
source_branch:
description: Branch name to sync from
required: true
destination_repo:
description: GitHub repo slug or full clone url
description: GitHub repo slug or full url
required: true
destination_branch:
description: Branch name to sync to
required: true
ssh_private_key:
description: SSH key used to authenticate with git clone urls provided (optional if public or https clone url with authentication)
description: SSH key used to authenticate with source and destination ssh urls provided (optional if public or https url with authentication)
required: false
source_ssh_private_key:
description: SSH key used to authenticate with source ssh url provided (optional if public or https url with authentication)
required: false
destination_ssh_private_key:
description: SSH key used to authenticate with destination ssh url provided (optional if public or https url with authentication)
required: false
runs:
using: 'docker'
image: 'Dockerfile'
env:
SSH_PRIVATE_KEY: ${{ inputs.ssh_private_key }}
SOURCE_SSH_PRIVATE_KEY: ${{ inputs.source_ssh_private_key }}
DESTINATION_SSH_PRIVATE_KEY: ${{ inputs.destination_ssh_private_key }}
args:
- ${{ inputs.source_repo }}
- ${{ inputs.source_branch }}
Expand Down
19 changes: 15 additions & 4 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@

set -e

if [[ -n "$SSH_PRIVATE_KEY" ]]
then
if [[ -n "$SSH_PRIVATE_KEY" ]]; then
mkdir -p /root/.ssh
echo "$SSH_PRIVATE_KEY" > /root/.ssh/id_rsa
echo "$SSH_PRIVATE_KEY" | sed 's/\\n/\n/g' >/root/.ssh/id_rsa
chmod 600 /root/.ssh/id_rsa
fi

if [[ -n "$SOURCE_SSH_PRIVATE_KEY" ]]; then
mkdir -p /root/.ssh
echo "$SOURCE_SSH_PRIVATE_KEY" | sed 's/\\n/\n/g' >/root/.ssh/src_rsa
chmod 600 /root/.ssh/src_rsa
fi

if [[ -n "$DESTINATION_SSH_PRIVATE_KEY" ]]; then
mkdir -p /root/.ssh
echo "$DESTINATION_SSH_PRIVATE_KEY" | sed 's/\\n/\n/g' >/root/.ssh/dst_rsa
chmod 600 /root/.ssh/dst_rsa
fi

mkdir -p ~/.ssh
cp /root/.ssh/* ~/.ssh/ 2> /dev/null || true
cp /root/.ssh/* ~/.ssh/ 2>/dev/null || true

sh -c "/git-sync.sh $*"
26 changes: 17 additions & 9 deletions git-sync.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,17 @@ SOURCE_BRANCH=$2
DESTINATION_REPO=$3
DESTINATION_BRANCH=$4

if ! echo $SOURCE_REPO | grep -Eq ':|@|\.git\/?$'
then
if [[ -n "$SSH_PRIVATE_KEY" ]]
then
if ! echo $SOURCE_REPO | grep -Eq ':|@|\.git\/?$'; then
if [[ -n "$SSH_PRIVATE_KEY" || -n "$SOURCE_SSH_PRIVATE_KEY" ]]; then
SOURCE_REPO="[email protected]:${SOURCE_REPO}.git"
GIT_SSH_COMMAND="ssh -v"
else
SOURCE_REPO="https://github.com/${SOURCE_REPO}.git"
fi
fi
if ! echo $DESTINATION_REPO | grep -Eq ':|@|\.git\/?$'
then
if [[ -n "$SSH_PRIVATE_KEY" ]]
then

if ! echo $DESTINATION_REPO | grep -Eq ':|@|\.git\/?$'; then
if [[ -n "$SSH_PRIVATE_KEY" || -n "$DESTINATION_SSH_PRIVATE_KEY" ]]; then
DESTINATION_REPO="[email protected]:${DESTINATION_REPO}.git"
GIT_SSH_COMMAND="ssh -v"
else
Expand All @@ -31,7 +28,13 @@ fi
echo "SOURCE=$SOURCE_REPO:$SOURCE_BRANCH"
echo "DESTINATION=$DESTINATION_REPO:$DESTINATION_BRANCH"

git clone "$SOURCE_REPO" /root/source --origin source && cd /root/source
if [[ -n "$SOURCE_SSH_PRIVATE_KEY" ]]; then
# Clone using source ssh key if provided
git clone -c core.sshCommand="/usr/bin/ssh -i ~/.ssh/src_rsa" "$SOURCE_REPO" /root/source --origin source && cd /root/source
else
git clone "$SOURCE_REPO" /root/source --origin source && cd /root/source
fi

git remote add destination "$DESTINATION_REPO"

# Pull all branches references down locally so subsequent commands can see them
Expand All @@ -40,4 +43,9 @@ git fetch source '+refs/heads/*:refs/heads/*' --update-head-ok
# Print out all branches
git --no-pager branch -a -vv

if [[ -n "$DESTINATION_SSH_PRIVATE_KEY" ]]; then
# Push using destination ssh key if provided
git config --local core.sshCommand "/usr/bin/ssh -i ~/.ssh/dst_rsa"
fi

git push destination "${SOURCE_BRANCH}:${DESTINATION_BRANCH}" -f

0 comments on commit 55c6b63

Please sign in to comment.