mirror of
https://github.com/cupcakearmy/gitea-sync.git
synced 2024-12-25 01:16:24 +00:00
Compare commits
3 Commits
a96af3a897
...
309e939a05
Author | SHA1 | Date | |
---|---|---|---|
309e939a05 | |||
ee25d7db59 | |||
7bc3c990e0 |
@ -1,5 +1,4 @@
|
|||||||
*
|
*
|
||||||
!package.json
|
!package.json
|
||||||
!pnpm-lock.yaml
|
!bun.lockb
|
||||||
!src
|
!src
|
||||||
!tsconfig.json
|
|
||||||
|
22
Dockerfile
22
Dockerfile
@ -1,19 +1,11 @@
|
|||||||
FROM node:18.15-alpine as base
|
FROM oven/bun:1 as base
|
||||||
|
|
||||||
RUN npm -g install pnpm@7
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json pnpm-lock.yaml ./
|
|
||||||
|
|
||||||
FROM base as build
|
FROM base as builder
|
||||||
RUN pnpm install --frozen-lockfile
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN pnpm run build
|
RUN bun install --production --frozen-lockfile
|
||||||
|
RUN bun build --target bun --minify src/index.ts --outfile app.js
|
||||||
FROM base as runner
|
|
||||||
RUN pnpm install --frozen-lockfile --prod
|
|
||||||
COPY --from=build /app/dist /app/dist
|
|
||||||
CMD ["pnpm", "run", "start"]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FROM base
|
||||||
|
COPY --from=builder /app/app.js .
|
||||||
|
ENTRYPOINT [ "bun", "run", "app.js" ]
|
||||||
|
@ -26,7 +26,7 @@ GITHUB_TOKEN=
|
|||||||
|
|
||||||
# Host of the Gitea server
|
# Host of the Gitea server
|
||||||
GITEA_HOST=
|
GITEA_HOST=
|
||||||
# Gitea token (scopes: repo)
|
# Gitea token (scopes: repos: read and write; user: read)
|
||||||
GITEA_TOKEN=
|
GITEA_TOKEN=
|
||||||
|
|
||||||
# OPTIONAL
|
# OPTIONAL
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# FOR DEVELOPMENT ONLY
|
# FOR DEVELOPMENT ONLY
|
||||||
# See README.md for an example
|
# See README.md for an example
|
||||||
|
|
||||||
version: "3.8"
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
job:
|
sync:
|
||||||
image: cupcakearmy/gitea-sync
|
image: cupcakearmy/gitea-sync
|
||||||
build: .
|
build: .
|
||||||
env_file: .env
|
env_file: .env
|
||||||
@ -18,4 +18,4 @@ services:
|
|||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- '3000:3000'
|
||||||
|
15
package.json
15
package.json
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node .",
|
"start": "node .",
|
||||||
@ -8,14 +8,13 @@
|
|||||||
},
|
},
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.7",
|
||||||
"dotenv": "^16.0.3",
|
"node-cron": "^3.0.3",
|
||||||
"node-cron": "^3.0.2",
|
"winston": "^3.11.0"
|
||||||
"winston": "^3.8.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "18",
|
"@types/node": "^20.11.7",
|
||||||
"@types/node-cron": "^3.0.7",
|
"@types/node-cron": "^3.0.11",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
302
pnpm-lock.yaml
generated
302
pnpm-lock.yaml
generated
@ -1,302 +0,0 @@
|
|||||||
lockfileVersion: '6.0'
|
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
axios:
|
|
||||||
specifier: ^1.6.0
|
|
||||||
version: 1.6.0
|
|
||||||
dotenv:
|
|
||||||
specifier: ^16.0.3
|
|
||||||
version: 16.0.3
|
|
||||||
node-cron:
|
|
||||||
specifier: ^3.0.2
|
|
||||||
version: 3.0.2
|
|
||||||
winston:
|
|
||||||
specifier: ^3.8.2
|
|
||||||
version: 3.8.2
|
|
||||||
|
|
||||||
devDependencies:
|
|
||||||
'@types/node':
|
|
||||||
specifier: '18'
|
|
||||||
version: 18.14.6
|
|
||||||
'@types/node-cron':
|
|
||||||
specifier: ^3.0.7
|
|
||||||
version: 3.0.7
|
|
||||||
typescript:
|
|
||||||
specifier: ^4.9.5
|
|
||||||
version: 4.9.5
|
|
||||||
|
|
||||||
packages:
|
|
||||||
|
|
||||||
/@colors/colors@1.5.0:
|
|
||||||
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
|
|
||||||
engines: {node: '>=0.1.90'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@dabh/diagnostics@2.0.3:
|
|
||||||
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
|
|
||||||
dependencies:
|
|
||||||
colorspace: 1.1.4
|
|
||||||
enabled: 2.0.0
|
|
||||||
kuler: 2.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/node-cron@3.0.7:
|
|
||||||
resolution: {integrity: sha512-9PuLtBboc/+JJ7FshmJWv769gDonTpItN0Ol5TMwclpSQNjVyB2SRxSKBcTtbSysSL5R7Oea06kTTFNciCoYwA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/node@18.14.6:
|
|
||||||
resolution: {integrity: sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/triple-beam@1.3.2:
|
|
||||||
resolution: {integrity: sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/async@3.2.4:
|
|
||||||
resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/asynckit@0.4.0:
|
|
||||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/axios@1.6.0:
|
|
||||||
resolution: {integrity: sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==}
|
|
||||||
dependencies:
|
|
||||||
follow-redirects: 1.15.2
|
|
||||||
form-data: 4.0.0
|
|
||||||
proxy-from-env: 1.1.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- debug
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/color-convert@1.9.3:
|
|
||||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
|
||||||
dependencies:
|
|
||||||
color-name: 1.1.3
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/color-name@1.1.3:
|
|
||||||
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/color-name@1.1.4:
|
|
||||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/color-string@1.9.1:
|
|
||||||
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
|
|
||||||
dependencies:
|
|
||||||
color-name: 1.1.4
|
|
||||||
simple-swizzle: 0.2.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/color@3.2.1:
|
|
||||||
resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==}
|
|
||||||
dependencies:
|
|
||||||
color-convert: 1.9.3
|
|
||||||
color-string: 1.9.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/colorspace@1.1.4:
|
|
||||||
resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==}
|
|
||||||
dependencies:
|
|
||||||
color: 3.2.1
|
|
||||||
text-hex: 1.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/combined-stream@1.0.8:
|
|
||||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
|
||||||
engines: {node: '>= 0.8'}
|
|
||||||
dependencies:
|
|
||||||
delayed-stream: 1.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/delayed-stream@1.0.0:
|
|
||||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
|
||||||
engines: {node: '>=0.4.0'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/dotenv@16.0.3:
|
|
||||||
resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/enabled@2.0.0:
|
|
||||||
resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/fecha@4.2.3:
|
|
||||||
resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/fn.name@1.1.0:
|
|
||||||
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/follow-redirects@1.15.2:
|
|
||||||
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
|
||||||
engines: {node: '>=4.0'}
|
|
||||||
peerDependencies:
|
|
||||||
debug: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
debug:
|
|
||||||
optional: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/form-data@4.0.0:
|
|
||||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
dependencies:
|
|
||||||
asynckit: 0.4.0
|
|
||||||
combined-stream: 1.0.8
|
|
||||||
mime-types: 2.1.35
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/inherits@2.0.4:
|
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/is-arrayish@0.3.2:
|
|
||||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/is-stream@2.0.1:
|
|
||||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/kuler@2.0.0:
|
|
||||||
resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/logform@2.5.1:
|
|
||||||
resolution: {integrity: sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==}
|
|
||||||
dependencies:
|
|
||||||
'@colors/colors': 1.5.0
|
|
||||||
'@types/triple-beam': 1.3.2
|
|
||||||
fecha: 4.2.3
|
|
||||||
ms: 2.1.3
|
|
||||||
safe-stable-stringify: 2.4.2
|
|
||||||
triple-beam: 1.3.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/mime-db@1.52.0:
|
|
||||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/mime-types@2.1.35:
|
|
||||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dependencies:
|
|
||||||
mime-db: 1.52.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ms@2.1.3:
|
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/node-cron@3.0.2:
|
|
||||||
resolution: {integrity: sha512-iP8l0yGlNpE0e6q1o185yOApANRe47UPbLf4YxfbiNHt/RU5eBcGB/e0oudruheSf+LQeDMezqC5BVAb5wwRcQ==}
|
|
||||||
engines: {node: '>=6.0.0'}
|
|
||||||
dependencies:
|
|
||||||
uuid: 8.3.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/one-time@1.0.0:
|
|
||||||
resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==}
|
|
||||||
dependencies:
|
|
||||||
fn.name: 1.1.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/proxy-from-env@1.1.0:
|
|
||||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/readable-stream@3.6.1:
|
|
||||||
resolution: {integrity: sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
dependencies:
|
|
||||||
inherits: 2.0.4
|
|
||||||
string_decoder: 1.3.0
|
|
||||||
util-deprecate: 1.0.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/safe-buffer@5.2.1:
|
|
||||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/safe-stable-stringify@2.4.2:
|
|
||||||
resolution: {integrity: sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/simple-swizzle@0.2.2:
|
|
||||||
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
|
||||||
dependencies:
|
|
||||||
is-arrayish: 0.3.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/stack-trace@0.0.10:
|
|
||||||
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/string_decoder@1.3.0:
|
|
||||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
|
||||||
dependencies:
|
|
||||||
safe-buffer: 5.2.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/text-hex@1.0.0:
|
|
||||||
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/triple-beam@1.3.0:
|
|
||||||
resolution: {integrity: sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/typescript@4.9.5:
|
|
||||||
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
|
|
||||||
engines: {node: '>=4.2.0'}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/util-deprecate@1.0.2:
|
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/uuid@8.3.2:
|
|
||||||
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
|
|
||||||
hasBin: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/winston-transport@4.5.0:
|
|
||||||
resolution: {integrity: sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==}
|
|
||||||
engines: {node: '>= 6.4.0'}
|
|
||||||
dependencies:
|
|
||||||
logform: 2.5.1
|
|
||||||
readable-stream: 3.6.1
|
|
||||||
triple-beam: 1.3.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/winston@3.8.2:
|
|
||||||
resolution: {integrity: sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==}
|
|
||||||
engines: {node: '>= 12.0.0'}
|
|
||||||
dependencies:
|
|
||||||
'@colors/colors': 1.5.0
|
|
||||||
'@dabh/diagnostics': 2.0.3
|
|
||||||
async: 3.2.4
|
|
||||||
is-stream: 2.0.1
|
|
||||||
logform: 2.5.1
|
|
||||||
one-time: 1.0.0
|
|
||||||
readable-stream: 3.6.1
|
|
||||||
safe-stable-stringify: 2.4.2
|
|
||||||
stack-trace: 0.0.10
|
|
||||||
triple-beam: 1.3.0
|
|
||||||
winston-transport: 4.5.0
|
|
||||||
dev: false
|
|
@ -12,6 +12,8 @@ const Base = axios.create({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const l = logger.child({ api: 'gitea' })
|
||||||
|
|
||||||
export type MirrorOptions = {
|
export type MirrorOptions = {
|
||||||
private: boolean
|
private: boolean
|
||||||
auth_token: string
|
auth_token: string
|
||||||
@ -20,7 +22,7 @@ export type MirrorOptions = {
|
|||||||
}
|
}
|
||||||
export async function mirror(options: MirrorOptions) {
|
export async function mirror(options: MirrorOptions) {
|
||||||
try {
|
try {
|
||||||
logger.debug('Mirroring repository', options)
|
l.debug('mirroring repository', options)
|
||||||
const response = await Base({
|
const response = await Base({
|
||||||
url: '/repos/migrate',
|
url: '/repos/migrate',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -41,18 +43,19 @@ export async function mirror(options: MirrorOptions) {
|
|||||||
releases: true,
|
releases: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
logger.debug('Mirrored repository', { data: response.data })
|
l.debug('mirrored repository', { data: response.data })
|
||||||
return response.data
|
return response.data
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof AxiosError) {
|
if (e instanceof AxiosError) {
|
||||||
logger.error('Error mirroring repository', e.response?.data)
|
l.error('Error mirroring repository', e.response?.data)
|
||||||
} else {
|
} else {
|
||||||
logger.error('Unknown error', e)
|
l.error('Unknown error', e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listRepositories(page: number, limit: number) {
|
export async function listRepositories(page: number, limit: number) {
|
||||||
|
l.debug(`listing repos`, { page, limit })
|
||||||
const response = await Base<ListRepositoriesResponse>({
|
const response = await Base<ListRepositoriesResponse>({
|
||||||
url: '/user/repos',
|
url: '/user/repos',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -65,22 +68,23 @@ export async function listRepositories(page: number, limit: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function listAllRepositories() {
|
export async function listAllRepositories() {
|
||||||
logger.debug('Listing all repositories in Gitea')
|
l.debug('listing all repositories')
|
||||||
const limit = 50
|
const limit = 50
|
||||||
const repos: ListRepositoriesResponse = []
|
const repos: ListRepositoriesResponse = []
|
||||||
let page = 1
|
let page = 1
|
||||||
while (true) {
|
while (true) {
|
||||||
|
l.debug('listing page', { page })
|
||||||
const response = await listRepositories(page, limit)
|
const response = await listRepositories(page, limit)
|
||||||
repos.push(...response)
|
repos.push(...response)
|
||||||
if (response.length < limit) break
|
if (response.length < limit) break
|
||||||
page++
|
page++
|
||||||
}
|
}
|
||||||
logger.debug('Listed all repositories in Gitea', { data: repos })
|
l.debug('listed all repositories', { repos: repos.map((repo) => repo.name) })
|
||||||
return repos
|
return repos
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateRepository(owner: string, repo: string, body: Partial<Repository>) {
|
export async function updateRepository(owner: string, repo: string, body: Partial<Repository>) {
|
||||||
logger.debug('Updating repository', { owner, repo, body })
|
l.debug('updating repository', { owner, repo, body })
|
||||||
await Base({
|
await Base({
|
||||||
url: `/repos/${owner}/${repo}`,
|
url: `/repos/${owner}/${repo}`,
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
|
@ -2,6 +2,7 @@ import axios from 'axios'
|
|||||||
|
|
||||||
import { Config } from '../config.js'
|
import { Config } from '../config.js'
|
||||||
import type { ListRepositoriesResponse } from './github.types.js'
|
import type { ListRepositoriesResponse } from './github.types.js'
|
||||||
|
import { logger } from '../logger.js'
|
||||||
|
|
||||||
const Base = axios.create({
|
const Base = axios.create({
|
||||||
baseURL: 'https://api.github.com',
|
baseURL: 'https://api.github.com',
|
||||||
@ -12,7 +13,10 @@ const Base = axios.create({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const l = logger.child({ api: 'github' })
|
||||||
|
|
||||||
async function listRepos(page: number, limit: number) {
|
async function listRepos(page: number, limit: number) {
|
||||||
|
l.debug('listing repos', { page, limit })
|
||||||
const response = await Base<ListRepositoriesResponse>({
|
const response = await Base<ListRepositoriesResponse>({
|
||||||
url: `user/repos`,
|
url: `user/repos`,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -26,14 +30,17 @@ async function listRepos(page: number, limit: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function listAllRepositories() {
|
export async function listAllRepositories() {
|
||||||
|
l.debug('listing all repos')
|
||||||
const limit = 100
|
const limit = 100
|
||||||
const repos: ListRepositoriesResponse = []
|
const repos: ListRepositoriesResponse = []
|
||||||
let page = 1
|
let page = 1
|
||||||
while (true) {
|
while (true) {
|
||||||
|
l.debug('listing page', { page })
|
||||||
const response = await listRepos(page, limit)
|
const response = await listRepos(page, limit)
|
||||||
repos.push(...response)
|
repos.push(...response)
|
||||||
if (response.length < limit) break
|
if (response.length < limit) break
|
||||||
page++
|
page++
|
||||||
}
|
}
|
||||||
|
l.debug('listed all repos')
|
||||||
return repos
|
return repos
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import { config } from 'dotenv'
|
|
||||||
|
|
||||||
config()
|
|
||||||
|
|
||||||
function getEnv(key: string, fallback: string, parse?: undefined, validator?: (s: string) => boolean): string
|
function getEnv(key: string, fallback: string, parse?: undefined, validator?: (s: string) => boolean): string
|
||||||
function getEnv<T>(key: string, fallback: T, parse: (value: string) => T, validator?: (T: string) => boolean): T
|
function getEnv<T>(key: string, fallback: T, parse: (value: string) => T, validator?: (T: string) => boolean): T
|
||||||
function getEnv<T>(
|
function getEnv<T>(
|
||||||
@ -19,12 +15,6 @@ function getEnv<T>(
|
|||||||
return parsed
|
return parsed
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBoolean(value: string): boolean {
|
|
||||||
value = value.toLowerCase()
|
|
||||||
const truthy = ['true', 'yes', '1', 'y']
|
|
||||||
return truthy.includes(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
function isPresent(s: string): boolean {
|
function isPresent(s: string): boolean {
|
||||||
return s.length > 0
|
return s.length > 0
|
||||||
}
|
}
|
||||||
|
24
src/core.ts
24
src/core.ts
@ -5,30 +5,32 @@ import { logger } from './logger.js'
|
|||||||
|
|
||||||
let running = false
|
let running = false
|
||||||
|
|
||||||
|
const l = logger.child({ context: 'runner' })
|
||||||
|
|
||||||
export async function sync() {
|
export async function sync() {
|
||||||
if (running) {
|
if (running) {
|
||||||
logger.info('Already running, skipping')
|
l.info('already running, skipping')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
logger.info('Starting sync')
|
l.info('starting sync')
|
||||||
const syncedRepos = await giteaRepos()
|
const syncedRepos = await giteaRepos()
|
||||||
const toSync = await githubRepos()
|
const toSync = await githubRepos()
|
||||||
logger.debug('Loaded repos', { remote: toSync.length, local: syncedRepos.length })
|
l.debug('loaded repos', { remote: toSync.length, local: syncedRepos.length })
|
||||||
|
|
||||||
for (const repo of toSync) {
|
for (const repo of toSync) {
|
||||||
|
const lr = l.child({ repo: repo.name })
|
||||||
const sameName = syncedRepos.find((r) => r.name === repo.name || r.original_url === repo.clone_url)
|
const sameName = syncedRepos.find((r) => r.name === repo.name || r.original_url === repo.clone_url)
|
||||||
if (sameName) {
|
if (sameName) {
|
||||||
if (sameName.original_url === repo.clone_url) {
|
if (sameName.original_url === repo.clone_url) {
|
||||||
if (sameName.private === repo.private) logger.info('Already synced, skipping', { name: repo.name })
|
if (sameName.private === repo.private) logger.info('Already synced, skipping', { name: repo.name })
|
||||||
else {
|
else {
|
||||||
logger.info('Visibility changed, updating', { name: repo.name })
|
lr.info('visibility changed, updating')
|
||||||
const [owner, repository] = sameName.full_name.split('/')
|
const [owner, repository] = sameName.full_name.split('/')
|
||||||
await updateRepository(owner, repository, { private: repo.private })
|
await updateRepository(owner, repository, { private: repo.private })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error('Repo with same name but different url', {
|
lr.error('repo with same name but different url', {
|
||||||
name: repo.name,
|
|
||||||
url: repo.clone_url,
|
url: repo.clone_url,
|
||||||
original_url: sameName.original_url,
|
original_url: sameName.original_url,
|
||||||
})
|
})
|
||||||
@ -42,14 +44,14 @@ export async function sync() {
|
|||||||
private: repo.private,
|
private: repo.private,
|
||||||
auth_token: Config.github.token,
|
auth_token: Config.github.token,
|
||||||
}
|
}
|
||||||
logger.info('Mirroring repository', options)
|
lr.info('mirroring repository', options)
|
||||||
await mirror(options)
|
await mirror(options)
|
||||||
logger.info('Mirrored repository', { name: repo.name })
|
lr.info('mirrored repository')
|
||||||
}
|
}
|
||||||
logger.info('Finished sync')
|
l.info('Finished sync')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.debug(error)
|
l.debug(error)
|
||||||
logger.error('Failed to sync', { error: error instanceof Error ? error.message : 'Unknown error' })
|
l.error('Failed to sync', { error: error instanceof Error ? error.message : 'Unknown error' })
|
||||||
} finally {
|
} finally {
|
||||||
running = false
|
running = false
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user