@ -0,0 +1,9 @@ |
|||
.idea/ |
|||
.git/ |
|||
node_modules/ |
|||
|
|||
.secrets.rc |
|||
.gitignore |
|||
|
|||
|
|||
run-local.sh |
@ -0,0 +1,3 @@ |
|||
.idea/ |
|||
node_modules/ |
|||
.secrets.rc |
@ -0,0 +1,7 @@ |
|||
FROM node:lts-alpine |
|||
|
|||
WORKDIR /app |
|||
COPY package.json package-lock.json ./ |
|||
RUN npm ci |
|||
COPY . . |
|||
CMD [ "/app/docker-entrypoint.sh" ] |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2019 Dennis Jekubczyk |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
@ -0,0 +1,46 @@ |
|||
# Mirror your github repositories to your gitea server |
|||
|
|||
This script mirrors automatically the public repositories from a github-user or github-organization to your gitea server. |
|||
It will - once started - create a mirrored repository under a given token for a gitea user fully automatically. |
|||
|
|||
Example: |
|||
A github user `github-user` has public repositories `dotfiles` and `zsh-config`. |
|||
Starting the script with a gitea token for the account `gitea-user` will create the following mirror repositories: |
|||
|
|||
- github.com/github-user/dotfiles ← some-gitea.url/gitea-user/dotfiles |
|||
- github.com/github-user/zsh-config ← some-gitea.url/zsh-config/dotfiles |
|||
|
|||
The mirror settings are default by your gitea instance. |
|||
|
|||
## Prerequisites |
|||
|
|||
- Something to mirror (a github user or organization with public repos) |
|||
- Gitea instance up and running |
|||
- User for Gitea with generated token |
|||
- Docker |
|||
|
|||
## Run it |
|||
|
|||
```sh |
|||
docker container run \ |
|||
-d \ |
|||
--restart always \ |
|||
-e GITHUB_USER=github-user \ |
|||
-e GITEA_URL=https://some-gitea.url \ |
|||
-e GITEA_TOKEN=please-exchange-with-token \ |
|||
jaedle/mirror-to-gitea:latest |
|||
``` |
|||
|
|||
### Parameters |
|||
|
|||
- `GITHUB_USER` name of users which public repos should be mirrored |
|||
- `GITEA_URL` url of your gitea server |
|||
- `GITEA_TOKEN` token for your gitea user |
|||
|
|||
## Things to do |
|||
|
|||
- configurable interval |
|||
- better logging |
|||
- use github token to solve problems with rate limits |
|||
- add gitlab support |
|||
- and so on.. |
@ -0,0 +1,14 @@ |
|||
#!/usr/bin/env sh |
|||
|
|||
set -e |
|||
|
|||
ONE_HOUR_DELAY=3600 |
|||
|
|||
while true |
|||
do |
|||
echo 'Starting to create mirrors' |
|||
node /app/src/index.js |
|||
|
|||
echo 'Waiting...' |
|||
sleep "${ONE_HOUR_DELAY}" |
|||
done |
@ -0,0 +1,387 @@ |
|||
{ |
|||
"name": "mirror-to-gitea", |
|||
"version": "1.0.0", |
|||
"lockfileVersion": 1, |
|||
"requires": true, |
|||
"dependencies": { |
|||
"@octokit/endpoint": { |
|||
"version": "3.1.3", |
|||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-3.1.3.tgz", |
|||
"integrity": "sha512-vAWzeoj9Lzpl3V3YkWKhGzmDUoMfKpyxJhpq74/ohMvmLXDoEuAGnApy/7TRi3OmnjyX2Lr+e9UGGAD0919ohA==", |
|||
"requires": { |
|||
"deepmerge": "3.2.0", |
|||
"is-plain-object": "^2.0.4", |
|||
"universal-user-agent": "^2.0.1", |
|||
"url-template": "^2.0.8" |
|||
} |
|||
}, |
|||
"@octokit/request": { |
|||
"version": "2.4.1", |
|||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-2.4.1.tgz", |
|||
"integrity": "sha512-nN8W24ZXEpJQJoVgMsGZeK9FOzxkc39Xn9ykseUpPpPMNEDFSvqfkCeqqKrjUiXRm72ubGLWG1SOz0aJPcgGww==", |
|||
"requires": { |
|||
"@octokit/endpoint": "^3.1.1", |
|||
"deprecation": "^1.0.1", |
|||
"is-plain-object": "^2.0.4", |
|||
"node-fetch": "^2.3.0", |
|||
"once": "^1.4.0", |
|||
"universal-user-agent": "^2.0.1" |
|||
} |
|||
}, |
|||
"@octokit/rest": { |
|||
"version": "16.17.0", |
|||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.17.0.tgz", |
|||
"integrity": "sha512-1RB7e4ptR/M+1Ik3Qn84pbppbSadBaCtpgFqgqsXn6s4ZVE6hqW9SOm6UW5yd3KT7ObVfdYUkhMlgR937oKyDw==", |
|||
"requires": { |
|||
"@octokit/request": "2.4.1", |
|||
"before-after-hook": "^1.4.0", |
|||
"btoa-lite": "^1.0.0", |
|||
"lodash.get": "^4.4.2", |
|||
"lodash.set": "^4.3.2", |
|||
"lodash.uniq": "^4.5.0", |
|||
"octokit-pagination-methods": "^1.1.0", |
|||
"universal-user-agent": "^2.0.0", |
|||
"url-template": "^2.0.8" |
|||
} |
|||
}, |
|||
"asynckit": { |
|||
"version": "0.4.0", |
|||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", |
|||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" |
|||
}, |
|||
"before-after-hook": { |
|||
"version": "1.4.0", |
|||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-1.4.0.tgz", |
|||
"integrity": "sha512-l5r9ir56nda3qu14nAXIlyq1MmUSs0meCIaFAh8HwkFwP1F8eToOuS3ah2VAHHcY04jaYD7FpJC5JTXHYRbkzg==" |
|||
}, |
|||
"btoa-lite": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", |
|||
"integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=" |
|||
}, |
|||
"combined-stream": { |
|||
"version": "1.0.7", |
|||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", |
|||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", |
|||
"requires": { |
|||
"delayed-stream": "~1.0.0" |
|||
} |
|||
}, |
|||
"component-emitter": { |
|||
"version": "1.2.1", |
|||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", |
|||
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" |
|||
}, |
|||
"cookiejar": { |
|||
"version": "2.1.2", |
|||
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", |
|||
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" |
|||
}, |
|||
"cross-spawn": { |
|||
"version": "6.0.5", |
|||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", |
|||
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", |
|||
"requires": { |
|||
"nice-try": "^1.0.4", |
|||
"path-key": "^2.0.1", |
|||
"semver": "^5.5.0", |
|||
"shebang-command": "^1.2.0", |
|||
"which": "^1.2.9" |
|||
} |
|||
}, |
|||
"debug": { |
|||
"version": "4.1.1", |
|||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", |
|||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", |
|||
"requires": { |
|||
"ms": "^2.1.1" |
|||
} |
|||
}, |
|||
"deepmerge": { |
|||
"version": "3.2.0", |
|||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.2.0.tgz", |
|||
"integrity": "sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow==" |
|||
}, |
|||
"delayed-stream": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", |
|||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" |
|||
}, |
|||
"deprecation": { |
|||
"version": "1.0.1", |
|||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-1.0.1.tgz", |
|||
"integrity": "sha512-ccVHpE72+tcIKaGMql33x5MAjKQIZrk+3x2GbJ7TeraUCZWHoT+KSZpoC+JQFsUBlSTXUrBaGiF0j6zVTepPLg==" |
|||
}, |
|||
"execa": { |
|||
"version": "0.10.0", |
|||
"resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", |
|||
"integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", |
|||
"requires": { |
|||
"cross-spawn": "^6.0.0", |
|||
"get-stream": "^3.0.0", |
|||
"is-stream": "^1.1.0", |
|||
"npm-run-path": "^2.0.0", |
|||
"p-finally": "^1.0.0", |
|||
"signal-exit": "^3.0.0", |
|||
"strip-eof": "^1.0.0" |
|||
} |
|||
}, |
|||
"form-data": { |
|||
"version": "2.3.3", |
|||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", |
|||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", |
|||
"requires": { |
|||
"asynckit": "^0.4.0", |
|||
"combined-stream": "^1.0.6", |
|||
"mime-types": "^2.1.12" |
|||
} |
|||
}, |
|||
"formidable": { |
|||
"version": "1.2.1", |
|||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", |
|||
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" |
|||
}, |
|||
"get-stream": { |
|||
"version": "3.0.0", |
|||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", |
|||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" |
|||
}, |
|||
"inherits": { |
|||
"version": "2.0.3", |
|||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", |
|||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" |
|||
}, |
|||
"is-plain-object": { |
|||
"version": "2.0.4", |
|||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", |
|||
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", |
|||
"requires": { |
|||
"isobject": "^3.0.1" |
|||
} |
|||
}, |
|||
"is-stream": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", |
|||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" |
|||
}, |
|||
"isexe": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", |
|||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" |
|||
}, |
|||
"isobject": { |
|||
"version": "3.0.1", |
|||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", |
|||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" |
|||
}, |
|||
"lodash.get": { |
|||
"version": "4.4.2", |
|||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", |
|||
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" |
|||
}, |
|||
"lodash.set": { |
|||
"version": "4.3.2", |
|||
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", |
|||
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" |
|||
}, |
|||
"lodash.uniq": { |
|||
"version": "4.5.0", |
|||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", |
|||
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" |
|||
}, |
|||
"macos-release": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.0.0.tgz", |
|||
"integrity": "sha512-iCM3ZGeqIzlrH7KxYK+fphlJpCCczyHXc+HhRVbEu9uNTCrzYJjvvtefzeKTCVHd5AP/aD/fzC80JZ4ZP+dQ/A==" |
|||
}, |
|||
"methods": { |
|||
"version": "1.1.2", |
|||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", |
|||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" |
|||
}, |
|||
"mime": { |
|||
"version": "2.4.0", |
|||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", |
|||
"integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==" |
|||
}, |
|||
"mime-db": { |
|||
"version": "1.38.0", |
|||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", |
|||
"integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" |
|||
}, |
|||
"mime-types": { |
|||
"version": "2.1.22", |
|||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", |
|||
"integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", |
|||
"requires": { |
|||
"mime-db": "~1.38.0" |
|||
} |
|||
}, |
|||
"ms": { |
|||
"version": "2.1.1", |
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", |
|||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" |
|||
}, |
|||
"nice-try": { |
|||
"version": "1.0.5", |
|||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", |
|||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" |
|||
}, |
|||
"node-fetch": { |
|||
"version": "2.3.0", |
|||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", |
|||
"integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" |
|||
}, |
|||
"npm-run-path": { |
|||
"version": "2.0.2", |
|||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", |
|||
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", |
|||
"requires": { |
|||
"path-key": "^2.0.0" |
|||
} |
|||
}, |
|||
"octokit-pagination-methods": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", |
|||
"integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==" |
|||
}, |
|||
"once": { |
|||
"version": "1.4.0", |
|||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", |
|||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", |
|||
"requires": { |
|||
"wrappy": "1" |
|||
} |
|||
}, |
|||
"os-name": { |
|||
"version": "3.0.0", |
|||
"resolved": "https://registry.npmjs.org/os-name/-/os-name-3.0.0.tgz", |
|||
"integrity": "sha512-7c74tib2FsdFbQ3W+qj8Tyd1R3Z6tuVRNNxXjJcZ4NgjIEQU9N/prVMqcW29XZPXGACqaXN3jq58/6hoaoXH6g==", |
|||
"requires": { |
|||
"macos-release": "^2.0.0", |
|||
"windows-release": "^3.1.0" |
|||
} |
|||
}, |
|||
"p-finally": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", |
|||
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" |
|||
}, |
|||
"path-key": { |
|||
"version": "2.0.1", |
|||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", |
|||
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" |
|||
}, |
|||
"qs": { |
|||
"version": "6.6.0", |
|||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz", |
|||
"integrity": "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA==" |
|||
}, |
|||
"readable-stream": { |
|||
"version": "3.2.0", |
|||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", |
|||
"integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", |
|||
"requires": { |
|||
"inherits": "^2.0.3", |
|||
"string_decoder": "^1.1.1", |
|||
"util-deprecate": "^1.0.1" |
|||
} |
|||
}, |
|||
"safe-buffer": { |
|||
"version": "5.1.2", |
|||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", |
|||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" |
|||
}, |
|||
"semver": { |
|||
"version": "5.6.0", |
|||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", |
|||
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" |
|||
}, |
|||
"shebang-command": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", |
|||
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", |
|||
"requires": { |
|||
"shebang-regex": "^1.0.0" |
|||
} |
|||
}, |
|||
"shebang-regex": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", |
|||
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" |
|||
}, |
|||
"signal-exit": { |
|||
"version": "3.0.2", |
|||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", |
|||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" |
|||
}, |
|||
"string_decoder": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", |
|||
"integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", |
|||
"requires": { |
|||
"safe-buffer": "~5.1.0" |
|||
} |
|||
}, |
|||
"strip-eof": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", |
|||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" |
|||
}, |
|||
"superagent": { |
|||
"version": "4.1.0", |
|||
"resolved": "https://registry.npmjs.org/superagent/-/superagent-4.1.0.tgz", |
|||
"integrity": "sha512-FT3QLMasz0YyCd4uIi5HNe+3t/onxMyEho7C3PSqmti3Twgy2rXT4fmkTz6wRL6bTF4uzPcfkUCa8u4JWHw8Ag==", |
|||
"requires": { |
|||
"component-emitter": "^1.2.0", |
|||
"cookiejar": "^2.1.2", |
|||
"debug": "^4.1.0", |
|||
"form-data": "^2.3.3", |
|||
"formidable": "^1.2.0", |
|||
"methods": "^1.1.1", |
|||
"mime": "^2.4.0", |
|||
"qs": "^6.6.0", |
|||
"readable-stream": "^3.0.6" |
|||
} |
|||
}, |
|||
"universal-user-agent": { |
|||
"version": "2.0.3", |
|||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-2.0.3.tgz", |
|||
"integrity": "sha512-eRHEHhChCBHrZsA4WEhdgiOKgdvgrMIHwnwnqD0r5C6AO8kwKcG7qSku3iXdhvHL3YvsS9ZkSGN8h/hIpoFC8g==", |
|||
"requires": { |
|||
"os-name": "^3.0.0" |
|||
} |
|||
}, |
|||
"url-template": { |
|||
"version": "2.0.8", |
|||
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", |
|||
"integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" |
|||
}, |
|||
"util-deprecate": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", |
|||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" |
|||
}, |
|||
"which": { |
|||
"version": "1.3.1", |
|||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", |
|||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", |
|||
"requires": { |
|||
"isexe": "^2.0.0" |
|||
} |
|||
}, |
|||
"windows-release": { |
|||
"version": "3.1.0", |
|||
"resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.1.0.tgz", |
|||
"integrity": "sha512-hBb7m7acFgQPQc222uEQTmdcGLeBmQLNLFIh0rDk3CwFOBrfjefLzEfEfmpMq8Af/n/GnFf3eYf203FY1PmudA==", |
|||
"requires": { |
|||
"execa": "^0.10.0" |
|||
} |
|||
}, |
|||
"wrappy": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", |
|||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
{ |
|||
"name": "mirror-to-gitea", |
|||
"version": "1.0.0", |
|||
"description": "mirror all your public github repositories to your gitea server", |
|||
"main": "index.js", |
|||
"scripts": { |
|||
"test": "echo \"Error: no test specified\" && exit 1" |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/jaedle/mirror-to-gitea.git" |
|||
}, |
|||
"keywords": [], |
|||
"author": "", |
|||
"license": "ISC", |
|||
"bugs": { |
|||
"url": "https://github.com/jaedle/mirror-to-gitea/issues" |
|||
}, |
|||
"homepage": "https://github.com/jaedle/mirror-to-gitea#readme", |
|||
"dependencies": { |
|||
"@octokit/rest": "^16.2.0", |
|||
"superagent": "^4.0.0" |
|||
} |
|||
} |
@ -0,0 +1,14 @@ |
|||
#!/usr/bin/env sh |
|||
|
|||
set -ex |
|||
|
|||
docker image build -t jaedle/mirror-to-gitea:development . |
|||
source .secrets.rc |
|||
|
|||
docker container run \ |
|||
-it \ |
|||
--rm \ |
|||
-e GITHUB_USERNAME="$GITHUB_USERNAME" \ |
|||
-e GITEA_URL="$GITEA_URL" \ |
|||
-e GITEA_TOKEN="$GITEA_TOKEN" \ |
|||
jaedle/mirror-to-gitea:development |
@ -0,0 +1,98 @@ |
|||
const octokit = require('@octokit/rest')(); |
|||
const request = require('superagent'); |
|||
|
|||
|
|||
async function getGithubRepositories(username) { |
|||
return octokit.paginate('GET /users/:username/repos', { username: username }) |
|||
.then(repositories => toRepositoryList(repositories)); |
|||
} |
|||
|
|||
function toRepositoryList(repositories) { |
|||
return repositories.map(repository => { |
|||
return { name: repository.name, url: repository.clone_url } |
|||
}); |
|||
} |
|||
|
|||
async function getGiteaUser(gitea) { |
|||
return request.get(gitea.url |
|||
+ '/api/v1/user') |
|||
.query(`access_token=${gitea.token}`) |
|||
.then(response => { |
|||
return { id: response.body.id, name: response.body.username } |
|||
}); |
|||
} |
|||
|
|||
function isAlreadyMirroredOnGitea(repository, gitea, giteaUser) { |
|||
const requestUrl = `${gitea.url}/api/v1/repos/${giteaUser.name}/${repository}`; |
|||
return request.get( |
|||
requestUrl) |
|||
.query(`access_token=${gitea.token}`) |
|||
.then(() => true) |
|||
.catch(() => false); |
|||
} |
|||
|
|||
function mirrorOnGitea(repository, gitea, giteaUser) { |
|||
request.post(`${gitea.url}/api/v1/repos/migrate`) |
|||
.query(`access_token=${gitea.token}`) |
|||
.send({ |
|||
clone_addr: repository.url, |
|||
mirror: true, |
|||
repo_name: repository.name, |
|||
uid: giteaUser.id, |
|||
}) |
|||
.then(() => { |
|||
console.log('Did it!'); |
|||
}) |
|||
.catch(err => { |
|||
console.log('Failed', err); |
|||
}); |
|||
|
|||
} |
|||
|
|||
async function mirror(repository, gitea, giteaUser) { |
|||
if (await isAlreadyMirroredOnGitea(repository.name, |
|||
gitea, |
|||
giteaUser)) { |
|||
console.log('Repository is already mirrored; doing nothing: ', repository.name); |
|||
return; |
|||
} |
|||
console.log('Mirroring repository to gitea: ', repository.name); |
|||
await mirrorOnGitea(repository, gitea, giteaUser); |
|||
} |
|||
|
|||
async function main() { |
|||
const githubUsername = process.env.GITHUB_USERNAME; |
|||
if (!githubUsername) { |
|||
console.error('No GITHUB_USERNAME specified, please specify! Exiting..'); |
|||
return; |
|||
} |
|||
const giteaUrl = process.env.GITEA_URL; |
|||
if (!giteaUrl) { |
|||
console.error('No GITEA_URL specified, please specify! Exiting..'); |
|||
return; |
|||
} |
|||
|
|||
const giteaToken = process.env.GITEA_TOKEN; |
|||
if (!giteaToken) { |
|||
console.error('No GITEA_TOKEN specified, please specify! Exiting..'); |
|||
return; |
|||
} |
|||
|
|||
|
|||
const githubRepositories = await getGithubRepositories(githubUsername); |
|||
console.log(`Found ${githubRepositories.length} repositories on github`); |
|||
|
|||
const gitea = { |
|||
url: giteaUrl, |
|||
token: giteaToken, |
|||
}; |
|||
|
|||
const giteaUser = await getGiteaUser(gitea); |
|||
githubRepositories.forEach( |
|||
async repository => { |
|||
await mirror(repository, gitea, giteaUser); |
|||
} |
|||
); |
|||
} |
|||
|
|||
main(); |