#!/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 (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"