This is the 12th day of my participation in the Gwen Challenge.More article challenges

Anything can get lost, unless you make a backup before you lose it! This article will show you how to use GitHub Actions to implement automatic backup repository.

The target

The goal of this article is to synchronize all repositories under GitHub user user-a to GitHub user user-b.

To prepare

Create a new code store with the following directory structure:

.├ ─.exercises ── workflows │ ├─Copy the code

And set three Secret in the code store, which are:

  • GH_TOKEN_ACorresponds to a GitHub useruser-aThe AccessToken
  • GH_TOKEN_BCorresponds to a GitHub useruser-bThe AccessToken
  • SLACK_WEBHOOKCorresponding Slack WebHook address (optional)

workflow

Gets the code warehouse list

Use GitHub CLI gh to obtain all code storehouses under GitHub user-a

echo ${GH_TOKEN_A} > gh_token_a Write user-a's GitHub AccessToken to the file
gh auth login --with-token < gh_token_a # GitHub CLI login
gh repo list user-a -L 1000 > a_repos # fetch all the repository of user-a and write to the file
cat a_repos # display code store list
cat a_repos | wc -l # display the total number of code stores
Copy the code

Create a repository with the same name

Create a repository of the same name under GitHub user user-b.

gh repo create user-b/${repo_name} --private --description "${repo}" -y || true # Ignore error, code bin may already exist
Copy the code

Clone code store

Clone the GitHub repository under user-a with –bare.

git clone --bare https://${GH_TOKEN_A}@github.com/user-a/${repo_name}.git ${repo_name}
Copy the code

Push the code

The –all and –mirror parameters are used for code push respectively to prevent push failure due to too much data.

  • --allPush all branches
  • --mirrorAccording to pushrefs/All references under, including branches, tags, and so on
cd ${repo_name}
mirror_repo="https://${GH_TOKEN_B}@github.com/user-b/${repo_name}.git"
git push --all -f ${mirror_repo} || true
git push --mirror -f ${mirror_repo} || true
Copy the code

To optimize the

  • Ignore code silos that are too large or don’t require backup
In order to ensure the accuracy of the code warehouse name judgment, add oblique bars on the left and right sides of each code warehouse name when defining and judging
IGNORE_REPOS="/repo_a/repo_b/"

[[ ${IGNORE_REPOS}= ~"/${repo_name}/"&&]]continue || true
Copy the code
  • fortagToo many code silos, backing up only branches
ONLY_BRANCH_REPOS="/repo_c/repo_d/"

[[ ${ONLY_BRANCH_REPOS}= ~"/${repo_name}/"&&]]continue || true
Copy the code
  • Since the GitHub Actions time zone isUTC, timed task time required-8h

Monday to Friday at 2 a.m. :

  • General configuration:0, 2 times 1, minus 5
  • GitHub Actions Scheduled tasks:0, 18 times * 0, minus 4

Complete workflow configuration

. Making/workflows/mirror. Yaml files:

name: Mirror repos

on:
  schedule:
    - cron: "0 18 * * 0-4" Set up a scheduled task, Monday through Friday at 2am backup
  workflow_dispatch: # Manually trigger the build

jobs:
  mirror:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: GitHub CLI version
        run: gh --version

      - name: List repos
        env:
          GH_TOKEN_A: The ${{ secrets.GH_TOKEN_A }}
        run: | echo ${GH_TOKEN_A} > gh_token_a gh auth login --with-token < gh_token_a gh repo list user-a -L 1000 > a_repos cat a_repos cat a_repos | wc -l
      - name: Mirror repos
        env:
          GH_TOKEN_A: The ${{ secrets.GH_TOKEN_A }}
          GH_TOKEN_B: The ${{ secrets.GH_TOKEN_B }}
          IGNORE_REPOS: "/repo_a/repo_b/"
          ONLY_BRANCH_REPOS: "/repo_c/repo_d/"
        run: | echo ${GH_TOKEN_B} > gh_token_b gh auth login --with-token < gh_token_b
          mkdir repos
          cd repos
          set -x
          cat ${GITHUB_WORKSPACE}/a_repos | while read repo; do
            repo_name=$(echo ${repo} | awk '{print $1}' | awk -F/ '{print $2}')
            [[ ${IGNORE_REPOS} = ~ "/${repo_name}/" ]] && continue || true

            gh repo create user-b/${repo_name} --private --description "${repo}" -y || true
            rm -rf ${repo_name}

            git clone --bare https://${GH_TOKEN_A}@github.com/user-a/${repo_name}.git ${repo_name}

            cd ${repo_name}
            mirror_repo="https://${GH_TOKEN_B}@github.com/user-b/${repo_name}.git"
            git push --all -f ${mirror_repo} || true
            [[ ${ONLY_BRANCH_REPOS} = ~ "/${repo_name}/" ]] && continue || true
            git push --mirror -f ${mirror_repo} || true
            cd -
          done

      - name: Slack Notification
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_WEBHOOK: The ${{ secrets.SLACK_WEBHOOK }}
Copy the code