Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e6df30e
tmp: A naive github-sync framework
Musicminion Feb 24, 2026
fa29536
dev: update dev yml for github sync, also added with ldap test, Readm…
Musicminion Feb 24, 2026
a48fef0
web: update passport-ldapauth to 3.0.1
Musicminion Feb 24, 2026
382d914
optimize: clean unused code and fix unauthorized github reminder
Musicminion Feb 24, 2026
8ae6703
feat: support import and export for github
Musicminion Feb 26, 2026
9d06105
github-sync: bug fix and new features:
Musicminion Feb 26, 2026
76654fb
feature: support github sync with merge API, also frontend code
Musicminion Feb 27, 2026
9c96646
fix: add clean up for github-sync
Musicminion Feb 28, 2026
e17d2c5
frontend: optimize import while loading
Musicminion Feb 28, 2026
9094979
fix: use fast-forward to apply changes in overleaf if no update in gi…
Musicminion Feb 28, 2026
5ababd6
ce: add github-sync to `server-ce`
Musicminion Feb 28, 2026
370bf05
feat: add proxy for github sync
Musicminion Feb 28, 2026
37f8b84
fix: proxy import from github-sync
Musicminion Feb 28, 2026
7f1a7b7
fix: enhance GitHub sync Modal with need-auth modal for new user
Musicminion Feb 28, 2026
ff2527a
docs: update README
Musicminion Mar 2, 2026
dd03d8f
fix: refactor GitHub sync module imports to use dynamic loading
Musicminion Mar 2, 2026
edd28de
fix: add fetchJson import for GitHub sync in handler
Musicminion Mar 2, 2026
17c0e85
github-sync: remove dev router
Musicminion Mar 2, 2026
4511f94
ci: add `github-sync` to dev image
Musicminion Mar 3, 2026
0886af2
fix: improve error handling in GitHub sync and optimize token storage
Musicminion Mar 3, 2026
bc23e17
fix: filter non-blob items in generateRespURL and update token validi…
Musicminion Mar 3, 2026
b0c869e
fix: enhance validation for GitHub sync state and improve error handling
Musicminion Mar 3, 2026
34f0013
fix: update OLModal properties to disable initialFocus
Musicminion Mar 7, 2026
be50d34
fix: enhance error handling for GitHub branch diffing by checking res…
Musicminion Mar 7, 2026
8745430
Add Star History section to README
Musicminion Mar 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions develop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ each service:
| `history-v1` | 9239 |
| `project-history` | 9240 |
| `linked-url-proxy` | 9241 |
| `github-sync` | 9242 |

To attach to a service using Chrome's _remote debugging_, go to
<chrome://inspect/> and make sure _Discover network targets_ is checked. Next
Expand Down
11 changes: 11 additions & 0 deletions develop/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ services:
- ../services/filestore/app.js:/overleaf/services/filestore/app.js
- ../services/filestore/config:/overleaf/services/filestore/config

github-sync:
command: ["node", "--watch", "app.js"]
environment:
- NODE_OPTIONS=--inspect=0.0.0.0:9229
ports:
- "127.0.0.1:9242:9229"
volumes:
- ../services/github-sync/app:/overleaf/services/github-sync/app
- ../services/github-sync/app.js:/overleaf/services/github-sync/app.js
- ../services/github-sync/config:/overleaf/services/github-sync/config

history-v1:
command: ["node", "--watch", "app.js"]
environment:
Expand Down
16 changes: 15 additions & 1 deletion develop/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ services:
- filestore-uploads:/overleaf/services/filestore/uploads
- history-v1-buckets:/buckets

github-sync:
build:
context: ..
dockerfile: services/github-sync/Dockerfile
env_file:
- dev.env

history-v1:
build:
context: ..
Expand Down Expand Up @@ -155,6 +162,7 @@ services:
volumes:
- sharelatex-data:/var/lib/overleaf
- web-data:/overleaf/services/web/data
- ./data/certs/:/var/lib/overleaf/certs/
depends_on:
- mongo
- redis
Expand Down Expand Up @@ -232,4 +240,10 @@ services:
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_SERVER: mongo
ME_CONFIG_MONGODB_SERVER: mongo

# For ldap testing
# https://github.com/rroemhild/docker-test-openldap
ldap:
restart: always
image: ghcr.io/rroemhild/docker-test-openldap:v2.5.0
1 change: 1 addition & 0 deletions services/github-sync/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.18.0
46 changes: 46 additions & 0 deletions services/github-sync/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This file was auto-generated, do not edit it directly.
# Instead run bin/update_build_scripts from
# https://github.com/overleaf/internal/

