mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 09:09:36 +02:00
[server-ce] tests: migrate host-admin to ESM, zod and npm-workspaces (#28838)
* [server-ce] tests: migrate host-admin to ESM, zod and npm-workspaces * [server-ce] test: use import.meta.dirname Co-authored-by: Eric Mc Sween <eric.mcsween@overleaf.com> * [server-ce] test: fix zod schema for docker compose endpoint --------- Co-authored-by: Eric Mc Sween <eric.mcsween@overleaf.com> GitOrigin-RevId: d490948693f341210c0ab5c2947db7c9a17775ef
This commit is contained in:
41
package-lock.json
generated
41
package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"workspaces": [
|
"workspaces": [
|
||||||
"jobs/mirror-documentation",
|
"jobs/mirror-documentation",
|
||||||
"libraries/*",
|
"libraries/*",
|
||||||
|
"server-ce/test",
|
||||||
"services/analytics",
|
"services/analytics",
|
||||||
"services/chat",
|
"services/chat",
|
||||||
"services/clsi",
|
"services/clsi",
|
||||||
@@ -14838,6 +14839,10 @@
|
|||||||
"resolved": "tools/saas-e2e",
|
"resolved": "tools/saas-e2e",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@overleaf/server-ce-test": {
|
||||||
|
"resolved": "server-ce/test",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@overleaf/settings": {
|
"node_modules/@overleaf/settings": {
|
||||||
"resolved": "libraries/settings",
|
"resolved": "libraries/settings",
|
||||||
"link": true
|
"link": true
|
||||||
@@ -50695,6 +50700,42 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"server-ce/test": {
|
||||||
|
"name": "@overleaf/server-ce-test",
|
||||||
|
"devDependencies": {
|
||||||
|
"@isomorphic-git/lightning-fs": "^4.6.0",
|
||||||
|
"@overleaf/validation-tools": "*",
|
||||||
|
"@testing-library/cypress": "^10.0.3",
|
||||||
|
"@types/adm-zip": "^0.5.7",
|
||||||
|
"@types/pdf-parse": "^1.1.5",
|
||||||
|
"@types/uuid": "^9.0.8",
|
||||||
|
"adm-zip": "^0.5.12",
|
||||||
|
"body-parser": "^1.20.3",
|
||||||
|
"cypress": "13.13.2",
|
||||||
|
"cypress-multi-reporters": "^2.0.5",
|
||||||
|
"express": "^4.21.2",
|
||||||
|
"isomorphic-git": "^1.33.1",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"mocha-junit-reporter": "^2.2.1",
|
||||||
|
"pdf-parse": "^1.1.1",
|
||||||
|
"uuid": "^9.0.1",
|
||||||
|
"zod-validation-error": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"server-ce/test/node_modules/uuid": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"services/analytics": {
|
"services/analytics": {
|
||||||
"name": "@overleaf/analytics",
|
"name": "@overleaf/analytics",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
"workspaces": [
|
"workspaces": [
|
||||||
"jobs/mirror-documentation",
|
"jobs/mirror-documentation",
|
||||||
"libraries/*",
|
"libraries/*",
|
||||||
|
"server-ce/test",
|
||||||
"services/analytics",
|
"services/analytics",
|
||||||
"services/chat",
|
"services/chat",
|
||||||
"services/clsi",
|
"services/clsi",
|
||||||
|
|||||||
7
server-ce/test/Jenkinsfile
vendored
7
server-ce/test/Jenkinsfile
vendored
@@ -64,8 +64,7 @@ pipeline {
|
|||||||
parallel {
|
parallel {
|
||||||
stage('Install deps') {
|
stage('Install deps') {
|
||||||
steps {
|
steps {
|
||||||
sh 'make install -j10'
|
sh 'make monorepo_setup'
|
||||||
sh 'make -C server-ce/test npm_install_in_docker'
|
|
||||||
script {
|
script {
|
||||||
job_npm_install_done = true
|
job_npm_install_done = true
|
||||||
}
|
}
|
||||||
@@ -85,9 +84,7 @@ pipeline {
|
|||||||
return job_npm_install_done
|
return job_npm_install_done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dir('server-ce/test') {
|
sh 'bin/run -w /overleaf/server-ce/test monorepo npm run format'
|
||||||
sh 'make format_in_docker'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Copybara') {
|
stage('Copybara') {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ all: test-e2e
|
|||||||
# We need to have both file-system layouts agree on the path for the docker compose project.
|
# We need to have both file-system layouts agree on the path for the docker compose project.
|
||||||
# Notable the container labels com.docker.compose.project.working_dir and com.docker.compose.project.config_files need to match when creating containers from the docker host (how you started things) and from host-admin (how tests reconfigure the instance).
|
# Notable the container labels com.docker.compose.project.working_dir and com.docker.compose.project.config_files need to match when creating containers from the docker host (how you started things) and from host-admin (how tests reconfigure the instance).
|
||||||
export PWD = $(shell pwd)
|
export PWD = $(shell pwd)
|
||||||
|
export MONOREPO = $(shell cd ../../ && pwd)
|
||||||
|
|
||||||
export TEX_LIVE_DOCKER_IMAGE ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2023.1
|
export TEX_LIVE_DOCKER_IMAGE ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2023.1
|
||||||
export ALL_TEX_LIVE_DOCKER_IMAGES ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2023.1,us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2022.1
|
export ALL_TEX_LIVE_DOCKER_IMAGES ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2023.1,us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2022.1
|
||||||
@@ -96,14 +97,4 @@ build_mailtrap:
|
|||||||
git clone https://github.com/dbck/docker-mailtrap.git || true && cd docker-mailtrap && git checkout v1.5.0
|
git clone https://github.com/dbck/docker-mailtrap.git || true && cd docker-mailtrap && git checkout v1.5.0
|
||||||
docker build -t mailtrap docker-mailtrap/build
|
docker build -t mailtrap docker-mailtrap/build
|
||||||
|
|
||||||
npm_install_in_docker: export COMPOSE_PROJECT_NAME=
|
|
||||||
npm_install_in_docker:
|
|
||||||
$(MAKE) -C ../../ .metadata/docker-image/monorepo
|
|
||||||
cd ../../ && bin/run --no-deps --workdir /overleaf/server-ce/test monorepo npm --no-dry-run install
|
|
||||||
|
|
||||||
format_in_docker: export COMPOSE_PROJECT_NAME=
|
|
||||||
format_in_docker:
|
|
||||||
$(MAKE) -C ../../ .metadata/docker-image/monorepo
|
|
||||||
cd ../../ && bin/run --no-deps --workdir /overleaf/server-ce/test monorepo npm run format
|
|
||||||
|
|
||||||
.PHONY: test-e2e test-e2e-open
|
.PHONY: test-e2e test-e2e-open
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const { defineConfig } = require('cypress')
|
import { defineConfig } from 'cypress'
|
||||||
const { readPdf, readFileInZip } = require('./helpers/read-file')
|
import { readFileInZip, readPdf } from './helpers/read-file'
|
||||||
const fs = require('node:fs')
|
import fs from 'node:fs'
|
||||||
|
|
||||||
if (process.env.CYPRESS_SHARD && !process.env.SPEC_PATTERN) {
|
if (process.env.CYPRESS_SHARD && !process.env.SPEC_PATTERN) {
|
||||||
// Running Cypress on all the specs is wasteful (~1min) when only few of them
|
// Running Cypress on all the specs is wasteful (~1min) when only few of them
|
||||||
@@ -36,20 +36,19 @@ const specPattern = process.env.SPEC_PATTERN || './**/*.spec.ts'
|
|||||||
let reporterOptions = {}
|
let reporterOptions = {}
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
reporterOptions = {
|
reporterOptions = {
|
||||||
reporter: '/overleaf/server-ce/test/node_modules/cypress-multi-reporters',
|
reporter: `${process.env.MONOREPO}/node_modules/cypress-multi-reporters`,
|
||||||
reporterOptions: {
|
reporterOptions: {
|
||||||
configFile: 'cypress/cypress-multi-reporters.json',
|
configFile: 'cypress/cypress-multi-reporters.json',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = defineConfig({
|
export default defineConfig({
|
||||||
defaultCommandTimeout: 10_000,
|
defaultCommandTimeout: 10_000,
|
||||||
fixturesFolder: 'cypress/fixtures',
|
fixturesFolder: 'cypress/fixtures',
|
||||||
video: process.env.CYPRESS_VIDEO === 'true',
|
video: process.env.CYPRESS_VIDEO === 'true',
|
||||||
screenshotsFolder: 'cypress/results',
|
screenshotsFolder: 'cypress/results',
|
||||||
videosFolder: 'cypress/results',
|
videosFolder: 'cypress/results',
|
||||||
videoUploadOnPasses: false,
|
|
||||||
viewportHeight: 768,
|
viewportHeight: 768,
|
||||||
viewportWidth: 1024,
|
viewportWidth: 1024,
|
||||||
e2e: {
|
e2e: {
|
||||||
@@ -70,11 +70,15 @@ services:
|
|||||||
stop_grace_period: 0s
|
stop_grace_period: 0s
|
||||||
entrypoint: npm
|
entrypoint: npm
|
||||||
command: run cypress:run
|
command: run cypress:run
|
||||||
working_dir: /overleaf/server-ce/test
|
# See comment in Makefile regarding matching file paths
|
||||||
|
working_dir: $PWD
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/overleaf/server-ce/test
|
- $PWD:$PWD
|
||||||
|
- $MONOREPO/libraries:$MONOREPO/libraries:ro
|
||||||
|
- $MONOREPO/node_modules:$MONOREPO/node_modules:ro
|
||||||
user: "${DOCKER_USER:-1000:1000}"
|
user: "${DOCKER_USER:-1000:1000}"
|
||||||
environment:
|
environment:
|
||||||
|
MONOREPO:
|
||||||
CYPRESS_SHARD:
|
CYPRESS_SHARD:
|
||||||
CYPRESS_BASE_URL: http://sharelatex
|
CYPRESS_BASE_URL: http://sharelatex
|
||||||
CYPRESS_FULL_FILESTORE_MIGRATION:
|
CYPRESS_FULL_FILESTORE_MIGRATION:
|
||||||
@@ -101,11 +105,14 @@ services:
|
|||||||
working_dir: $PWD
|
working_dir: $PWD
|
||||||
volumes:
|
volumes:
|
||||||
- $PWD:$PWD
|
- $PWD:$PWD
|
||||||
|
- $MONOREPO/libraries:$MONOREPO/libraries:ro
|
||||||
|
- $MONOREPO/node_modules:$MONOREPO/node_modules:ro
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
stop_grace_period: 0s
|
stop_grace_period: 0s
|
||||||
environment:
|
environment:
|
||||||
CI:
|
CI:
|
||||||
PWD:
|
PWD:
|
||||||
|
MONOREPO:
|
||||||
CYPRESS_SHARD:
|
CYPRESS_SHARD:
|
||||||
COMPOSE_PROJECT_NAME:
|
COMPOSE_PROJECT_NAME:
|
||||||
TEX_LIVE_DOCKER_IMAGE:
|
TEX_LIVE_DOCKER_IMAGE:
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import pdf from 'pdf-parse'
|
// @ts-ignore broken package entrypoint
|
||||||
|
import pdf from 'pdf-parse/lib/pdf-parse.js'
|
||||||
import AdmZip from 'adm-zip'
|
import AdmZip from 'adm-zip'
|
||||||
import { promisify } from 'util'
|
import { setTimeout } from 'timers/promises'
|
||||||
|
|
||||||
const sleep = promisify(setTimeout)
|
|
||||||
|
|
||||||
const MAX_ATTEMPTS = 15
|
const MAX_ATTEMPTS = 15
|
||||||
const POLL_INTERVAL = 500
|
const POLL_INTERVAL = 500
|
||||||
@@ -31,7 +30,7 @@ export async function readFileInZip({
|
|||||||
throw new Error(`${fileToRead} not found in ${pathToZip}`)
|
throw new Error(`${fileToRead} not found in ${pathToZip}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await sleep(POLL_INTERVAL)
|
await setTimeout(POLL_INTERVAL)
|
||||||
attempt++
|
attempt++
|
||||||
}
|
}
|
||||||
throw new Error(`${pathToZip} not found`)
|
throw new Error(`${pathToZip} not found`)
|
||||||
@@ -45,7 +44,7 @@ export async function readPdf(file: string) {
|
|||||||
const { text } = await pdf(dataBuffer)
|
const { text } = await pdf(dataBuffer)
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
await sleep(POLL_INTERVAL)
|
await setTimeout(POLL_INTERVAL)
|
||||||
attempt++
|
attempt++
|
||||||
}
|
}
|
||||||
throw new Error(`${file} not found`)
|
throw new Error(`${file} not found`)
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
const fs = require('fs')
|
import fs from 'node:fs'
|
||||||
const Path = require('path')
|
import Path from 'node:path'
|
||||||
const { execFile } = require('child_process')
|
import { execFile } from 'node:child_process'
|
||||||
const express = require('express')
|
import bodyParser from 'body-parser'
|
||||||
const bodyParser = require('body-parser')
|
import express from 'express'
|
||||||
const {
|
import YAML from 'js-yaml'
|
||||||
celebrate: validate,
|
import { isZodErrorLike } from 'zod-validation-error'
|
||||||
Joi,
|
import { ParamsError, validateReq, z } from '@overleaf/validation-tools'
|
||||||
errors: handleValidationErrors,
|
|
||||||
} = require('celebrate')
|
|
||||||
const YAML = require('js-yaml')
|
|
||||||
|
|
||||||
const DATA_DIR = Path.join(
|
const DATA_DIR = Path.join(
|
||||||
__dirname,
|
import.meta.dirname,
|
||||||
'data',
|
'data',
|
||||||
// Give each shard their own data dir.
|
// Give each shard their own data dir.
|
||||||
process.env.CYPRESS_SHARD || 'default'
|
process.env.CYPRESS_SHARD || 'default'
|
||||||
@@ -108,84 +105,80 @@ app.use((req, res, next) => {
|
|||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
||||||
app.post(
|
app.post('/run/script', (req, res) => {
|
||||||
'/run/script',
|
const {
|
||||||
validate(
|
body: { cwd, script, args, user, hasOverleafEnv },
|
||||||
{
|
} = validateReq(
|
||||||
body: {
|
req,
|
||||||
cwd: Joi.string().required(),
|
z.object({
|
||||||
script: Joi.string().required(),
|
body: z.object({
|
||||||
args: Joi.array().items(Joi.string()),
|
cwd: z.string(),
|
||||||
user: Joi.string().required(),
|
script: z.string(),
|
||||||
hasOverleafEnv: Joi.boolean().required(),
|
args: z.array(z.string()),
|
||||||
},
|
user: z.string(),
|
||||||
},
|
hasOverleafEnv: z.boolean(),
|
||||||
{ allowUnknown: false }
|
}),
|
||||||
),
|
})
|
||||||
(req, res) => {
|
)
|
||||||
const { cwd, script, args, user, hasOverleafEnv } = req.body
|
|
||||||
|
|
||||||
const env = hasOverleafEnv
|
const env = hasOverleafEnv
|
||||||
? 'source /etc/overleaf/env.sh || source /etc/sharelatex/env.sh'
|
? 'source /etc/overleaf/env.sh || source /etc/sharelatex/env.sh'
|
||||||
: 'true'
|
: 'true'
|
||||||
|
|
||||||
runDockerCompose(
|
runDockerCompose(
|
||||||
'exec',
|
'exec',
|
||||||
[
|
[
|
||||||
'--workdir',
|
'--workdir',
|
||||||
`/overleaf/${cwd}`,
|
`/overleaf/${cwd}`,
|
||||||
'sharelatex',
|
'sharelatex',
|
||||||
'bash',
|
'bash',
|
||||||
'-c',
|
'-c',
|
||||||
`source /etc/container_environment.sh && ${env} && /sbin/setuser ${user} node ${script} ${args.map(a => JSON.stringify(a)).join(' ')}`,
|
`source /etc/container_environment.sh && ${env} && /sbin/setuser ${user} node ${script} ${args.map(a => JSON.stringify(a)).join(' ')}`,
|
||||||
],
|
],
|
||||||
(error, stdout, stderr) => {
|
(error, stdout, stderr) => {
|
||||||
res.json({
|
res.json({
|
||||||
error,
|
error,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
app.post(
|
app.post('/run/gruntTask', (req, res) => {
|
||||||
'/run/gruntTask',
|
const {
|
||||||
validate(
|
body: { task, args },
|
||||||
{
|
} = validateReq(
|
||||||
body: {
|
req,
|
||||||
task: Joi.string().required(),
|
z.object({
|
||||||
args: Joi.array().items(Joi.string()),
|
body: z.object({
|
||||||
},
|
task: z.string(),
|
||||||
},
|
args: z.array(z.string()),
|
||||||
{ allowUnknown: false }
|
}),
|
||||||
),
|
})
|
||||||
(req, res) => {
|
)
|
||||||
const { task, args } = req.body
|
|
||||||
|
|
||||||
runDockerCompose(
|
runDockerCompose(
|
||||||
'exec',
|
'exec',
|
||||||
[
|
[
|
||||||
'--workdir',
|
'--workdir',
|
||||||
'/var/www/sharelatex',
|
'/var/www/sharelatex',
|
||||||
'sharelatex',
|
'sharelatex',
|
||||||
'bash',
|
'bash',
|
||||||
'-c',
|
'-c',
|
||||||
`source /etc/container_environment.sh && /sbin/setuser www-data grunt ${JSON.stringify(task)} ${args.map(a => JSON.stringify(a)).join(' ')}`,
|
`source /etc/container_environment.sh && /sbin/setuser www-data grunt ${JSON.stringify(task)} ${args.map(a => JSON.stringify(a)).join(' ')}`,
|
||||||
],
|
],
|
||||||
(error, stdout, stderr) => {
|
(error, stdout, stderr) => {
|
||||||
res.json({
|
res.json({
|
||||||
error,
|
error,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
const allowedVars = Joi.object(
|
const allowedVars = z.object(
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
[
|
[
|
||||||
'OVERLEAF_APP_NAME',
|
'OVERLEAF_APP_NAME',
|
||||||
@@ -227,7 +220,7 @@ const allowedVars = Joi.object(
|
|||||||
'SHARELATEX_SITE_URL',
|
'SHARELATEX_SITE_URL',
|
||||||
'SHARELATEX_MONGO_URL',
|
'SHARELATEX_MONGO_URL',
|
||||||
'SHARELATEX_REDIS_HOST',
|
'SHARELATEX_REDIS_HOST',
|
||||||
].map(name => [name, Joi.string()])
|
].map(name => [name, z.string().optional()])
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -296,36 +289,37 @@ function setVarsDockerCompose({
|
|||||||
writeDockerComposeOverride(cfg)
|
writeDockerComposeOverride(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.post(
|
app.post('/docker/compose/:cmd', (req, res) => {
|
||||||
'/docker/compose/:cmd',
|
const {
|
||||||
validate(
|
params: { cmd },
|
||||||
{
|
body: { args },
|
||||||
body: {
|
} = validateReq(
|
||||||
args: Joi.array().allow(
|
req,
|
||||||
'--detach',
|
z.object({
|
||||||
'--wait',
|
params: z.object({
|
||||||
'--volumes',
|
cmd: z.literal(['up', 'stop', 'down', 'ps', 'logs']),
|
||||||
'--timeout=60',
|
}),
|
||||||
'sharelatex',
|
body: z.object({
|
||||||
'git-bridge',
|
args: z.array(
|
||||||
'mongo',
|
z.literal([
|
||||||
'redis'
|
'--detach',
|
||||||
|
'--wait',
|
||||||
|
'--volumes',
|
||||||
|
'--timeout=60',
|
||||||
|
'sharelatex',
|
||||||
|
'git-bridge',
|
||||||
|
'mongo',
|
||||||
|
'redis',
|
||||||
|
])
|
||||||
),
|
),
|
||||||
},
|
}),
|
||||||
params: {
|
|
||||||
cmd: Joi.allow('up', 'stop', 'down', 'ps', 'logs'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ allowUnknown: false }
|
|
||||||
),
|
|
||||||
(req, res) => {
|
|
||||||
const { cmd } = req.params
|
|
||||||
const { args } = req.body
|
|
||||||
runDockerCompose(cmd, args, (error, stdout, stderr) => {
|
|
||||||
res.json({ error, stdout, stderr })
|
|
||||||
})
|
})
|
||||||
}
|
)
|
||||||
)
|
|
||||||
|
runDockerCompose(cmd, args, (error, stdout, stderr) => {
|
||||||
|
res.json({ error, stdout, stderr })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
function maybeResetData(resetData, callback) {
|
function maybeResetData(resetData, callback) {
|
||||||
if (!resetData) return callback()
|
if (!resetData) return callback()
|
||||||
@@ -347,88 +341,78 @@ function maybeResetData(resetData, callback) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.post(
|
app.post('/reconfigure', (req, res) => {
|
||||||
'/reconfigure',
|
const {
|
||||||
validate(
|
body: { pro, version, vars, withDataDir, resetData, mongoVersion },
|
||||||
{
|
} = validateReq(
|
||||||
body: {
|
req,
|
||||||
pro: Joi.boolean().required(),
|
z.object({
|
||||||
mongoVersion: Joi.string().allow('').optional(),
|
body: z.object({
|
||||||
version: Joi.string().required(),
|
pro: z.boolean(),
|
||||||
|
version: z.string(),
|
||||||
vars: allowedVars,
|
vars: allowedVars,
|
||||||
withDataDir: Joi.boolean().optional(),
|
withDataDir: z.boolean(),
|
||||||
resetData: Joi.boolean().optional(),
|
resetData: z.boolean(),
|
||||||
},
|
mongoVersion: z.string(),
|
||||||
},
|
}),
|
||||||
{ allowUnknown: false }
|
|
||||||
),
|
|
||||||
(req, res) => {
|
|
||||||
const { pro, version, vars, withDataDir, resetData, mongoVersion } =
|
|
||||||
req.body
|
|
||||||
maybeResetData(resetData, (error, stdout, stderr) => {
|
|
||||||
if (error) return res.json({ error, stdout, stderr })
|
|
||||||
|
|
||||||
const previousConfigServer = previousConfig
|
|
||||||
const newConfig = JSON.stringify(req.body)
|
|
||||||
if (previousConfig === newConfig) {
|
|
||||||
return res.json({ previousConfigServer })
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
setVarsDockerCompose({ pro, version, vars, withDataDir, mongoVersion })
|
|
||||||
} catch (error) {
|
|
||||||
return res.json({ error })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) return res.json({ error, stdout, stderr })
|
|
||||||
runDockerCompose(
|
|
||||||
'up',
|
|
||||||
['--detach', '--wait', 'sharelatex'],
|
|
||||||
(error, stdout, stderr) => {
|
|
||||||
previousConfig = newConfig
|
|
||||||
res.json({ error, stdout, stderr, previousConfigServer })
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
)
|
||||||
)
|
maybeResetData(resetData, (error, stdout, stderr) => {
|
||||||
|
if (error) return res.json({ error, stdout, stderr })
|
||||||
|
|
||||||
app.post(
|
const previousConfigServer = previousConfig
|
||||||
'/mongo/setFeatureCompatibilityVersion',
|
const newConfig = JSON.stringify(req.body)
|
||||||
validate(
|
if (previousConfig === newConfig) {
|
||||||
{
|
return res.json({ previousConfigServer })
|
||||||
body: {
|
|
||||||
mongoVersion: Joi.string().required(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ allowUnknown: false }
|
|
||||||
),
|
|
||||||
(req, res) => {
|
|
||||||
const { mongoVersion } = req.body
|
|
||||||
const mongosh = mongoVersion > '5' ? 'mongosh' : 'mongo'
|
|
||||||
const params = {
|
|
||||||
setFeatureCompatibilityVersion: mongoVersion,
|
|
||||||
}
|
}
|
||||||
if (mongoVersion >= '7.0') {
|
|
||||||
// MongoServerError: Once you have upgraded to 7.0, you will not be able to downgrade FCV and binary version without support assistance. Please re-run this command with 'confirm: true' to acknowledge this and continue with the FCV upgrade.
|
try {
|
||||||
// NOTE: 6.0 does not know about this flag. So conditionally add it.
|
setVarsDockerCompose({ pro, version, vars, withDataDir, mongoVersion })
|
||||||
// MongoServerError: BSON field 'setFeatureCompatibilityVersion.confirm' is an unknown field.
|
} catch (error) {
|
||||||
params.confirm = true
|
return res.json({ error })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error) return res.json({ error, stdout, stderr })
|
||||||
runDockerCompose(
|
runDockerCompose(
|
||||||
'exec',
|
'up',
|
||||||
[
|
['--detach', '--wait', 'sharelatex'],
|
||||||
'mongo',
|
|
||||||
mongosh,
|
|
||||||
'--eval',
|
|
||||||
`db.adminCommand(${JSON.stringify(params)})`,
|
|
||||||
],
|
|
||||||
(error, stdout, stderr) => {
|
(error, stdout, stderr) => {
|
||||||
res.json({ error, stdout, stderr })
|
previousConfig = newConfig
|
||||||
|
res.json({ error, stdout, stderr, previousConfigServer })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.post('/mongo/setFeatureCompatibilityVersion', (req, res) => {
|
||||||
|
const {
|
||||||
|
body: { mongoVersion },
|
||||||
|
} = validateReq(
|
||||||
|
req,
|
||||||
|
z.object({
|
||||||
|
body: z.object({
|
||||||
|
mongoVersion: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
const mongosh = mongoVersion > '5' ? 'mongosh' : 'mongo'
|
||||||
|
const params = {
|
||||||
|
setFeatureCompatibilityVersion: mongoVersion,
|
||||||
}
|
}
|
||||||
)
|
if (mongoVersion >= '7.0') {
|
||||||
|
// MongoServerError: Once you have upgraded to 7.0, you will not be able to downgrade FCV and binary version without support assistance. Please re-run this command with 'confirm: true' to acknowledge this and continue with the FCV upgrade.
|
||||||
|
// NOTE: 6.0 does not know about this flag. So conditionally add it.
|
||||||
|
// MongoServerError: BSON field 'setFeatureCompatibilityVersion.confirm' is an unknown field.
|
||||||
|
params.confirm = true
|
||||||
|
}
|
||||||
|
runDockerCompose(
|
||||||
|
'exec',
|
||||||
|
['mongo', mongosh, '--eval', `db.adminCommand(${JSON.stringify(params)})`],
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
res.json({ error, stdout, stderr })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
app.get('/redis/keys', (req, res) => {
|
app.get('/redis/keys', (req, res) => {
|
||||||
runDockerCompose(
|
runDockerCompose(
|
||||||
@@ -450,7 +434,14 @@ app.delete('/data/user_files', (req, res) => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.use(handleValidationErrors())
|
app.use((error, req, res, next) => {
|
||||||
|
if (error instanceof ParamsError) {
|
||||||
|
res.status(404).json({ error })
|
||||||
|
} else if (isZodErrorLike(error)) {
|
||||||
|
res.status(400).json({ error })
|
||||||
|
}
|
||||||
|
next(error)
|
||||||
|
})
|
||||||
|
|
||||||
purgeDataDir()
|
purgeDataDir()
|
||||||
writeDockerComposeOverride(defaultDockerComposeOverride())
|
writeDockerComposeOverride(defaultDockerComposeOverride())
|
||||||
|
|||||||
4021
server-ce/test/package-lock.json
generated
4021
server-ce/test/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,23 @@
|
|||||||
{
|
{
|
||||||
"name": "@overleaf/server-ce/test",
|
"name": "@overleaf/server-ce-test",
|
||||||
"description": "e2e tests for Overleaf Community Edition",
|
"description": "e2e tests for Overleaf Community Edition",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cypress:open": "cypress open --e2e --browser chrome",
|
"cypress:open": "cypress open --e2e --browser chrome",
|
||||||
"cypress:run": "cypress run --e2e --browser chrome",
|
"cypress:run": "cypress run --e2e --browser chrome",
|
||||||
"format": "prettier --list-different $PWD/'**/*.{js,mjs,ts,tsx,json}'",
|
"format": "prettier --list-different $PWD/'**/*.{js,mjs,ts,tsx,json}'",
|
||||||
"format:fix": "prettier --write $PWD/'**/*.{js,mjs,ts,tsx,json}'"
|
"format:fix": "prettier --write $PWD/'**/*.{js,mjs,ts,tsx,json}'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"devDependencies": {
|
||||||
"@isomorphic-git/lightning-fs": "^4.6.0",
|
"@isomorphic-git/lightning-fs": "^4.6.0",
|
||||||
|
"@overleaf/validation-tools": "*",
|
||||||
"@testing-library/cypress": "^10.0.3",
|
"@testing-library/cypress": "^10.0.3",
|
||||||
"@types/adm-zip": "^0.5.7",
|
"@types/adm-zip": "^0.5.7",
|
||||||
"@types/pdf-parse": "^1.1.5",
|
"@types/pdf-parse": "^1.1.5",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"adm-zip": "^0.5.12",
|
"adm-zip": "^0.5.12",
|
||||||
"body-parser": "^1.20.3",
|
"body-parser": "^1.20.3",
|
||||||
"celebrate": "^15.0.3",
|
|
||||||
"cypress": "13.13.2",
|
"cypress": "13.13.2",
|
||||||
"cypress-multi-reporters": "^2.0.5",
|
"cypress-multi-reporters": "^2.0.5",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"mocha-junit-reporter": "^2.2.1",
|
"mocha-junit-reporter": "^2.2.1",
|
||||||
"pdf-parse": "^1.1.1",
|
"pdf-parse": "^1.1.1",
|
||||||
"typescript": "^5.0.4",
|
"uuid": "^9.0.1",
|
||||||
"uuid": "^9.0.1"
|
"zod-validation-error": "^4.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user