diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dc83a81d2b421de89432d5d80756b977f740ce29..e62db0947ac41ed0eb629a4632b34dfc1dd88813 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ build: - docker:18.09.6-dind parallel: matrix: - - VERSION: [code, kube] + - VERSION: [code, kube, desktop] script: - ./build.sh $TAG $VERSION $CI_REGISTRY_IMAGE - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.e-biz.fr diff --git a/Dockerfile.desktop b/Dockerfile.desktop new file mode 100644 index 0000000000000000000000000000000000000000..23c2ddf46d9c9c3c7d54d62b1bdffb2edda0dc2d --- /dev/null +++ b/Dockerfile.desktop @@ -0,0 +1,32 @@ +FROM node:alpine3.15 + +RUN apk update +RUN apk --no-cache add vim && apk --no-cache add nano \ + && apk --no-cache add rsync && apk --no-cache add sudo \ + && apk --no-cache add bash && apk --no-cache add openssh \ + && apk --no-cache add git && apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python + +## User account +RUN addgroup -S sudo && adduser --disabled-password --gecos '' deadlock && \ + adduser deadlock sudo && \ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + + +COPY setup_trace_desktop.py setup_trace.py +RUN chmod 700 setup_trace.py +RUN chown deadlock setup_trace.py + +COPY recorder-out deadlock/ +COPY .gitignore_recorder deadlock/.gitignore + + + +COPY start.desktop.sh . +RUN chmod 504 deadlock/ -R +RUN chmod 500 start.desktop.sh + +RUN mkdir /project && mkdir /tmp/.ssh && mkdir /home/deadlock/mission + +RUN chown deadlock:deadlock /home/deadlock + +ENTRYPOINT ["bash", "start.desktop.sh"] \ No newline at end of file diff --git a/deadlock-plugins/deadlock-extension/package-lock.json b/deadlock-plugins/deadlock-extension/package-lock.json index b295b7667c31cb60e1d9f701b2cefc4ce3da03cb..e5b42ab7f5b342f005434b4e50b8fa5c6b742f38 100644 --- a/deadlock-plugins/deadlock-extension/package-lock.json +++ b/deadlock-plugins/deadlock-extension/package-lock.json @@ -37,7 +37,7 @@ "webpack-cli": "^4.9.1" }, "engines": { - "vscode": "^1.63.0" + "vscode": "^1.66.0" } }, "node_modules/@babel/code-frame": { diff --git a/deadlock-plugins/deadlock-extension/src/core/config.ts b/deadlock-plugins/deadlock-extension/src/core/config.ts index 629d89ddb3183a72bfab6d8bb97bd6e15fc91049..7222a295001d60f5bb9c7068efd7b7ecb324a3e5 100644 --- a/deadlock-plugins/deadlock-extension/src/core/config.ts +++ b/deadlock-plugins/deadlock-extension/src/core/config.ts @@ -3,17 +3,17 @@ import * as path from 'path'; const homeDir = os.homedir(); // if we are on container, means the directory will depend differently -const onContainer = homeDir.includes('theia') || homeDir.includes('root'); +const onContainer = homeDir.includes('theia') || homeDir.includes('root') || homeDir.includes('deadlock'); const deadlockExtensionPath = path.join(homeDir, 'deadlock-extension'); export const PROJECT_SRC_PATH = onContainer ? '/project' : path.join(homeDir, 'deadlock-extension', '/project'); -export const PROJECT_THEIA_PATH = onContainer - ? path.join('/home/project') +export const PROJECT_DEADLOCK_DESKTOP_PATH = onContainer + ? path.join('/home/deadlock/mission') : path.join(deadlockExtensionPath, 'project-theia'); -export const DOCS_PATH = path.join(path.join(onContainer ? '/home/theia' : deadlockExtensionPath), 'docs'); +export const DOCS_PATH = path.join(path.join(onContainer ? '/home/deadlock' : deadlockExtensionPath), 'docs'); export const CONFIG_PATH = onContainer ? '/home/config/' : path.join(deadlockExtensionPath, 'config'); @@ -21,8 +21,8 @@ export const USER_CHALLENGE_PATH = path.join(CONFIG_PATH, 'user-challenge.json') export const BRIEFING_FILE_NAME = 'briefing.md'; -export const ENV_FILE_PATH = path.join(PROJECT_THEIA_PATH, '/.env'); +export const ENV_FILE_PATH = path.join(PROJECT_DEADLOCK_DESKTOP_PATH, '/.env'); export const BASHRC_PATH = path.join(homeDir, '/.bashrc'); -export const SERVICES_PATHS_PATH = path.join(PROJECT_THEIA_PATH, '/paths.json'); +export const SERVICES_PATHS_PATH = path.join(PROJECT_DEADLOCK_DESKTOP_PATH, '/paths.json'); diff --git a/deadlock-plugins/deadlock-extension/src/core/gitMission.ts b/deadlock-plugins/deadlock-extension/src/core/gitMission.ts index 9e739afc67856fa5f0f13e735acde4d5e2f4554a..d56b5086350b026af42fae51c86489bc6ced088e 100644 --- a/deadlock-plugins/deadlock-extension/src/core/gitMission.ts +++ b/deadlock-plugins/deadlock-extension/src/core/gitMission.ts @@ -47,6 +47,9 @@ export default class GitMission { console.log('Init Git mission..'); const remote = await this.readRemote(); + + //TODO: REMOVE + console.log('After finish readremote..'); if (remote === DEFAULT_REMOTE) { return Promise.resolve(this); } diff --git a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts b/deadlock-plugins/deadlock-extension/src/core/userConfig.ts index 46295519cf5a44668fabe677467787ecbfd7276e..da50d104cf84ef2e34792ee93f17e91c5d352e51 100644 --- a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts +++ b/deadlock-plugins/deadlock-extension/src/core/userConfig.ts @@ -1,3 +1,4 @@ +import { log } from './../recorder/utils'; /** * Example: * { diff --git a/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts b/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts index 17865f4da95b95c0572a67cbb59456bb0fb82657..99dbc5213f5a45d31760fca026d719aba6066c84 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts @@ -47,7 +47,7 @@ export default class CommandRecorder { let lastLineIndexWatched = 0; setInterval(() => { try { - const trace = fs.readFileSync('/home/theia/.bash_history', 'utf8'); + const trace = fs.readFileSync('/home/deadlock/.bash_history', 'utf8'); const lines = trace.split(/\r?\n/); this.commandsInProgress.forEach((command) => (command.still = false)); diff --git a/deadlock-plugins/deadlock-extension/src/recorder/index.ts b/deadlock-plugins/deadlock-extension/src/recorder/index.ts index 51f4a3a41cd3a2804c1ac81a2e2b5f5c15efbb72..32d9225b38373083ec62481e933fa014ca6dfa4b 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/index.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/index.ts @@ -1,7 +1,7 @@ import CommandRecorder from './command-recorder'; import GitMission from '../core/gitMission'; import UserConfigNode from './userConfigNode'; -import { PROJECT_SRC_PATH, PROJECT_THEIA_PATH } from '../core/config'; +import { PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH } from '../core/config'; import { copyProjectSources, clearFilesExceptGit, log, error, renameTempToUserGitFiles } from './utils'; import UserConfig from '../core/userConfig'; @@ -10,10 +10,10 @@ export default class Recorder { log('Setup user project..'); if (!userConfig.isProfessor()) { - await copyProjectSources(PROJECT_SRC_PATH, PROJECT_THEIA_PATH, ['.git/']); + await copyProjectSources(PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH, ['.git/']); if (gitMission) { - renameTempToUserGitFiles(PROJECT_THEIA_PATH, gitMission.author); + renameTempToUserGitFiles(PROJECT_DEADLOCK_DESKTOP_PATH, gitMission.author); log('Starting CommandRecorder..'); new CommandRecorder(gitMission).run(); @@ -21,7 +21,7 @@ export default class Recorder { error('Cannot start command recorder, gitMission not found'); } } else { - await copyProjectSources(PROJECT_SRC_PATH, PROJECT_THEIA_PATH); + await copyProjectSources(PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH); } } diff --git a/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts b/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts index e3154055e67b1b1a0d13521cc58a7c7891aac31e..081c4bded0b0982b05926d77e896a9ffb2b56727 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts @@ -1,6 +1,6 @@ import UserConfigNode from './userConfigNode'; import GitMission from '../core/gitMission'; -import { PROJECT_SRC_PATH, PROJECT_THEIA_PATH } from '../core/config'; +import { PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH } from '../core/config'; import { log, error, commitAndPushCode, CommitFrom } from './utils'; const util = require('util'); @@ -10,13 +10,13 @@ async function containsDiff() { try { // https://man7.org/linux/man-pages/man1/diff.1.html // Exit status is 0 if inputs are the same, 1 if different, 2 if trouble. - await exec(`diff -qr ${PROJECT_SRC_PATH} ${PROJECT_THEIA_PATH}`); + await exec(`diff -qr ${PROJECT_SRC_PATH} ${PROJECT_DEADLOCK_DESKTOP_PATH}`); // When status code is 0 exec does not fail } catch (result) { // when status code is > 0 if (result.code === 1) { const stdout = result.stdout; - if (stdout.indexOf('Files ') !== -1 || stdout.indexOf('Only in /home/project/') !== -1) { + if (stdout.indexOf('Files ') !== -1 || stdout.indexOf('Only in /home/deadlock/') !== -1) { // if user created new file or added a directory return true; } diff --git a/deadlock-plugins/deadlock-extension/src/recorder/utils.ts b/deadlock-plugins/deadlock-extension/src/recorder/utils.ts index cc271f3f93a3efba58d1b43ba020581c0f1f417e..77553de4f03e56a6f2c4f249d48a8598a1d7d93c 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/utils.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/utils.ts @@ -1,5 +1,5 @@ import GitMission from '../core/gitMission'; -import { PROJECT_SRC_PATH, PROJECT_THEIA_PATH } from '../core/config'; +import { PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH } from '../core/config'; import { format } from 'date-fns'; import { execSync } from 'child_process'; import { existsSync, renameSync, copyFileSync, PathLike } from 'fs'; @@ -29,9 +29,15 @@ export const error = (message: any, ...args: any[]) => { } }; -export async function copyProjectSources(srcPath: string, theiaPath: string, excludes: Array<string> = []) { +export async function copyProjectSources( + srcPath: string, + userMissionWorkdirPath: string, + excludes: Array<string> = [], +) { const excludeCmd = excludes.map((current) => `--exclude ${current}`).join(' '); - return exec(`rsync -a ${srcPath}/ ${theiaPath} ${excludeCmd} && chown -R theia:theia /home/project`); + return exec( + `rsync -a ${srcPath}/ ${userMissionWorkdirPath} ${excludeCmd} && chown -R deadlock:deadlock /home/deadlock`, + ); } export async function pathContainsFiles(path: string) { @@ -111,9 +117,9 @@ export async function commitAndPushCode(gitMission: GitMission, from: CommitFrom log('Commit & push'); await clearFilesExceptGit(PROJECT_SRC_PATH); - copyGitUserFiles(PROJECT_THEIA_PATH, PROJECT_SRC_PATH, gitMission.author); + copyGitUserFiles(PROJECT_DEADLOCK_DESKTOP_PATH, PROJECT_SRC_PATH, gitMission.author); execSync( - `rsync -r --exclude .git --exclude npm --exclude target ${PROJECT_THEIA_PATH}/* ${PROJECT_SRC_PATH} && cp ${Path.join( + `rsync -r --exclude .git --exclude npm --exclude target ${PROJECT_DEADLOCK_DESKTOP_PATH}/* ${PROJECT_SRC_PATH} && cp ${Path.join( __dirname, '.gitignore', )} ${PROJECT_SRC_PATH} && chown -R root:root /project`, diff --git a/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts b/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts index 0c09a3432b10756053286f85229c1f4adc17b138..26a90fbb943c452938ea79a3208ad63a381b7c5e 100644 --- a/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts +++ b/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts @@ -28,42 +28,42 @@ export default class QuickSetupView extends WebviewBase { render(): string { return ` - <head> - ${this.renderHeaderHtml()} - </head> - <body> - ${this.renderHtmlBody()} - </body> - `; + <head> + ${this.renderHeaderHtml()} + </head> + <body> + ${this.renderHtmlBody()} + </body> + `; } renderHtmlBody() { const hadMissionWorkdir = this.extensionStore.getMissionWorkdir() !== undefined; return ` - <h1>Quick Setup</h1> - <div class="deadlock-getting-started-card-container"> + <h1>Quick Setup</h1> + <div class="deadlock-getting-started-card-container"> - ${this.renderCardHtml( - 'Connexion à Deadlock', - "Tu as besoin d'être connecté à Deadlock pour continuer.", - { name: 'Se connecter', onClickFunctionName: 'openAuthenticationPageAction' }, - this._isAlreadyConnected, - this._isAlreadyConnected, - )} - ${this.renderCardHtml( - 'Dossier contenant tes exercices', - 'Choisis le dossier qui contiendra tous les exercices Deadlock.', - { - name: 'Choisir un dossier', - onClickFunctionName: 'launchChooseMissionWorkdirAction', - }, - hadMissionWorkdir, - )} - </div> - - - `; + ${this.renderCardHtml( + 'Connexion à Deadlock', + "Tu as besoin d'être connecté à Deadlock pour continuer.", + { name: 'Se connecter', onClickFunctionName: 'openAuthenticationPageAction' }, + this._isAlreadyConnected, + this._isAlreadyConnected, + )} + ${this.renderCardHtml( + 'Dossier contenant tes exercices', + 'Choisis le dossier qui contiendra tous les exercices Deadlock.', + { + name: 'Choisir un dossier', + onClickFunctionName: 'launchChooseMissionWorkdirAction', + }, + hadMissionWorkdir, + )} + </div> + + + `; } renderCardHtml( @@ -75,22 +75,22 @@ export default class QuickSetupView extends WebviewBase { callbackArgs?: string, ) { return ` - <div class="deadlock-getting-started-card"> - <vscode-checkbox ${isChecked ? 'checked' : ''} readonly> </vscode-checkbox> - <div class="card-body"> - <div class="card-title"> - ${title} - </div> - <div class="card-description"> - ${description} - </div> - <vscode-button ${isDisabled ? 'disabled' : ''} onclick="${button.onClickFunctionName}(${callbackArgs})">${ - button.name - }</vscode-button> - </div> - </div> - - `; + <div class="deadlock-getting-started-card"> + <vscode-checkbox ${isChecked ? 'checked' : ''} readonly> </vscode-checkbox> + <div class="card-body"> + <div class="card-title"> + ${title} + </div> + <div class="card-description"> + ${description} + </div> + <vscode-button ${isDisabled ? 'disabled' : ''} onclick="${ + button.onClickFunctionName + }(${callbackArgs})">${button.name}</vscode-button> + </div> + </div> + + `; } renderHeaderHtml() { @@ -111,11 +111,11 @@ export default class QuickSetupView extends WebviewBase { const customScript = this.getExternalRessourcePath(this.extensionUri, ['resources', 'js', 'gettingStartedView.js']); return ` - <meta charset="UTF-8"> - <script type="module" src="${toolkitUri}"></script> - <script type="text/javascript" src="${customScript}"></script> - <link href="${customStyle}" rel="stylesheet" /> - `; + <meta charset="UTF-8"> + <script type="module" src="${toolkitUri}"></script> + <script type="text/javascript" src="${customScript}"></script> + <link href="${customStyle}" rel="stylesheet" /> + `; } onMessageReceive(message: any): void { diff --git a/setup_trace_desktop.py b/setup_trace_desktop.py new file mode 100644 index 0000000000000000000000000000000000000000..80f70c3c9d60d86bda52a33a14a72ccac9379fae --- /dev/null +++ b/setup_trace_desktop.py @@ -0,0 +1,12 @@ + +open('/home/deadlock/.bash_history', 'a').close() + +bashrc = open('/home/deadlock/.bashrc', 'a') +bashrc.write('\n') +bashrc.write('HISTCONTROL=""') +bashrc.write('\n') +bashrc.write("PROMPT_COMMAND='history -a'") +bashrc.write('\n') + +# Close the file +bashrc.close() \ No newline at end of file diff --git a/start.desktop.sh b/start.desktop.sh new file mode 100644 index 0000000000000000000000000000000000000000..9b14acbd80b16aa06a51223f66bf91da580bd2fe --- /dev/null +++ b/start.desktop.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +ON_START_UP_FILE="/deadlock/startup.sh" +TAG="[DEADLOCK]" + +# setup ssh key for root user +# must be installed by the API first within /tmp/.ssh +mkdir ~/.ssh +cp /tmp/.ssh/* ~/.ssh/ + +# start init mission script if exists +if [ -f "$ON_START_UP_FILE" ]; then + echo + echo "$TAG Startup your script.." + echo + /bin/bash $ON_START_UP_FILE & +else + echo + echo "$TAG No startup script found." + echo +fi + + +su deadlock -c "python setup_trace.py" +rm setup_trace.py + + +trap "node deadlock/preStop.js" SIGTERM + +# start command recorder +node deadlock/recorder.js & + +echo "WELCOME TO DEADLOCK CHALLENGE" + +child=$! +wait "$child" + + + + + + +