FROM node:22.18.0 AS base

WORKDIR /overleaf/services/github-sync

# Google Cloud Storage needs a writable $HOME/.config for resumable uploads
# (see https://googleapis.dev/nodejs/storage/latest/File.html#createWriteStream)
RUN mkdir /home/node/.config && chown node:node /home/node/.config

FROM base AS app

COPY package.json package-lock.json /overleaf/
COPY libraries/access-token-encryptor/package.json /overleaf/libraries/access-token-encryptor/package.json
COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json
COPY libraries/logger/package.json /overleaf/libraries/logger/package.json
COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json
COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json
COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json
COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json
COPY libraries/settings/package.json /overleaf/libraries/settings/package.json
COPY libraries/stream-utils/package.json /overleaf/libraries/stream-utils/package.json
COPY services/github-sync/package.json /overleaf/services/github-sync/package.json
COPY tools/migrations/package.json /overleaf/tools/migrations/package.json
COPY patches/ /overleaf/patches/
COPY tools/migrations/ /overleaf/tools/migrations/

RUN cd /overleaf && npm ci --quiet
COPY libraries/access-token-encryptor/ /overleaf/libraries/access-token-encryptor/
COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/
COPY libraries/logger/ /overleaf/libraries/logger/
COPY libraries/metrics/ /overleaf/libraries/metrics/
COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/
COPY libraries/o-error/ /overleaf/libraries/o-error/
COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/
COPY libraries/settings/ /overleaf/libraries/settings/
COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/
COPY services/github-sync/ /overleaf/services/github-sync/
COPY tools/migrations/ /overleaf/tools/migrations/

FROM app
USER node

CMD ["node", "--expose-gc", "app.js"]
3 changes: 3 additions & 0 deletions services/github-sync/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# GitHub Sync Service

Overleaf Github Sync Service, @Ayaka-notes.
19 changes: 19 additions & 0 deletions services/github-sync/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Metrics must be initialized before importing anything else
import '@overleaf/metrics/initialize.js'

import logger from '@overleaf/logger'
import Settings from '@overleaf/settings'
import { createServer } from './app/js/server.js'

const port = Settings.internal?.githubSync?.port
const host = Settings.internal?.githubSync?.host

const { server } = createServer()
server.listen(port, host, err => {
if (err) {
logger.fatal({ err }, `Cannot bind to ${host}:${port}. Exiting.`)
process.exit(1)
}

logger.info({ host, port }, 'GitHub Sync service listening')
})
26 changes: 26 additions & 0 deletions services/github-sync/app/js/mongodb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @ts-check

import Metrics from '@overleaf/metrics'
import Settings from '@overleaf/settings'
import MongoUtils from '@overleaf/mongo-utils'
import { MongoClient } from 'mongodb'

export { ObjectId } from 'mongodb'

export const mongoClient = new MongoClient(
Settings.mongo.url,
Settings.mongo.options
)
const mongoDb = mongoClient.db()

export const db = {
githubSyncEntityVersions: mongoDb.collection('githubSyncEntityVersions'),
githubSyncProjectStates: mongoDb.collection('githubSyncProjectStates'),
githubSyncUserCredentials: mongoDb.collection('githubSyncUserCredentials'),
}

Metrics.mongodb.monitor(mongoClient)

export async function cleanupTestDatabase() {
await MongoUtils.cleanupTestDatabase(mongoClient)
}
16 changes: 16 additions & 0 deletions services/github-sync/app/js/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import express from 'express'
import { db, ObjectId } from './mongodb.js'

export function createServer() {
const app = express()

app.get('/status', (_req, res) => {
res.status(200).json({ status: 'ok', service: 'github-sync' })
})

app.get('/healthz', (_req, res) => {
res.sendStatus(204)
})

return { app, server: app }
}
30 changes: 30 additions & 0 deletions services/github-sync/config/settings.defaults.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const http = require('node:http')
const https = require('node:https')

http.globalAgent.maxSockets = 300
http.globalAgent.keepAlive = false
https.globalAgent.keepAlive = false

