Merge branch 'master' of github.com:Nek/backstage

This commit is contained in:
Ivan Shmidt
2020-05-08 16:48:45 +02:00
30 changed files with 414 additions and 28 deletions
+2
View File
@@ -22,11 +22,13 @@
"@types/react-lazylog": "^4.5.0",
"@types/react-redux": "^7.1.8",
"circleci-api": "^4.0.0",
"moment": "^2.25.3",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-lazylog": "^4.5.2",
"react-redux": "^7.2.0",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"react-use": "^13.0.0"
},
"devDependencies": {
+15
View File
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { Route, Switch } from 'react-router';
import { Provider, useDispatch } from 'react-redux';
-1
View File
@@ -60,7 +60,6 @@ export class CircleCIApi {
}
async getBuild(buildNumber: number, options: CircleCIOptions) {
console.log({ buildNumber, options });
return getFullBuild(options.token, buildNumber, {
circleHost: this.apiUrl,
...options.vcs,
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { Header, Page, pageTheme, HeaderLabel } from '@backstage/core';
// @ts-ignore
@@ -10,7 +25,7 @@ export const Layout: React.FC = ({ children }) => (
pageTitleOverride="Circle CI"
title={
<Box display="flex" alignItems="center">
<img src={logo} style={{ height: '1em' }} />
<img src={logo} style={{ height: '1em' }} alt="Backstage Logo" />
<Box mr={1} /> Circle CI
</Box>
}
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './Layout';
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { FC } from 'react';
import { Link as RouterLink, useLocation } from 'react-router-dom';
import { ContentHeader, SupportButton } from '@backstage/core';
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './PluginHeader';
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { FC } from 'react';
import { Content } from '@backstage/core';
import { Grid } from '@material-ui/core';
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './BuildsPage';
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2020 Spotify AB
*
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Builds } from './Builds';
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { FC } from 'react';
import { Link, Typography, Box, IconButton } from '@material-ui/core';
import { Replay as RetryIcon, GitHub as GithubIcon } from '@material-ui/icons';
@@ -29,7 +44,7 @@ export type CITableBuildInfo = {
passed: number;
skipped: number;
failed: number;
testUrl: string; //fixme better name
testUrl: string; // fixme better name
};
onRetryClick: () => void;
};
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { CITable, CITableBuildInfo } from './CITable';
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { FC } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
@@ -72,7 +87,7 @@ const pickClassName = (
return classes.neutral;
};
export const DetailedViewPage: FC<{}> = () => {
let { buildId = '' } = useParams();
const { buildId = '' } = useParams();
const classes = useStyles();
const dispatch: Dispatch = useDispatch();
const api = useApi(circleCIApiRef);
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './DetailedViewPage';
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useEffect, useState, FC, Suspense } from 'react';
import {
ExpansionPanel,
@@ -20,7 +35,6 @@ const useStyles = makeStyles({
button: {
order: -1,
marginRight: 0,
// FIXME: how not to hardcode this
marginLeft: '-20px',
},
});
@@ -36,12 +50,13 @@ export const ActionOutput: FC<{
const [messages, setMessages] = useState([]);
useEffect(() => {
fetch(url)
.then((res) => res.json())
.then((actionOutput) => {
actionOutput &&
.then(res => res.json())
.then(actionOutput => {
if (typeof actionOutput !== 'undefined') {
setMessages(
actionOutput.map(({ message }: { message: string }) => message),
);
}
});
}, [url]);
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { ActionOutput } from './ActionOutput';
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
@@ -21,20 +36,14 @@ export const SettingsPage = () => {
token: tokenFromStore,
owner: ownerFromStore,
repo: repoFromStore,
} = useSelector(
(state: iRootState): SettingsState =>
(console.log({ state }) as any) || state.settings,
);
} = useSelector((state: iRootState): SettingsState => state.settings);
// const apiGitInfo = api.options.vcs;
// const [authed] = React.useState(false);
const [token, setToken] = React.useState(() => tokenFromStore);
const [owner, setOwner] = React.useState(() => ownerFromStore);
const [repo, setRepo] = React.useState(() => repoFromStore);
const dispatch: Dispatch = useDispatch();
React.useEffect(() => () => console.log('Settings unmounterd'), []);
React.useEffect(() => {
if (tokenFromStore !== token) {
setToken(tokenFromStore);
@@ -60,7 +69,7 @@ export const SettingsPage = () => {
title={
<>
Project Credentials
{/*{authed ? <StatusOK /> : <StatusFailed />} */}
{/* {authed ? <StatusOK /> : <StatusFailed />} */}
<Snackbar
autoHideDuration={1000}
open={saved}
@@ -80,7 +89,7 @@ export const SettingsPage = () => {
value={token}
fullWidth
variant="outlined"
onChange={(e) => setToken(e.target.value)}
onChange={e => setToken(e.target.value)}
/>
</ListItem>
<ListItem>
@@ -90,7 +99,7 @@ export const SettingsPage = () => {
label="Owner"
variant="outlined"
value={owner}
onChange={(e) => setOwner(e.target.value)}
onChange={e => setOwner(e.target.value)}
/>
</ListItem>
<ListItem>
@@ -100,7 +109,7 @@ export const SettingsPage = () => {
fullWidth
variant="outlined"
value={repo}
onChange={(e) => setRepo(e.target.value)}
onChange={e => setRepo(e.target.value)}
/>
</ListItem>
<ListItem>
@@ -1 +1,16 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './SettingsPage';
+15
View File
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const proxySettings = {
'/circleci/api': {
target: 'https://circleci.com/api/v1.1',
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Dispatch, iRootState } from '../store';
import { GitType, BuildWithSteps } from 'circleci-api';
import { CircleCIApi } from '../../api';
@@ -6,6 +21,7 @@ export type BuildState = {
builds: Record<number, BuildWithSteps>;
pollingIntervalId: number | null;
pollingState: PollingState;
getBuildError: Error | null;
};
const INTERVAL_AMOUNT = 1500;
@@ -19,6 +35,7 @@ export const buildWithSteps = {
builds: {},
pollingIntervalId: null,
pollingState: PollingState.Idle,
getBuildError: null,
} as BuildState,
reducers: {
setBuild(state: BuildState, payload: BuildWithSteps) {
@@ -30,6 +47,9 @@ export const buildWithSteps = {
builds: { ...state.builds, [payload.build_num!]: payload },
};
},
setBuildError(state: BuildState, payload: Error | null) {
return { ...state, getBuildError: payload };
},
setPollingIntervalId(state: BuildState, payload: number | null) {
return {
...state,
@@ -45,6 +65,7 @@ export const buildWithSteps = {
state: iRootState,
) {
try {
dispatch.buildWithSteps.setBuildError(null);
const options = {
token: state.settings.token,
vcs: {
@@ -56,7 +77,7 @@ export const buildWithSteps = {
const build = await api.getBuild(buildId, options);
dispatch.buildWithSteps.setBuild(build);
} catch (e) {
console.log(e);
dispatch.buildWithSteps.setBuildError(e);
}
},
startPolling(
+31 -4
View File
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Dispatch, iRootState } from '../store';
import { BuildSummary, GitType } from 'circleci-api';
import { CircleCIApi } from '../../api';
@@ -6,6 +21,8 @@ export type BuildsState = {
builds: BuildSummary[];
pollingIntervalId: number | null;
pollingState: PollingState;
restartBuildError: Error | null;
getBuildsError: Error | null;
};
const INTERVAL_AMOUNT = 1500;
@@ -19,6 +36,8 @@ export const builds = {
builds: [] as BuildSummary[],
pollingIntervalId: null,
pollingState: PollingState.Idle,
restartBuildError: null,
getBuildsError: null,
},
reducers: {
setBuilds(state: BuildsState, payload: BuildSummary[]) {
@@ -35,11 +54,18 @@ export const builds = {
payload === null ? PollingState.Idle : PollingState.Polling,
};
},
setRestartBuildError(state: BuildsState, payload: Error | null) {
return { ...state, restartBuildError: payload };
},
setGetBuildsError(state: BuildsState, payload: Error | null) {
return { ...state, getBuildsError: payload };
},
},
effects: (dispatch: Dispatch) => ({
async getBuilds(api: CircleCIApi, state: iRootState) {
try {
const builds = await api.getBuilds({
dispatch.builds.setGetBuildsError(null);
const newBuilds = await api.getBuilds({
token: state.settings.token,
vcs: {
owner: state.settings.owner,
@@ -47,9 +73,9 @@ export const builds = {
type: GitType.GITHUB,
},
});
dispatch.builds.setBuilds(builds);
dispatch.builds.setBuilds(newBuilds);
} catch (e) {
console.log(e);
dispatch.builds.setGetBuildsError(null);
}
},
async restartBuild(
@@ -57,6 +83,7 @@ export const builds = {
state: iRootState,
) {
try {
dispatch.builds.setRestartBuildError(null);
await api.retry(buildId, {
token: state.settings.token,
vcs: {
@@ -66,7 +93,7 @@ export const builds = {
},
});
} catch (e) {
console.log(e);
dispatch.builds.setRestartBuildError(e);
}
},
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { settings } from './settings';
import { builds } from './builds';
import { buildWithSteps } from './buildWithSteps';
+20 -1
View File
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Dispatch, iRootState } from '../store';
import { circleCIApiRef } from '../../api';
@@ -30,11 +45,15 @@ export const settings = {
}: SettingsState & { doPersist: boolean }) {
if (doPersist) dispatch.settings.persist(credentials);
},
setRehydrateError(state: SettingsState, payload: Error | null) {
return { ...state, rehydrateError: payload };
},
persist(credentials: SettingsState) {
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(credentials));
},
rehydrate(_: any, state: iRootState) {
try {
dispatch.settings.setRehydrateError(null);
const stateFromStorage = JSON.parse(
sessionStorage.getItem(STORAGE_KEY)!,
);
@@ -49,7 +68,7 @@ export const settings = {
doPersist: false,
});
} catch (e) {
console.log(e);
dispatch.settings.setRehydrateError(e);
}
},
}),
+15
View File
@@ -1,3 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { init, RematchRootState, RematchDispatch } from '@rematch/core';
import { models, RootModel } from './models';