Skip to content

Commit

Permalink
fix(job): fix job socket events
Browse files Browse the repository at this point in the history
  • Loading branch information
jkuri committed Aug 4, 2017
1 parent 5dd7698 commit 788517f
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 45 deletions.
14 changes: 10 additions & 4 deletions src/api/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ export function startBuildProcess(buildId: number, jobId: number,
commands = commands.filter(cmd => !cmd.startsWith('export'));

startContainer(name, image, vars)
.concat(ssh ? executeInContainer(name, 'sudo /etc/init.d/ssh start') : null)
.concat(ssh ? getContainerExposedPort(name, 22) : null)
.concat(ssh ? executeInContainer(name, 'sudo /etc/init.d/ssh start') : Observable.empty())
.concat(ssh ? getContainerExposedPort(name, 22) : Observable.empty())
.concat(...commands.map(command => executeInContainer(name, command)))
.subscribe((event: ProcessOutput) => {
observer.next(event);
Expand All @@ -57,9 +57,14 @@ export function startBuildProcess(buildId: number, jobId: number,

function executeInContainer(name: string, command: string): Observable<ProcessOutput> {
return new Observable(observer => {
const start = nodePty.spawn('docker', ['start', name]);
const start = nodePty.spawn('docker', ['start', name], { name: 'xterm-color' });

start.on('exit', startCode => {
if (startCode !== 0) {
observer.error(bold(red('Container errored with exit code ' + startCode)));
}


start.on('exit', () => {
let exitCode = 255;
let executed = false;
let attach = null;
Expand All @@ -81,6 +86,7 @@ function executeInContainer(name: string, command: string): Observable<ProcessOu
exitCode = 0;
attach.write(detachKey ? detachKey : 'exit $?\r');
} else if (data.includes('EXECNOK')) {
observer.error(red(`Last executed command returned error.`));
attach.write(detachKey ? detachKey : 'exit $?\r');
} else if (!data.includes(command) && !data.includes('exit $?') &&
!data.includes('logout') && !data.includes('read escape sequence')) {
Expand Down
7 changes: 7 additions & 0 deletions src/app/assets/public/images/icons/ssh.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 17 additions & 10 deletions src/app/components/app-job/app-job.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
<div class="build-top-container" [ngClass]="{ green: job?.status === 'success', yellow: job?.status === 'running', red: job?.status === 'failed' }">
<div class="build-top-content">
<div class="columns is-multiline">
<div class="column is-2">
<div class="column is-7">
<h1 class="bold">
<span><a [routerLink]="['/repo', job?.build.repository.id]">{{ job?.build.head_full_name }}</a></span>
<span><a [routerLink]="['/repo', job?.build?.repository?.id]">{{ job?.build?.head_full_name }}</a></span>
<span class="build-icon">
<img src="images/icons/clock.svg" *ngIf="job?.status === 'queued'">
<img src="images/icons/flickr.svg" *ngIf="job?.status === 'running'">
Expand All @@ -24,9 +24,6 @@ <h1 class="bold">
</span>
</h1>
</div>
<div class="column is-5">
<code *ngIf="sshd" class="ssh">ssh {{ sshd.split(':')[0] }} -p {{ sshd.split(':')[1] }} -l abstruse</code>
</div>
<div class="column is-5 justify-end right-buttons-top">
<button class="button is-fullwidth" name="btn-restart-ssh" type="button" (click)="restartJobWithSSH($event)" [disabled]="processing">
<div class="centered">
Expand Down Expand Up @@ -57,23 +54,23 @@ <h1 class="bold">
<hr/>

<div class="column is-3">
<h2>{{ job?.build.message }}</h2>
<h2>{{ job?.build?.message }}</h2>
</div>
<div class="column is-3">
<p>
<span class="icon">
<img src="images/icons/git-commit.svg">
</span>
<span *ngIf="job?.build.head_sha">{{ job?.build.head_sha.slice(0, 7) }}</span>
<span *ngIf="!job?.build.head_sha">{{ job?.build.sha.slice(0, 7) }}</span>
<span *ngIf="job?.build?.head_sha">{{ job?.build?.head_sha.slice(0, 7) }}</span>
<span *ngIf="!job?.build?.head_sha">{{ job?.build?.sha.slice(0, 7) }}</span>
</p>
</div>
<div class="column is-4">
<p>
<span class="icon">
<img [src]="job?.build.head_user_avatar_url" class="avatar-img">
<img [src]="job?.build?.head_user_avatar_url" class="avatar-img">
</span>
<span>{{ job?.build.author }} commited {{ timeWords }} ago</span>
<span>{{ job?.build?.author }} commited {{ timeWords }} ago</span>
</p>
</div>
<div class="column is-2">
Expand All @@ -88,6 +85,16 @@ <h2>{{ job?.build.message }}</h2>
</div>
</div>
</div>
<div class="column is-12" *ngIf="sshd">
<div class="ssh-container">
<span class="icon">
<img src="images/icons/ssh.svg">
</span>
<span>SSH Daemon is enabled in this container.</span>
<code>ssh {{ sshd.split(':')[0] }} -p {{ sshd.split(':')[1] }} -l abstruse</code>
<code>password: abstruse</code>
</div>
</div>
<div class="column is-12">
<app-terminal [data]="terminalInput" (outputData)="terminalOutput($event)" [options]="terminalOptions"></app-terminal>
</div>
Expand Down
70 changes: 39 additions & 31 deletions src/app/components/app-job/app-job.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,44 @@ export class AppJobComponent implements OnInit, OnDestroy {
this.loading = true;
this.status = 'queued';
this.terminalOptions = { size: 'large' };
this.id = null;
}

ngOnInit() {
this.termSub = this.socketService.outputEvents
.subscribe(event => {
if (event.type === 'data') {
this.ngZone.run(() => this.terminalInput = event.data);
} else if (event.type === 'jobStopped' && event.data === this.id) {
this.processing = false;
} else if (event.type === 'jobRestarted' && event.data === this.id) {
this.processing = false;
} else if (event.type === 'exposedPort') {
this.sshd = `${document.location.hostname}:${event.data}`;
}
});

this.sub = this.socketService.outputEvents
.filter(event => event.type === 'process')
.filter(event => event.job_id === parseInt(<any>this.id, 10))
.subscribe(event => {
if (!this.job) {
return;
}

if (event.data === 'jobStarted') {
this.job.status = 'running';
this.job.end_time = null;
this.job.start_time = new Date().getTime();
} else if (event.data === 'jobSucceded') {
this.job.status = 'success';
this.job.end_time = new Date().getTime();
} else if (event.data == 'jobFailed') {
this.job.status = 'failed';
this.job.end_time = new Date().getTime();
}
});

this.route.params.subscribe(params => {
this.id = params.id;

Expand All @@ -48,42 +83,12 @@ export class AppJobComponent implements OnInit, OnDestroy {
this.timeWords = distanceInWordsToNow(job.build.start_time);
this.loading = false;

this.termSub = this.socketService.outputEvents
.subscribe(event => {
if (event.type === 'data') {
this.ngZone.run(() => this.terminalInput = event.data);
} else if (event.type === 'jobStopped' && event.data === this.id) {
this.processing = false;
} else if (event.type === 'jobRestarted' && event.data === this.id) {
this.processing = false;
} else if (event.type === 'exposedPort') {
this.sshd = `${document.location.hostname}:${event.data}`;
}
});

this.socketService.emit({ type: 'subscribeToJobOutput', data: { jobId: this.id } });

this.updateJobTime();
setInterval(() => this.updateJobTime(), 1000);

this.sub = this.socketService.outputEvents
.filter(event => event.type === 'process')
.filter(event => event.job_id === parseInt(<any>this.id, 10))
.subscribe(event => {
if (event.data === 'jobStarted') {
job.status = 'running';
job.end_time = null;
job.start_time = new Date().getTime();
} else if (event.data === 'jobSucceded') {
job.status = 'success';
job.end_time = new Date().getTime();
} else if (event.data == 'jobFailed') {
job.status = 'failed';
job.end_time = new Date().getTime();
}
});
});
});
});
}

ngOnDestroy() {
Expand All @@ -105,6 +110,7 @@ export class AppJobComponent implements OnInit, OnDestroy {
e.stopPropagation();
this.terminalInput = { clear: true };
this.processing = true;
this.sshd = null;
this.socketService.emit({ type: 'restartJob', data: { jobId: this.id } });
}

Expand All @@ -113,13 +119,15 @@ export class AppJobComponent implements OnInit, OnDestroy {
e.stopPropagation();
this.terminalInput = { clear: true };
this.processing = true;
this.sshd = null;
this.socketService.emit({ type: 'restartJobWithSSH', data: { jobId: this.id } });
}

stopJob(e: MouseEvent): void {
e.preventDefault();
e.stopPropagation();
this.processing = true;
this.sshd = null;
this.socketService.emit({ type: 'stopJob', data: { jobId: this.id } });
}

Expand Down
21 changes: 21 additions & 0 deletions src/app/styles/build-details.sass
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,24 @@

.button
margin-left: 10px

.ssh-container
display: flex
align-items: center
padding: 15px 10px
background: $background
border: 1px solid $divider
font-size: 13px

span
margin: 0 10px 0 0

.icon
margin-left: 10px

code
background: $black
color: $white
padding: 5px 10px
border-radius: 4px
margin: 0 5px

0 comments on commit 788517f

Please sign in to comment.