Skip to content

Instantly share code, notes, and snippets.

@AriRexouium
Last active January 28, 2024 18:30
Show Gist options
  • Save AriRexouium/9cf8cc6e3ea66d4c67de38c6500391e4 to your computer and use it in GitHub Desktop.
Save AriRexouium/9cf8cc6e3ea66d4c67de38c6500391e4 to your computer and use it in GitHub Desktop.
Archive GitHub Repositories Shellscript
#!/usr/bin/env bash
# -*- coding: utf-8 -*-
set -euo pipefail
# Version 2024/01/28 - Changelog: https://gist.github.com/AriRexouium/9cf8cc6e3ea66d4c67de38c6500391e4
# This script uses the GitHub API to retrieve the logged in user's repos and gists, downloads them, then archives them.
# Create a classic PAT with the 'repo', 'gist' & 'admin:public_key' scopes and update TOKEN for this script to work.
# https://github.com/settings/tokens
# repo: To clone private repositories.
# gist: To clone private gists.
# admin:public_key: To create and delete the ssh key used for cloning.
#
# Usage: ./archivegithub.sh
#
# License:
# This script is licensed under the GNU General Public License v3.0 or later.
# For more information, see https://www.gnu.org/licenses/gpl-3.0.html
# Copyright (C) 2023 Jarrett Aiken <jarret.aiken@achl.fr> (https://achl.fr)
TOKEN=""
# Colors
ES="\x1B"
GREEN="$ES[0;32m"
YELLOW="$ES[0;33m"
BLUE="$ES[0;34m"
NC="$ES[0m"
echo -e "${YELLOW}Connecting to GitHub...${NC}"
QUERY="{viewer{login repositories(first:100,ownerAffiliations:OWNER){nodes{name}}gists(first:100,privacy:ALL){nodes{name}}}}"
REQUEST=$(curl \
-s \
-X POST \
-H "Authorization: Bearer ${TOKEN}" \
-d "{\"query\":\"${QUERY}\"}" \
"https://api.github.com/graphql"
)
LOGIN="$(echo "${REQUEST}" | jq -r ".data.viewer.login")"
REPOS=$(echo "${REQUEST}" | jq -r ".data.viewer.repositories.nodes[].name")
GISTS=$(echo "${REQUEST}" | jq -r ".data.viewer.gists.nodes[].name")
echo -e "${GREEN}Logged in as ${LOGIN} with $(echo "${REPOS}" | wc -l) repos and $(echo "${GISTS}" | wc -l) gists.${NC}\n"
mkdir -p "${PWD}/${LOGIN}/"{repos,gists}
_PWD="${PWD}/${LOGIN}"
echo -e "${BLUE}Generating SSH key...${NC}"
SSHK="${_PWD}/id_ed25519"
ssh-keygen \
-q \
-t ed25519 \
-f "${SSHK}" \
-N ""
chmod 600 "${SSHK}"
echo -e "${YELLOW}Adding SSH key to account...${NC}\n"
KEYID=$(curl \
-s \
-X POST \
-H "Authorization: Bearer ${TOKEN}" \
-d "{\"key\":\"$(cat "${SSHK}.pub")\"}" \
"https://api.github.com/user/keys" \
| jq -r ".id"
)
cd "${_PWD}/repos"
echo -e "${GREEN}Cloning repos...${NC}\n"
for REPO in ${REPOS}; do
echo -e "${BLUE}Cloning ${REPO}...${NC}"
git clone \
-q \
-c core.sshCommand="ssh -i ${SSHK}" \
"git@github.com:${LOGIN}/${REPO}.git" \
&& sleep 1 # so 'tar' doesn't occationally step on the toes of 'git clone'.
echo -e "${BLUE}Archiving ${REPO}...${NC}"
tar -cJf "${REPO}.tar.xz" "${REPO}"
echo -e "${YELLOW}Cleaning up ${REPO}...${NC}"
rm -rf "${REPO}"
echo
done
cd "${_PWD}/gists"
echo -e "${GREEN}Cloning gists...${NC}\n"
for GIST in ${GISTS}; do
echo -e "${BLUE}Cloning ${GIST}...${NC}"
git clone \
-q \
-c core.sshCommand="ssh -i ${SSHK}" \
"git@gist.github.com:${GIST}.git" \
&& sleep 1 # so 'tar' doesn't occationally step on the toes of 'git clone'.
echo -e "${BLUE}Archiving ${GIST}...${NC}"
tar -cJf "${GIST}.tar.xz" "${GIST}"
echo -e "${YELLOW}Cleaning up ${GIST}...${NC}"
rm -rf "${GIST}"
echo
done
echo -e "${YELLOW}Removing SSH key from account...${NC}"
curl \
-s \
-X DELETE \
-H "Authorization: Bearer ${TOKEN}" \
"https://api.github.com/user/keys/${KEYID}"
echo -e "${YELLOW}Removing SSH key...${NC}\n"
rm -rf "${SSHK}"*
echo -e "${GREEN}Finished!${NC}\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment