abstruse
Version:
Abstruse CI
388 lines (340 loc) • 10.9 kB
text/typescript
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { SocketService } from '../../services/socket.service';
import { ApiService } from '../../services/api.service';
import { AuthService } from '../../services/auth.service';
import { ConfigService } from '../../services/config.service';
import { Subscription } from 'rxjs';
import { delay, filter } from 'rxjs/operators';
export interface IRepoForm {
id: number;
access_tokens_id: any;
repository_provider: string;
api_url: string;
public: boolean;
}
export interface VariableForm {
name: string;
value: string;
repositories_id: number;
encrypted: number;
}
export class AppRepositoryComponent implements OnInit, OnDestroy {
loading: boolean;
fetching: boolean;
sub: Subscription;
subUpdate: Subscription;
tab: string;
id: string;
repo: any;
url: string;
statusBadge: string;
tokens: any[];
saving: boolean;
form: IRepoForm;
limit: number;
offset: number;
hideMoreButton: boolean;
userData: any;
userId: string | null;
environmentVariableForm: VariableForm;
accessTokensOptions: { key: string, value: string }[];
yesNoOptions: { key: number, value: string }[];
checkingConfig: boolean;
checkConfigResult: { read: boolean; config: boolean; };
repositoryProviders: { key: string, value: string }[];
triggeringBuild: boolean;
buildSuccessfullyTriggered: boolean;
buildTriggerError: boolean;
addingEnvVar: boolean;
fetchingConfig: boolean;
configFile: string;
runningConfigBuild: boolean;
configBuildStatus: boolean;
cache: any[];
cacheDeleted: boolean;
fetchingCache: boolean;
deletingCache: boolean;
constructor(
private route: ActivatedRoute,
private router: Router,
private socketService: SocketService,
private api: ApiService,
private authService: AuthService,
private config: ConfigService
) {
this.loading = true;
this.fetching = false;
this.limit = 5;
this.offset = 0;
this.environmentVariableForm = {
name: null, value: null, repositories_id: null, encrypted: 0
};
this.accessTokensOptions = [];
this.yesNoOptions = [{ key: 0, value: 'No' }, { key: 1, value: 'Yes' }];
this.repositoryProviders = [
{ key: 'github', value: 'GitHub' },
{ key: 'gitlab', value: 'GitLab' },
{ key: 'bitbucket', value: 'BitBucket' },
{ key: 'gogs', value: 'Gogs' }
];
}
ngOnInit() {
this.userData = this.authService.getData();
this.userId = this.userData && this.userData.id || null;
this.url = this.config.url;
this.id = this.route.snapshot.params.id;
const queryParams = this.route.snapshot.queryParams.tab;
if (!queryParams) {
this.router.navigate(['/repo', this.id], { queryParams: { tab: 'builds' } });
this.tab = 'builds';
} else {
this.tab = queryParams;
}
if (!this.id) {
this.router.navigate(['repositories']);
} else {
this.fetch();
this.fetchBuilds();
this.fetchBadge();
this.fetchCache();
if (this.userId) {
this.fetchTokens();
}
}
this.sub = this.socketService.outputEvents
.pipe(filter(x => x.type !== 'data'))
.subscribe(event => {
if (!this.repo || !event.data) {
return;
}
if (event.data === 'build added' && event.repository_id
&& event.repository_id === this.id && event.additionalData) {
if (!this.repo.builds) {
this.repo.builds = [];
}
this.repo.builds.unshift(event.additionalData);
this.updateJobs();
}
const index = this.repo.builds.findIndex(build => build.id === event.build_id);
if (index !== -1) {
const jobIndex = this.repo.builds[index].jobs.findIndex(job => job.id === event.job_id);
if (jobIndex !== -1) {
let status = null;
switch (event.data) {
case 'job succeded':
status = 'success';
this.repo.builds[index].jobs[jobIndex].end_time = event.additionalData;
break;
case 'job queued':
status = 'queued';
break;
case 'job started':
status = 'running';
this.repo.builds[index].jobs[jobIndex].start_time = event.additionalData;
break;
case 'job failed':
status = 'failed';
this.repo.builds[index].jobs[jobIndex].start_time = event.additionalData;
break;
case 'job stopped':
status = 'failed';
this.repo.builds[index].jobs[jobIndex].end_time = event.additionalData;
break;
}
this.repo.builds[index].jobs[jobIndex].status = status;
this.updateJobs();
}
}
});
this.subUpdate = this.socketService.outputEvents
.pipe(
filter((event: any) => event.data === 'build restarted' || event.data === 'build succeeded' || event.data === 'build failed')
)
.subscribe(event => {
let index = this.repo.builds.findIndex(i => i.id === event.build_id);
if (index !== -1) {
if (event.data === 'build restarted') {
this.repo.builds[index].start_time = event.additionalData;
this.updateJobs();
} else {
this.repo.builds[index].end_time = event.additionalData;
this.updateJobs();
}
}
});
}
ngOnDestroy() {
if (this.sub) {
this.sub.unsubscribe();
}
if (this.subUpdate) {
this.subUpdate.unsubscribe();
}
}
switchTab(tab: string): void {
if (this.route.snapshot.queryParams.tab === tab) {
return;
} else {
this.router.navigate(['repo', this.id], { queryParams: { tab: tab } });
this.tab = tab;
}
}
fetch(): void {
this.api.getRepository(this.id, this.userId).subscribe(event => {
this.repo = event;
this.form = {
id: parseInt(this.id, 10),
access_tokens_id: event.access_tokens_id,
repository_provider: event.repository_provider,
api_url: event.api_url,
public: event.public
};
this.loading = false;
});
}
fetchBuilds(e?: Event): void {
if (e && e.preventDefault) {
e.preventDefault();
e.stopPropagation();
}
this.fetching = true;
this.api.getRepositoryBuilds(this.id, this.limit, this.offset, this.userId || null).subscribe(builds => {
if (!this.repo.builds) {
this.repo.builds = [];
}
this.repo.builds = this.repo.builds.concat(builds);
this.fetching = false;
if (builds.length === this.limit) {
this.offset += 5;
} else {
this.hideMoreButton = true;
}
this.updateJobs();
});
}
fetchBadge(): void {
this.api.getBadge(parseInt(this.id, 10)).subscribe(event => {
if (event.ok && event._body && typeof event._body === 'string') {
this.statusBadge = event._body.replace(/ \r/g, '').replace(/url\(/g, 'url(' + document.location.href).trim();
}
});
}
fetchTokens(): void {
this.api.getAllTokens().subscribe(tokens => {
this.accessTokensOptions = tokens.map(token => {
return { key: token.id, value: token.user.fullname + '`s ' + token.description };
});
});
}
updateJobs(): void {
this.repo.builds = this.repo.builds
.map(build => {
let status = 'queued';
if (build.jobs.findIndex(job => job.status === 'failed') !== -1) {
status = 'failed';
}
if (build.jobs.findIndex(job => job.status === 'running') !== -1) {
status = 'running';
}
if (build.jobs.length === build.jobs.filter(job => job.status === 'success').length) {
status = 'success';
}
build.maxCompletedJobTime = Math.max(...build.jobs.map(job => job.end_time - job.start_time));
build.minRunningJobStartTime = Math.min(...build.jobs
.filter(job => job.status === 'running')
.map(job => job.start_time));
build.status = status;
return build;
});
}
gotoBuild(buildId: number) {
this.router.navigate(['build', buildId]);
}
fetchCache(): void {
this.fetchingCache = true;
this.cache = [];
this.api.fetchCacheForRepository(Number(this.id)).subscribe(cache => {
this.cache = cache;
this.fetchingCache = false;
});
}
deleteCache(): void {
this.deletingCache = true;
this.api.deleteCacheForRepository(Number(this.id)).subscribe(status => {
this.cacheDeleted = true;
this.deletingCache = false;
this.fetchCache();
});
}
checkRepositoryConfig(): void {
this.checkingConfig = true;
this.checkConfigResult = null;
this.api.checkRepositoryConfiguration(Number(this.id)).subscribe(ev => {
this.checkConfigResult = ev;
this.checkingConfig = false;
});
}
triggerTestBuild(): void {
this.triggeringBuild = true;
this.buildSuccessfullyTriggered = false;
this.buildTriggerError = false;
this.api.triggerTestBuild(Number(this.id)).subscribe(ev => {
if (ev) {
this.buildSuccessfullyTriggered = true;
} else {
this.buildTriggerError = true;
}
this.triggeringBuild = false;
});
}
fetchConfigFile(): void {
this.fetchingConfig = true;
this.api.getRepositoryConfigRawFile(Number(this.id)).subscribe(ev => {
this.fetchingConfig = false;
this.configFile = ev;
});
}
runConfigBuild(): void {
this.runningConfigBuild = true;
const cfg = {
config: this.configFile,
id: this.id
};
this.api.runRepositoryBuildFromConfig(cfg).subscribe(ev => {
this.configBuildStatus = ev;
this.runningConfigBuild = false;
});
}
saveRepoSettings(e: MouseEvent): void {
this.saving = true;
this.api.saveRepositorySettings(this.form)
.pipe(delay(1000))
.subscribe(saved => {
if (saved) {
this.saving = false;
}
});
}
addEnvironmentVariable(): void {
this.environmentVariableForm.repositories_id = this.repo.id;
this.addingEnvVar = true;
this.api.addNewEnvironmentVariable(this.environmentVariableForm)
.pipe(delay(500))
.subscribe(() => {
this.addingEnvVar = false;
this.fetch();
});
this.environmentVariableForm = {
name: null, value: null, repositories_id: null, encrypted: 0
};
}
removeVariable(id: number): void {
this.api.removeNewEnvironmentVariable(id)
.subscribe(() => this.fetch());
}
}