mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-06-02 21:49:25 +00:00
258 lines
5.5 KiB
JavaScript
258 lines
5.5 KiB
JavaScript
import React, { Component } from "react";
|
|
import { Link } from "react-router-dom";
|
|
|
|
import { fetchBuild, approveBuild, declineBuild } from "shared/utils/build";
|
|
import {
|
|
STATUS_BLOCKED,
|
|
STATUS_DECLINED,
|
|
STATUS_ERROR,
|
|
} from "shared/constants/status";
|
|
|
|
import { findChildProcess } from "shared/utils/proc";
|
|
import { fetchRepository } from "shared/utils/repository";
|
|
|
|
import Breadcrumb, { SEPARATOR } from "shared/components/breadcrumb";
|
|
|
|
import { Approval, Details, ProcList } from "./components";
|
|
|
|
import { branch } from "baobab-react/higher-order";
|
|
import { inject } from "config/client/inject";
|
|
|
|
import Output from "./logs";
|
|
|
|
import styles from "./index.less";
|
|
|
|
const binding = (props, context) => {
|
|
const { owner, repo, build } = props.match.params;
|
|
const slug = `${owner}/${repo}`;
|
|
const number = parseInt(build);
|
|
|
|
return {
|
|
repo: ["repos", "data", slug],
|
|
build: ["builds", "data", slug, number],
|
|
};
|
|
};
|
|
|
|
@inject
|
|
@branch(binding)
|
|
export default class BuildLogs extends Component {
|
|
constructor(props, context) {
|
|
super(props, context);
|
|
|
|
this.handleApprove = this.handleApprove.bind(this);
|
|
this.handleDecline = this.handleDecline.bind(this);
|
|
}
|
|
|
|
componentWillMount() {
|
|
this.synchronize(this.props);
|
|
}
|
|
|
|
handleApprove() {
|
|
const { repo, build, drone } = this.props;
|
|
this.props.dispatch(
|
|
approveBuild,
|
|
drone,
|
|
repo.owner,
|
|
repo.name,
|
|
build.number,
|
|
);
|
|
}
|
|
|
|
handleDecline() {
|
|
const { repo, build, drone } = this.props;
|
|
this.props.dispatch(
|
|
declineBuild,
|
|
drone,
|
|
repo.owner,
|
|
repo.name,
|
|
build.number,
|
|
);
|
|
}
|
|
|
|
componentWillUpdate(nextProps) {
|
|
if (this.props.match.url !== nextProps.match.url) {
|
|
this.synchronize(nextProps);
|
|
}
|
|
}
|
|
|
|
synchronize(props) {
|
|
if (!props.repo) {
|
|
this.props.dispatch(
|
|
fetchRepository,
|
|
props.drone,
|
|
props.match.params.owner,
|
|
props.match.params.repo,
|
|
);
|
|
}
|
|
if (!props.build || !props.build.procs) {
|
|
this.props.dispatch(
|
|
fetchBuild,
|
|
props.drone,
|
|
props.match.params.owner,
|
|
props.match.params.repo,
|
|
props.match.params.build,
|
|
);
|
|
}
|
|
}
|
|
|
|
shouldComponentUpdate(nextProps, nextState) {
|
|
return this.props !== nextProps;
|
|
}
|
|
|
|
render() {
|
|
const { repo, build } = this.props;
|
|
|
|
if (!build || !repo) {
|
|
return this.renderLoading();
|
|
}
|
|
|
|
if (build.status === STATUS_DECLINED || build.status === STATUS_ERROR) {
|
|
return this.renderError();
|
|
}
|
|
|
|
if (build.status === STATUS_BLOCKED) {
|
|
return this.renderBlocked();
|
|
}
|
|
|
|
if (!build.procs) {
|
|
return this.renderLoading();
|
|
}
|
|
|
|
return this.renderSimple();
|
|
}
|
|
|
|
renderLoading() {
|
|
return (
|
|
<div className={styles.host}>
|
|
<div className={styles.columns}>
|
|
<div className={styles.right}>Loading ...</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderBlocked() {
|
|
const { build } = this.props;
|
|
return (
|
|
<div className={styles.host}>
|
|
<div className={styles.columns}>
|
|
<div className={styles.right}>
|
|
<Details build={build} />
|
|
</div>
|
|
<div className={styles.left}>
|
|
<Approval
|
|
onapprove={this.handleApprove}
|
|
ondecline={this.handleDecline}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderError() {
|
|
const { build } = this.props;
|
|
return (
|
|
<div className={styles.host}>
|
|
<div className={styles.columns}>
|
|
<div className={styles.right}>
|
|
<Details build={build} />
|
|
</div>
|
|
<div className={styles.left}>
|
|
<div className={styles.logerror}>
|
|
{build.status === STATUS_ERROR ? (
|
|
build.error
|
|
) : (
|
|
"Pipeline execution was declined"
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
highlightedLine() {
|
|
if (location.hash.startsWith("#L")) {
|
|
return parseInt(location.hash.substr(2)) - 1;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
renderSimple() {
|
|
// if (nextProps.build.procs[0].children !== undefined){
|
|
// return null;
|
|
// }
|
|
|
|
const { repo, build, match } = this.props;
|
|
const selectedProc = match.params.proc
|
|
? findChildProcess(build.procs, match.params.proc)
|
|
: build.procs[0].children[0];
|
|
const selectedProcParent = findChildProcess(build.procs, selectedProc.ppid);
|
|
const highlighted = this.highlightedLine();
|
|
|
|
return (
|
|
<div className={styles.host}>
|
|
<div className={styles.columns}>
|
|
<div className={styles.right}>
|
|
<Details build={build} />
|
|
<section className={styles.sticky}>
|
|
{build.procs.map(function(rootProc) {
|
|
return (
|
|
<div style="padding-bottom: 50px;" key={rootProc.pid}>
|
|
<ProcList
|
|
key={rootProc.pid}
|
|
repo={repo}
|
|
build={build}
|
|
rootProc={rootProc}
|
|
selectedProc={selectedProc}
|
|
renderName={build.procs.length > 1}
|
|
/>
|
|
</div>
|
|
);
|
|
})}
|
|
</section>
|
|
</div>
|
|
<div className={styles.left}>
|
|
{selectedProc && selectedProc.error ? (
|
|
<div className={styles.logerror}>{selectedProc.error}</div>
|
|
) : null}
|
|
{selectedProcParent && selectedProcParent.error ? (
|
|
<div className={styles.logerror}>{selectedProcParent.error}</div>
|
|
) : null}
|
|
<Output
|
|
match={this.props.match}
|
|
build={this.props.build}
|
|
proc={selectedProc}
|
|
highlighted={highlighted}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
export class BuildLogsTitle extends Component {
|
|
render() {
|
|
const { owner, repo, build } = this.props.match.params;
|
|
return (
|
|
<Breadcrumb
|
|
elements={[
|
|
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
|
{owner} / {repo}
|
|
</Link>,
|
|
SEPARATOR,
|
|
<Link
|
|
to={`/${owner}/${repo}/${build}`}
|
|
key={`${owner}-${repo}-${build}`}
|
|
>
|
|
{build}
|
|
</Link>,
|
|
]}
|
|
/>
|
|
);
|
|
}
|
|
}
|