mirror of
https://github.com/morten-olsen/github-backup.git
synced 2026-02-08 01:36:24 +01:00
Added EXCLUDE and INCLUDE options
This commit is contained in:
@@ -3,3 +3,5 @@
|
|||||||
/backup
|
/backup
|
||||||
/*.log
|
/*.log
|
||||||
/.env
|
/.env
|
||||||
|
/.pnp.*
|
||||||
|
/.yarn
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@
|
|||||||
/*.log
|
/*.log
|
||||||
/.env
|
/.env
|
||||||
/backup
|
/backup
|
||||||
|
/.pnp.*
|
||||||
|
/.yarn
|
||||||
|
|||||||
1
.yarnrc.yml
Normal file
1
.yarnrc.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
nodeLinker: node-modules
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
FROM node:alpine as BuildEnv
|
FROM node:16-alpine as BuildEnv
|
||||||
COPY package.json /app/package.json
|
COPY package.json yarn.lock .yarnrc.yml /app/
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN yarn install
|
RUN \
|
||||||
|
corepack enable && \
|
||||||
|
yarn install
|
||||||
COPY . /app/
|
COPY . /app/
|
||||||
RUN yarn bundle
|
RUN yarn bundle
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ docker run -it --rm \
|
|||||||
```
|
```
|
||||||
_note: `--user` is not required, but recommended instead of running as root. Remember to give the user write access to the backup directory_
|
_note: `--user` is not required, but recommended instead of running as root. Remember to give the user write access to the backup directory_
|
||||||
|
|
||||||
|
You can also limit which repositories to backup using the environment variabled `INCLUDE` and `EXCLUDE`, which supports a list or repos separated by `,` and with `*` as wildcard
|
||||||
|
|
||||||
|
```
|
||||||
|
-e INCLUDE="morten-olsen/*,morten-olsen-env/dotfiles" -e EXCLUDE="morten-olsen/something,*/test"
|
||||||
|
```
|
||||||
|
|
||||||
## Backup structure
|
## Backup structure
|
||||||
```
|
```
|
||||||
|-{user1}
|
|-{user1}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "github-backup",
|
"name": "github-backup",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"packageManager": "yarn@3.1.0",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
30
src/index.ts
30
src/index.ts
@@ -3,16 +3,12 @@ import { Octokit } from '@octokit/rest';
|
|||||||
import simpleGit from 'simple-git';
|
import simpleGit from 'simple-git';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
|
||||||
import rimrafSync from 'rimraf';
|
|
||||||
import { nanoid } from 'nanoid';
|
|
||||||
import util from 'util';
|
|
||||||
import ora from 'ora';
|
import ora from 'ora';
|
||||||
|
|
||||||
const rimraf = util.promisify(rimrafSync);
|
|
||||||
|
|
||||||
const token = process.env.GITHUB_TOKEN;
|
const token = process.env.GITHUB_TOKEN;
|
||||||
const backupLocation = process.env.GITHUB_BACKUP_LOCATION || '/backup';
|
const backupLocation = process.env.GITHUB_BACKUP_LOCATION || '/backup';
|
||||||
|
const included = (process.env.INCLUDE || '*/*').split(',');
|
||||||
|
const excluded = (process.env.EXCLUDE || '').split(',');
|
||||||
|
|
||||||
const mirror = async (target: string, repo: string) => {
|
const mirror = async (target: string, repo: string) => {
|
||||||
const authRemote = `https://foo:${token}@github.com/${repo}`
|
const authRemote = `https://foo:${token}@github.com/${repo}`
|
||||||
@@ -36,6 +32,22 @@ const mirror = async (target: string, repo: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const shouldRun = (repoUser: string, repoName: string) => {
|
||||||
|
const isIncluded = included.reduce((result, current) => {
|
||||||
|
if (result) return result;
|
||||||
|
const [user = '*', repo = '*'] = current.split('/');
|
||||||
|
return (user === '*' || user === repoUser) && (repo === '*' || repo === repoName);
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
const isExcluded = excluded.reduce((result, current) => {
|
||||||
|
if (result) return result;
|
||||||
|
const [user = '', repo = ''] = current.split('/');
|
||||||
|
return (user === '*' || user === repoUser) && (repo === '*' || repo === repoName);
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
return isIncluded && !isExcluded;
|
||||||
|
}
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
const github = new Octokit({
|
const github = new Octokit({
|
||||||
auth: process.env.GITHUB_TOKEN,
|
auth: process.env.GITHUB_TOKEN,
|
||||||
@@ -45,6 +57,10 @@ const run = async () => {
|
|||||||
const errors: any[] = [];
|
const errors: any[] = [];
|
||||||
for await (const repos of github.paginate.iterator(action, { visibility: 'all' })) {
|
for await (const repos of github.paginate.iterator(action, { visibility: 'all' })) {
|
||||||
for (const repo of repos.data) {
|
for (const repo of repos.data) {
|
||||||
|
if (!shouldRun(repo.owner.login, repo.name)) {
|
||||||
|
console.log(`skipping ${repo.full_name}`)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const loader = ora('preparing');
|
const loader = ora('preparing');
|
||||||
loader.prefixText = repo.full_name;
|
loader.prefixText = repo.full_name;
|
||||||
loader.start();
|
loader.start();
|
||||||
@@ -59,7 +75,7 @@ const run = async () => {
|
|||||||
await mirror(gitLocation, repo.full_name);
|
await mirror(gitLocation, repo.full_name);
|
||||||
loader.text = '';
|
loader.text = '';
|
||||||
loader.succeed();
|
loader.succeed();
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
loader.fail(err.toString());
|
loader.fail(err.toString());
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user