Merge pull request #18893 from overleaf/msm-sp-e2e-native-run

[CE/SP] Added `test-e2e-native` runner

GitOrigin-RevId: a123b2a83a47566a091acc37ccef6c4895bc9949
This commit is contained in:
Miguel Serrano 2024-06-17 13:05:06 +02:00 committed by Copybot
parent 9cb313d687
commit 6ba61f19f4
5 changed files with 68 additions and 31 deletions

View file

@ -10,6 +10,10 @@ export TEX_LIVE_DOCKER_IMAGE ?= quay.io/sharelatex/texlive-full:2023.1
export ALL_TEX_LIVE_DOCKER_IMAGES ?= quay.io/sharelatex/texlive-full:2023.1,quay.io/sharelatex/texlive-full:2022.1
export IMAGE_TAG_PRO ?= quay.io/sharelatex/sharelatex-pro:latest
test-e2e-native:
docker compose -f docker-compose.yml -f docker-compose.native.yml up --build --no-log-prefix sharelatex host-admin -d
CYPRESS_ADMIN_CLIENT_URL='http://localhost:8081' CYPRESS_GIT_BRIDGE_PUBLIC_HOST='localhost' npm run cypress:open
test-e2e:
docker compose up --build --no-log-prefix --exit-code-from=e2e e2e

View file

@ -0,0 +1,14 @@
version: '2.2'
services:
sharelatex:
ports:
- "127.0.0.1:80:80"
environment:
OVERLEAF_SITE_URL: 'http://localhost'
host-admin:
ports:
- "127.0.0.1:8081:80"
environment:
NATIVE_CYPRESS: 'true'
ACCESS_CONTROL_ALLOW_ORIGIN: 'http://localhost'

View file