module.exports = {
internal: {
githubSync: {
host: process.env.GITHUB_SYNC_HOST || process.env.LISTEN_ADDRESS || '127.0.0.1',
port: 3022,
},
},

mongo: {
url:
process.env.MONGO_CONNECTION_STRING ||
`mongodb://${process.env.MONGO_HOST || '127.0.0.1'}/sharelatex`,
options: {
monitorCommands: true,
},
},

apis: {
project_history: {
url: `http://${process.env.PROJECT_HISTORY_HOST || '127.0.0.1'}:3054`,
}
}
}
58 changes: 58 additions & 0 deletions services/github-sync/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@overleaf/github-sync",
"description": "GitHub synchronization microservice for Overleaf",
"private": true,
"main": "app.js",
"type": "module",
"scripts": {
"start": "node app.js",
"nodemon": "node --watch app.js",
"lint": "eslint --max-warnings 0 --format unix .",
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
"lint:fix": "eslint --fix .",
"types:check": "tsc --noEmit"
},
"dependencies": {
"@octokit/request": "^9.2.2",
"@overleaf/access-token-encryptor": "*",
"@overleaf/fetch-utils": "*",
"@overleaf/logger": "*",
"@overleaf/metrics": "*",
"@overleaf/mongo-utils": "*",
"@overleaf/o-error": "*",
"@overleaf/promise-utils": "*",
"@overleaf/settings": "*",
"async": "^3.2.5",
"base64-stream": "^0.1.2",
"body-parser": "1.20.4",
"bunyan": "^1.8.15",
"express": "4.22.1",
"lodash": "^4.17.21",
"mongodb-legacy": "6.1.3",
"nock": "^13.5.6",
"octonode": "0.9.5",
"p-limit": "^2.2.0",
"randomstring": "^1.1.5",
"request": "2.88.2"
},
"devDependencies": {
"@overleaf/migrations": "*",
"@overleaf/stream-utils": "*",
"@pollyjs/adapter-node-http": "^6.0.6",
"@pollyjs/core": "^6.0.6",
"@pollyjs/persister-fs": "^6.0.6",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"mocha": "^11.1.0",
"mocha-junit-reporter": "^2.2.1",
"mocha-multi-reporters": "^1.5.1",
"sandboxed-module": "^2.0.4",
"sinon": "^9.2.4",
"sinon-chai": "^3.7.0",
"timekeeper": "2.2.0",
"typescript": "^5.0.4"
},
"version": "1.0.0",
"license": "AGPL-3.0"
}
29 changes: 26 additions & 3 deletions services/web/config/settings.defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -1011,10 +1011,25 @@ module.exports = {
mainEditorLayoutPanels: [],
langFeedbackLinkingWidgets: [],
labsExperiments: [],
integrationLinkingWidgets: [],
integrationLinkingWidgets: [
Path.resolve(
__dirname,
'../modules/github-sync/frontend/js/components/github-sync-widget.tsx'
),
Comment on lines +1018 to +1022
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate GitHub UI imports on feature flag

These module imports are always enabled in overleafModuleImports, so GitHub UI surfaces even when GITHUB_SYNC_ENABLED is false. In that configuration the backend router is not mounted, so users still see GitHub actions but hit missing endpoints (for example status/auth routes), which breaks the intended disable switch for this feature.

Useful? React with 👍 / 👎.

],
referenceLinkingWidgets: [],
importProjectFromGithubModalWrapper: [],
importProjectFromGithubMenu: [],
importProjectFromGithubModalWrapper: [
Path.resolve(
__dirname,
'../modules/github-sync/frontend/js/components/import-from-github-modal-wrapper.tsx'
),
],
importProjectFromGithubMenu: [
Path.resolve(
__dirname,
'../modules/github-sync/frontend/js/components/import-from-github-menu.tsx'
),
],
editorLeftMenuSync: [
Path.resolve(
__dirname,
Expand Down Expand Up @@ -1105,6 +1120,7 @@ module.exports = {
'login-register',
'oauth2-server',
'git-bridge',
'github-sync'
],
viewIncludes: {},

Expand Down Expand Up @@ -1154,4 +1170,11 @@ module.exports.oauthProviders = {
linkPath: '/oidc/login',
},
}),
}

module.exports.githubSync = {
enabled: process.env.GITHUB_SYNC_ENABLED === 'true',
clientID: process.env.GITHUB_SYNC_CLIENT_ID,
clientSecret: process.env.GITHUB_SYNC_CLIENT_SECRET,
callbackURL: process.env.GITHUB_SYNC_CALLBACK_URL,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import mongoose from "../../../../app/src/infrastructure/Mongoose.mjs"

const { Schema } = mongoose
const { ObjectId } = Schema

export const GitHubSyncUserCredentialsSchema = new Schema(
{
userId: { type: ObjectId, ref: 'User', required: true, unique: true },
auth_token_encrypted: { type: String, required: true },
},
{ collection: 'githubSyncUserCredentials', minimize: false }
)

export const GitHubSyncUserCredentials = mongoose.model(
'GitHubSyncUserCredentials',
GitHubSyncUserCredentialsSchema,
)
Loading