From 017ba3a4ece03788dd9950daa2f613bf73a0a623 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 13 Feb 2018 12:05:10 +0000 Subject: [PATCH] mvp needs hacked pacth in docker runner wip most tests pass --- .gitignore | 1 + Dockerfile | 16 +- Jenkinsfile | 36 +- Makefile | 5 + app/coffee/CommandRunner.coffee | 2 + app/coffee/CompileController.coffee | 3 + app/coffee/CompileManager.coffee | 12 +- app/coffee/LatexRunner.coffee | 1 + app/coffee/OutputFileFinder.coffee | 2 - app/coffee/ResourceWriter.coffee | 1 + bin/synctex | Bin 0 -> 90472 bytes config/settings.defaults.coffee | 3 + docker-compose.ci.yml | 10 +- docker-compose.yml | 8 +- docker-runner | 2 +- package-lock.json | 4702 ++++++++++------- package.json | 112 +- .../coffee/ExampleDocumentTests.coffee | 3 +- test/acceptance/coffee/helpers/Client.coffee | 1 + 19 files changed, 3008 insertions(+), 1912 deletions(-) create mode 100755 bin/synctex diff --git a/.gitignore b/.gitignore index 99e9760..476f2d1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ cache db.sqlite config/* bin/synctex +npm-debug.log diff --git a/Dockerfile b/Dockerfile index d98547c..83e452d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,17 +2,21 @@ FROM node:6.9.5 RUN wget -qO- https://get.docker.com/ | sh -# ---- Copy Files/Build ---- -WORKDIR /app +run apt-get install poppler-utils vim ghostscript --yes + +# run git build-essential --yes +# RUN git clone https://github.com/netblue30/firejail.git +# RUN cd firejail && ./configure && make && make install-strip +# run mkdir /data + COPY ./ /app -# Build react/vue/angular bundle static files -# RUN npm run build + +WORKDIR /app + RUN npm install RUN npm run compile -EXPOSE 3013 - ENV SHARELATEX_CONFIG /app/config/settings.production.coffee ENV NODE_ENV production diff --git a/Jenkinsfile b/Jenkinsfile index ab90aaa..bc9ba01 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,34 +9,9 @@ pipeline { } stages { - stage('Install') { - agent { - docker { - image 'node:6.9.5' - args "-v /var/lib/jenkins/.npm:/tmp/.npm -e HOME=/tmp" - reuseNode true - } - } + stage('Build') { steps { - // we need to disable logallrefupdates, else git clones - // during the npm install will require git to lookup the - // user id which does not exist in the container's - // /etc/passwd file, causing the clone to fail. - sh 'git config --global core.logallrefupdates false' - sh 'rm -rf node_modules' - sh 'npm install && npm rebuild' - } - } - - stage('Compile') { - agent { - docker { - image 'node:6.9.5' - reuseNode true - } - } - steps { - sh 'npm run compile:all' + sh 'make build' } } @@ -54,12 +29,7 @@ pipeline { stage('Package and publish build') { steps { - sh 'echo ${BUILD_NUMBER} > build_number.txt' - sh 'touch build.tar.gz' // Avoid tar warning about files changing during read - sh 'tar -czf build.tar.gz --exclude=build.tar.gz --exclude-vcs .' - withAWS(credentials:'S3_CI_BUILDS_AWS_KEYS', region:"${S3_REGION_BUILD_ARTEFACTS}") { - s3Upload(file:'build.tar.gz', bucket:"${S3_BUCKET_BUILD_ARTEFACTS}", path:"${JOB_NAME}/${BUILD_NUMBER}.tar.gz") - } + sh 'make publish' } } diff --git a/Makefile b/Makefile index 6407885..6e7fca5 100644 --- a/Makefile +++ b/Makefile @@ -25,5 +25,10 @@ test_acceptance: test_clean # clear the database before each acceptance test run test_clean: $(DOCKER_COMPOSE) down +build: + docker build --pull --tag quay.io/sharelatex/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) . + +publish: + docker push quay.io/sharelatex/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) .PHONY: clean test test_unit test_acceptance test_clean build publish diff --git a/app/coffee/CommandRunner.coffee b/app/coffee/CommandRunner.coffee index f47af00..969b55f 100644 --- a/app/coffee/CommandRunner.coffee +++ b/app/coffee/CommandRunner.coffee @@ -5,7 +5,9 @@ logger.info "using standard command runner" module.exports = CommandRunner = run: (project_id, command, directory, image, timeout, environment, callback = (error) ->) -> + console.log("Command runner", directory) command = (arg.replace('$COMPILE_DIR', directory) for arg in command) + console.log("Command runner 2", command) logger.log project_id: project_id, command: command, directory: directory, "running command" logger.warn "timeouts and sandboxing are not enabled with CommandRunner" diff --git a/app/coffee/CompileController.coffee b/app/coffee/CompileController.coffee index 99973fd..52c0e14 100644 --- a/app/coffee/CompileController.coffee +++ b/app/coffee/CompileController.coffee @@ -34,11 +34,14 @@ module.exports = CompileController = status = "error" code = 500 logger.error err: error, project_id: request.project_id, "error running compile" + else status = "failure" for file in outputFiles if file.path?.match(/output\.pdf$/) status = "success" + if status == "failure" + logger.err project_id: request.project_id, outputFiles:outputFiles, "project failed to compile successfully, no output.pdf generated" timer.done() res.status(code or 200).send { diff --git a/app/coffee/CompileManager.coffee b/app/coffee/CompileManager.coffee index 167a80e..d3d319a 100644 --- a/app/coffee/CompileManager.coffee +++ b/app/coffee/CompileManager.coffee @@ -41,6 +41,7 @@ module.exports = CompileManager = doCompile: (request, callback = (error, outputFiles) ->) -> compileDir = getCompileDir(request.project_id, request.user_id) + console.log("doCompile",compileDir ) timer = new Metrics.Timer("write-to-disk") logger.log project_id: request.project_id, user_id: request.user_id, "syncing resources to disk" @@ -206,9 +207,14 @@ module.exports = CompileManager = file_path = base_dir + "/" + file_name compileDir = getCompileDir(project_id, user_id) synctex_path = Path.join(compileDir, "output.pdf") - CompileManager._runSynctex ["code", synctex_path, file_path, line, column], (error, stdout) -> + command = ["code", synctex_path, file_path, line, column] + CompileManager._runSynctex command, (error, stdout) -> return callback(error) if error? - logger.log project_id: project_id, user_id:user_id, file_name: file_name, line: line, column: column, stdout: stdout, "synctex code output" + if stdout.toLowerCase().indexOf("warning") == -1 + logType = "log" + else + logType = "err" + logger[logType] project_id: project_id, user_id:user_id, file_name: file_name, line: line, column: column, command:command, stdout: stdout, "synctex code output" callback null, CompileManager._parseSynctexFromCodeOutput(stdout) syncFromPdf: (project_id, user_id, page, h, v, callback = (error, filePositions) ->) -> @@ -216,6 +222,7 @@ module.exports = CompileManager = base_dir = Settings.path.synctexBaseDir(compileName) compileDir = getCompileDir(project_id, user_id) synctex_path = Path.join(compileDir, "output.pdf") + logger.log({base_dir, project_id, synctex_path}, "base diiir") CompileManager._runSynctex ["pdf", synctex_path, page, h, v], (error, stdout) -> return callback(error) if error? logger.log project_id: project_id, user_id:user_id, page: page, h: h, v:v, stdout: stdout, "synctex pdf output" @@ -243,6 +250,7 @@ module.exports = CompileManager = return callback(error) if error? if Settings.clsi?.synctexCommandWrapper? [bin_path, args] = Settings.clsi?.synctexCommandWrapper bin_path, args + logger.log({bin_path, args}, "synctex being run") child_process.execFile bin_path, args, timeout: 10 * seconds, (error, stdout, stderr) -> if error? logger.err err:error, args:args, "error running synctex" diff --git a/app/coffee/LatexRunner.coffee b/app/coffee/LatexRunner.coffee index 6a5a4f6..11e71e5 100644 --- a/app/coffee/LatexRunner.coffee +++ b/app/coffee/LatexRunner.coffee @@ -8,6 +8,7 @@ ProcessTable = {} # table of currently running jobs (pids or docker container n module.exports = LatexRunner = runLatex: (project_id, options, callback = (error) ->) -> + console.log("LatexRunner", options.directory) {directory, mainFile, compiler, timeout, image, environment} = options compiler ||= "pdflatex" timeout ||= 60000 # milliseconds diff --git a/app/coffee/OutputFileFinder.coffee b/app/coffee/OutputFileFinder.coffee index 4b07f6e..662440b 100644 --- a/app/coffee/OutputFileFinder.coffee +++ b/app/coffee/OutputFileFinder.coffee @@ -10,8 +10,6 @@ module.exports = OutputFileFinder = for resource in resources incomingResources[resource.path] = true - logger.log directory: directory, "getting output files" - OutputFileFinder._getAllFiles directory, (error, allFiles = []) -> if error? logger.err err:error, "error finding all output files" diff --git a/app/coffee/ResourceWriter.coffee b/app/coffee/ResourceWriter.coffee index 0b6aef5..66cfbfa 100644 --- a/app/coffee/ResourceWriter.coffee +++ b/app/coffee/ResourceWriter.coffee @@ -109,6 +109,7 @@ module.exports = ResourceWriter = callback() _writeResourceToDisk: (project_id, resource, basePath, callback = (error) ->) -> + console.log("_writeResourceToDisk", basePath, resource.path) ResourceWriter.checkPath basePath, resource.path, (error, path) -> return callback(error) if error? mkdirp Path.dirname(path), (error) -> diff --git a/bin/synctex b/bin/synctex new file mode 100755 index 0000000000000000000000000000000000000000..99044b97a0259b30afbf0bfb34365e4f1270479e GIT binary patch literal 90472 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:nwe6m+2D>* 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", + }, + "author": "James Allen ", "dependencies": { - "async": "0.2.9", - "body-parser": "^1.2.0", - "dockerode": "^2.5.3", - "express": "^4.2.0", - "fs-extra": "^0.16.3", - "grunt-mkdir": "^1.0.0", - "heapdump": "^0.3.5", - "lockfile": "^1.0.3", - "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#v1.5.4", - "lynx": "0.0.11", - "metrics-sharelatex": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.5.0", - "mkdirp": "0.3.5", - "mysql": "2.6.2", - "request": "^2.21.0", - "sequelize": "^2.1.3", - "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0", - "smoke-test-sharelatex": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#v0.2.0", - "sqlite3": "~3.1.8", - "underscore": "^1.8.2", - "v8-profiler": "^5.2.4", + "async": "0.2.9", + "body-parser": "^1.2.0", + "dockerode": "^2.5.3", + "express": "^4.2.0", + "fs-extra": "^0.16.3", + "grunt-mkdir": "^1.0.0", + "heapdump": "^0.3.5", + "lockfile": "^1.0.3", + "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#v1.5.4", + "lynx": "0.0.11", + "metrics-sharelatex": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.5.0", + "mkdirp": "0.3.5", + "mysql": "2.6.2", + "request": "^2.21.0", + "sequelize": "^2.1.3", + "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0", + "smoke-test-sharelatex": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#v0.2.0", + "sqlite3": "~3.1.8", + "underscore": "^1.8.2", + "v8-profiler": "^5.2.4", "wrench": "~1.5.4" - }, + }, "devDependencies": { - "mocha": "1.10.0", - "coffee-script": "1.6.0", - "chai": "~1.8.1", - "sinon": "~1.7.3", - "grunt": "~0.4.2", - "grunt-contrib-coffee": "~0.7.0", - "grunt-contrib-clean": "~0.5.0", - "grunt-shell": "~0.6.1", - "grunt-mocha-test": "~0.8.1", - "sandboxed-module": "~0.3.0", - "timekeeper": "0.0.4", - "grunt-execute": "^0.1.5", - "bunyan": "^0.22.1", + "mocha": "^4.0.1", + "coffee-script": "1.6.0", + "chai": "~1.8.1", + "sinon": "~1.7.3", + "grunt": "~0.4.2", + "grunt-contrib-coffee": "~0.7.0", + "grunt-contrib-clean": "~0.5.0", + "grunt-shell": "~0.6.1", + "grunt-mocha-test": "~0.8.1", + "sandboxed-module": "~0.3.0", + "timekeeper": "0.0.4", + "grunt-execute": "^0.1.5", + "bunyan": "^0.22.1", "grunt-bunyan": "^0.5.0" } } diff --git a/test/acceptance/coffee/ExampleDocumentTests.coffee b/test/acceptance/coffee/ExampleDocumentTests.coffee index 4d431c2..e9a58b5 100644 --- a/test/acceptance/coffee/ExampleDocumentTests.coffee +++ b/test/acceptance/coffee/ExampleDocumentTests.coffee @@ -11,7 +11,8 @@ try catch e convertToPng = (pdfPath, pngPath, callback = (error) ->) -> - convert = ChildProcess.exec "convert #{fixturePath(pdfPath)} #{fixturePath(pngPath)}" + command = "convert #{fixturePath(pdfPath)} #{fixturePath(pngPath)}" + convert = ChildProcess.exec command stdout = "" convert.stdout.on "data", (chunk) -> console.log "STDOUT", chunk.toString() convert.stderr.on "data", (chunk) -> console.log "STDERR", chunk.toString() diff --git a/test/acceptance/coffee/helpers/Client.coffee b/test/acceptance/coffee/helpers/Client.coffee index 7663496..546c235 100644 --- a/test/acceptance/coffee/helpers/Client.coffee +++ b/test/acceptance/coffee/helpers/Client.coffee @@ -31,6 +31,7 @@ module.exports = Client = express = require("express") app = express() app.use express.static(directory) + console.log("starting test server on", port, host) app.listen(port, host).on "error", (error) -> console.error "error starting server:", error.message process.exit(1)