@ -15,6 +15,9 @@ describe('git-bridge', function () {
V1_HISTORY_URL: 'http://sharelatex:3100/api',
}
const gitBridgePublicHost =
Cypress.env('GIT_BRIDGE_PUBLIC_HOST') || 'sharelatex'
describe('enabled in Server Pro', function () {
startWith({
pro: true,
@ -74,7 +77,9 @@ describe('git-bridge', function () {
cy.findByText('Git').click()
cy.findByRole('dialog').within(() => {
cy.get('@projectId').then(id => {
cy.get('code').contains(`git clone http://git@sharelatex/git/${id}`)
cy.get('code').contains(
`git clone http://git@${gitBridgePublicHost}/git/${id}`
)
})
cy.findByRole('button', {
name: 'Generate token',
@ -88,7 +93,9 @@ describe('git-bridge', function () {
cy.findByText('Git').click()
cy.findByRole('dialog').within(() => {
cy.get('@projectId').then(id => {
cy.get('code').contains(`git clone http://git@sharelatex/git/${id}`)
cy.get('code').contains(
`git clone http://git@${gitBridgePublicHost}/git/${id}`
)
})
cy.findByText('Generate token').should('not.exist')
cy.findByText(/generate a new one in Account Settings/)
@ -109,7 +116,7 @@ describe('git-bridge', function () {
cy.get('@projectId').then(projectId => {
cy.findByRole('dialog').within(() => {
cy.get('code').contains(
`git clone http://git@sharelatex/git/${projectId}`
`git clone http://git@${gitBridgePublicHost}/git/${projectId}`
)
})
cy.findByRole('button', {

View file

@ -1,5 +1,7 @@
const hostAdminUrl = Cypress.env('ADMIN_CLIENT_URL') || 'http://host-admin'
export async function dockerCompose(cmd: string, ...args: string[]) {
return await fetchJSON(`http://host-admin/docker/compose/${cmd}`, {
return await fetchJSON(`${hostAdminUrl}/docker/compose/${cmd}`, {
method: 'POST',
body: JSON.stringify({
args,
@ -8,13 +10,13 @@ export async function dockerCompose(cmd: string, ...args: string[]) {
}
export async function mongoInit() {
return await fetchJSON('http://host-admin/mongo/init', {
return await fetchJSON(`${hostAdminUrl}/mongo/init`, {
method: 'POST',
})
}
export async function resetData() {
return await fetchJSON('http://host-admin/reset/data', {
return await fetchJSON(`${hostAdminUrl}/reset/data`, {
method: 'POST',
})
}
@ -25,7 +27,7 @@ export async function reconfigure({
vars = {},
withDataDir = false,
}) {
return await fetchJSON('http://host-admin/reconfigure', {
return await fetchJSON(`${hostAdminUrl}/reconfigure`, {
method: 'POST',
body: JSON.stringify({
pro,
@ -65,7 +67,7 @@ export async function runScript({
script: string
args?: string[]
}) {
return await fetchJSON('http://host-admin/run/script', {
return await fetchJSON(`${hostAdminUrl}/run/script`, {
method: 'POST',
body: JSON.stringify({
cwd,

View file

@ -11,7 +11,9 @@ const {
const YAML = require('js-yaml')
const PATHS = {
DOCKER_COMPOSE_FILE: 'docker-compose.yml',
DOCKER_COMPOSE_OVERRIDE: 'docker-compose.override.yml',
DOCKER_COMPOSE_NATIVE: 'docker-compose.native.yml',
DATA_DIR: Path.join(__dirname, 'data'),
SANDBOXED_COMPILES_HOST_DIR: Path.join(__dirname, 'data/compiles'),
}
@ -44,6 +46,17 @@ function writeDockerComposeOverride(cfg) {
fs.writeFileSync(PATHS.DOCKER_COMPOSE_OVERRIDE, YAML.dump(cfg))
}
function runDockerCompose(command, args, callback) {
const files = ['-f', PATHS.DOCKER_COMPOSE_FILE]
if (process.env.NATIVE_CYPRESS) {
files.push('-f', PATHS.DOCKER_COMPOSE_NATIVE)
}
if (fs.existsSync(PATHS.DOCKER_COMPOSE_OVERRIDE)) {
files.push('-f', PATHS.DOCKER_COMPOSE_OVERRIDE)
}
execFile('docker', ['compose', ...files, command, ...args], callback)
}
function purgeDataDir() {
fs.rmSync(PATHS.DATA_DIR, { recursive: true, force: true })
}
@ -58,7 +71,9 @@ app.use((req, res, next) => {
// Basic access logs
console.log(req.method, req.url, req.body)
// Add CORS headers
res.setHeader('Access-Control-Allow-Origin', 'http://sharelatex')
const accessControlAllowOrigin =
process.env.ACCESS_CONTROL_ALLOW_ORIGIN || 'http://sharelatex'
res.setHeader('Access-Control-Allow-Origin', accessControlAllowOrigin)
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
res.setHeader('Access-Control-Max-Age', '3600')
next()
@ -79,11 +94,9 @@ app.post(
(req, res) => {
const { cwd, script, args } = req.body
execFile(
'docker',
runDockerCompose(
'exec',
[
'compose',
'exec',
'sharelatex',
'bash',
'-c',
@ -204,24 +217,22 @@ app.post(
if (['stop', 'down'].includes(cmd)) {
mongoIsInitialized = false
}
execFile('docker', ['compose', cmd, ...args], (error, stdout, stderr) => {
runDockerCompose(cmd, args, (error, stdout, stderr) => {
res.json({ error, stdout, stderr })
})
}
)
function mongoInit(callback) {
execFile(
'docker',
['compose', 'up', '--detach', '--wait', 'mongo'],
runDockerCompose(
'up',
['--detach', '--wait', 'mongo'],
(error, stdout, stderr) => {
if (error) return callback(error, stdout, stderr)
execFile(
'docker',
runDockerCompose(
'exec',
[
'compose',
'exec',
'mongo',
'mongo',
'--eval',
@ -268,10 +279,9 @@ app.post(
const doMongoInit = mongoIsInitialized ? cb => cb() : mongoInit
doMongoInit((error, stdout, stderr) => {
if (error) return res.json({ error, stdout, stderr })
execFile(
'docker',
['compose', 'up', '--detach', '--wait', 'sharelatex'],
runDockerCompose(
'up',
['--detach', '--wait', 'sharelatex'],
(error, stdout, stderr) => {
res.json({ error, stdout, stderr })
}
@ -281,9 +291,9 @@ app.post(
)
app.post('/reset/data', (req, res) => {
execFile(
'docker',
['compose', 'stop', '--timeout=0', 'sharelatex'],
runDockerCompose(
'stop',
['--timeout=0', 'sharelatex'],
(error, stdout, stderr) => {
if (error) return res.json({ error, stdout, stderr })
@ -294,9 +304,9 @@ app.post('/reset/data', (req, res) => {
}
mongoIsInitialized = false
execFile(
'docker',
['compose', 'down', '--timeout=0', '--volumes', 'mongo', 'redis'],
runDockerCompose(
'down',
['--timeout=0', '--volumes', 'mongo', 'redis'],
(error, stdout, stderr) => {
res.json({ error, stdout, stderr })
}