Merge branch 'master' into scaffold

This commit is contained in:
Fabian Chong
2020-09-16 14:17:16 +08:00
20 changed files with 87 additions and 70 deletions
@@ -177,9 +177,6 @@ docs on creating private GitHub access tokens is available
Note that the need for private GitHub access tokens will be replaced with GitHub
Apps integration further down the line.
> **Right now it is only possible to scaffold repositories inside GitHub
> organizations, and not under personal accounts.**
The GitHub access token is passed along using the `GITHUB_ACCESS_TOKEN`
environment variable.
@@ -30,11 +30,6 @@ the documentation template.
Create an entity from the documentation template and you will get the needed
setup for free.
!!! warning Currently the Backstage Software Templates are limited to create
repositories inside GitHub organizations. You also need to generate an personal
access token and use as an environment variable. Read more about this
[here](../software-templates/installation.md#runtime-dependencies).
### Manually add documentation setup to already existing repository
Prerequisities:
@@ -15,26 +15,26 @@
*/
import React from 'react';
import { ProgressCard } from './ProgressCard';
import { GaugeCard } from './GaugeCard';
import { Grid } from '@material-ui/core';
const linkInfo = { title: 'Go to XYZ Location', link: '#' };
export default {
title: 'Progress Card',
component: ProgressCard,
component: GaugeCard,
};
export const Default = () => (
<Grid container spacing={2}>
<Grid item>
<ProgressCard title="Progress" progress={0.3} />
<GaugeCard title="Progress" progress={0.3} />
</Grid>
<Grid item>
<ProgressCard title="Progress" progress={0.57} />
<GaugeCard title="Progress" progress={0.57} />
</Grid>
<Grid item>
<ProgressCard title="Progress" progress={0.89} />
<GaugeCard title="Progress" progress={0.89} />
</Grid>
</Grid>
);
@@ -42,21 +42,17 @@ export const Default = () => (
export const Subhead = () => (
<Grid container spacing={2}>
<Grid item>
<ProgressCard
title="Progress"
subheader="With a subheader"
progress={0.3}
/>
<GaugeCard title="Progress" subheader="With a subheader" progress={0.3} />
</Grid>
<Grid item>
<ProgressCard
<GaugeCard
title="Progress"
subheader="With a subheader"
progress={0.57}
/>
</Grid>
<Grid item>
<ProgressCard
<GaugeCard
title="Progress"
subheader="With a subheader"
progress={0.89}
@@ -68,13 +64,13 @@ export const Subhead = () => (
export const LinkInFooter = () => (
<Grid container spacing={2}>
<Grid item>
<ProgressCard title="Progress" deepLink={linkInfo} progress={0.3} />
<GaugeCard title="Progress" deepLink={linkInfo} progress={0.3} />
</Grid>
<Grid item>
<ProgressCard title="Progress" deepLink={linkInfo} progress={0.57} />
<GaugeCard title="Progress" deepLink={linkInfo} progress={0.57} />
</Grid>
<Grid item>
<ProgressCard title="Progress" deepLink={linkInfo} progress={0.89} />
<GaugeCard title="Progress" deepLink={linkInfo} progress={0.89} />
</Grid>
</Grid>
);
@@ -18,32 +18,30 @@ import React from 'react';
import { render } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import { ProgressCard } from './ProgressCard';
import { GaugeCard } from './GaugeCard';
const minProps = { title: 'Tingle upgrade', progress: 0.12 };
describe('<ProgressCard />', () => {
describe('<GaugeCard />', () => {
it('renders without exploding', () => {
const { getByText } = render(wrapInTestApp(<ProgressCard {...minProps} />));
const { getByText } = render(wrapInTestApp(<GaugeCard {...minProps} />));
expect(getByText(/Tingle.*/)).toBeInTheDocument();
});
it('renders progress and title', () => {
const { getByText } = render(wrapInTestApp(<ProgressCard {...minProps} />));
const { getByText } = render(wrapInTestApp(<GaugeCard {...minProps} />));
expect(getByText(/Tingle.*/)).toBeInTheDocument();
expect(getByText(/12%.*/)).toBeInTheDocument();
});
it('does not render deepLink', () => {
const { queryByText } = render(
wrapInTestApp(<ProgressCard {...minProps} />),
);
const { queryByText } = render(wrapInTestApp(<GaugeCard {...minProps} />));
expect(queryByText('View more')).not.toBeInTheDocument();
});
it('handles invalid numbers', () => {
const badProps = { title: 'Tingle upgrade', progress: 'hejjo' };
const { getByText } = render(wrapInTestApp(<ProgressCard {...badProps} />));
const { getByText } = render(wrapInTestApp(<GaugeCard {...badProps} />));
expect(getByText(/N\/A.*/)).toBeInTheDocument();
});
});
@@ -18,7 +18,7 @@ import React, { FC } from 'react';
import { makeStyles } from '@material-ui/core';
import { InfoCard } from '../../layout/InfoCard';
import { BottomLinkProps } from '../../layout/BottomLink';
import { CircleProgress } from './CircleProgress';
import { GaugeProgress } from './GaugeProgress';
type Props = {
title: string;
@@ -36,7 +36,7 @@ const useStyles = makeStyles({
},
});
export const ProgressCard: FC<Props> = props => {
export const GaugeCard: FC<Props> = props => {
const classes = useStyles(props);
const { title, subheader, progress, deepLink, variant } = props;
@@ -48,7 +48,7 @@ export const ProgressCard: FC<Props> = props => {
deepLink={deepLink}
variant={variant}
>
<CircleProgress value={progress} />
<GaugeProgress value={progress} />
</InfoCard>
</div>
);
@@ -17,32 +17,32 @@
import React from 'react';
import { render } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import { CircleProgress, getProgressColor } from './CircleProgress';
import { GaugeProgress, getProgressColor } from './GaugeProgress';
describe('<CircleProgress />', () => {
describe('<GaugeProgress />', () => {
it('renders without exploding', () => {
const { getByText } = render(
wrapInTestApp(<CircleProgress value={10} fractional={false} />),
wrapInTestApp(<GaugeProgress value={10} fractional={false} />),
);
getByText('10%');
});
it('handles fractional prop', () => {
const { getByText } = render(
wrapInTestApp(<CircleProgress value={0.1} fractional />),
wrapInTestApp(<GaugeProgress value={0.1} fractional />),
);
getByText('10%');
});
it('handles max prop', () => {
const { getByText } = render(
wrapInTestApp(<CircleProgress value={1} max={10} fractional={false} />),
wrapInTestApp(<GaugeProgress value={1} max={10} fractional={false} />),
);
getByText('1%');
});
it('handles unit prop', () => {
const { getByText } = render(
wrapInTestApp(<CircleProgress value={10} fractional={false} unit="m" />),
wrapInTestApp(<GaugeProgress value={10} fractional={false} unit="m" />),
);
getByText('10m');
});
@@ -77,7 +77,7 @@ export function getProgressColor(
return palette.status.ok;
}
export const CircleProgress: FC<Props> = props => {
export const GaugeProgress: FC<Props> = props => {
const classes = useStyles(props);
const theme = useTheme<BackstageTheme>();
const { value, fractional, inverse, unit, max } = {
@@ -15,29 +15,29 @@
*/
import React from 'react';
import { HorizontalProgress } from './HorizontalProgress';
import { LinearGauge } from './LinearGauge';
const containerStyle = { width: 300 };
export default {
title: 'HorizontalProgress',
component: HorizontalProgress,
title: 'LinearGauge',
component: LinearGauge,
};
export const Default = () => (
<div style={containerStyle}>
<HorizontalProgress value={0.8} />
<LinearGauge value={0.8} />
</div>
);
export const MediumProgress = () => (
<div style={containerStyle}>
<HorizontalProgress value={0.5} />
<LinearGauge value={0.5} />
</div>
);
export const LowProgress = () => (
<div style={containerStyle}>
<HorizontalProgress value={0.2} />
<LinearGauge value={0.2} />
</div>
);
@@ -19,7 +19,7 @@ import { Tooltip, useTheme } from '@material-ui/core';
// @ts-ignore
import { Line } from 'rc-progress';
import { BackstageTheme } from '@backstage/theme';
import { getProgressColor } from './CircleProgress';
import { getProgressColor } from './GaugeProgress';
type Props = {
/**
@@ -28,7 +28,7 @@ type Props = {
value: number;
};
export const HorizontalProgress: FC<Props> = ({ value }) => {
export const LinearGauge: FC<Props> = ({ value }) => {
const theme = useTheme<BackstageTheme>();
if (isNaN(value)) {
return null;
@@ -14,6 +14,6 @@
* limitations under the License.
*/
export { ProgressCard } from './ProgressCard';
export { CircleProgress } from './CircleProgress';
export { HorizontalProgress } from './HorizontalProgress';
export { GaugeCard } from './GaugeCard';
export { GaugeProgress } from './GaugeProgress';
export { LinearGauge } from './LinearGauge';
@@ -30,7 +30,7 @@ import {
Table,
StatusOK,
TableColumn,
ProgressCard,
GaugeCard,
TrendLine,
} from '../../components';
import { Box, Typography, Link, Chip, Grid } from '@material-ui/core';
@@ -120,14 +120,14 @@ const DataGrid = () => (
direction="row"
>
<Grid item xs={6}>
<ProgressCard
<GaugeCard
title="GKE Usage Score"
subheader="This should be above 75%"
progress={0.87}
/>
</Grid>
<Grid item xs={6}>
<ProgressCard
<GaugeCard
title="Deployment Score"
subheader="This should be above 40%"
progress={0.58}
+1 -1
View File
@@ -18,7 +18,7 @@ FROM python:3.8-alpine
RUN apk update && apk --no-cache add gcc musl-dev openjdk11-jdk curl graphviz ttf-dejavu fontconfig
RUN curl -L http://sourceforge.net/projects/plantuml/files/plantuml.1.2020.16.jar/download > /opt/plantuml.jar
RUN pip install --upgrade pip && pip install mkdocs-techdocs-core==0.0.4
RUN pip install --upgrade pip && pip install mkdocs-techdocs-core==0.0.6
# Create script to call plantuml.jar from a location in path
@@ -50,6 +50,10 @@ python -m black src/
## Changelog
### 0.0.5
- Downgrade some versions of markdown extensions to versions that are more stable
### 0.0.4
- Added support for more mkdocs extensions
@@ -4,10 +4,10 @@
mkdocs==1.1.2
mkdocs-material==5.3.2
mkdocs-monorepo-plugin==0.4.5
plantuml-markdown==3.4.0
plantuml-markdown==3.1.2
markdown_inline_graphviz_extension==1.1
pygments==2.6.1
pymdown-extensions==7.1
pymdown-extensions==8.0.0
# The linter using for Python
# Note: This requires Python 3.6+ to run, but can format Python 2 code too.
@@ -18,7 +18,7 @@ from setuptools import setup, find_packages
setup(
name='mkdocs-techdocs-core',
version='0.0.4',
version='0.0.6',
description='A Mkdocs package that contains TechDocs defaults',
long_description='',
keywords='mkdocs',
@@ -31,10 +31,10 @@ setup(
'mkdocs>=1.1.2',
'mkdocs-material==5.3.2',
'mkdocs-monorepo-plugin==0.4.5',
'plantuml-markdown==3.4.0',
'plantuml-markdown==3.1.2',
'markdown_inline_graphviz_extension==1.1',
'pygments==2.6.1',
'pymdown-extensions==7.1'
'pymdown-extensions==8.0.0'
],
classifiers=[
'Development Status :: 1 - Planning',
@@ -19,6 +19,9 @@ export const mockGithubClient = {
createInOrg: jest.fn(),
createForAuthenticatedUser: jest.fn(),
},
users: {
getByUsername: jest.fn(),
},
};
export class Octokit {
@@ -19,11 +19,18 @@ jest.mock('nodegit');
import { Octokit } from '@octokit/rest';
import * as NodeGit from 'nodegit';
import { OctokitResponse, ReposCreateInOrgResponseData } from '@octokit/types';
import {
OctokitResponse,
ReposCreateInOrgResponseData,
UsersGetByUsernameResponseData,
} from '@octokit/types';
import { GithubPublisher } from './github';
const { mockGithubClient } = require('@octokit/rest') as {
mockGithubClient: { repos: jest.Mocked<Octokit['repos']> };
mockGithubClient: {
repos: jest.Mocked<Octokit['repos']>;
users: jest.Mocked<Octokit['users']>;
};
};
const {
@@ -59,10 +66,14 @@ describe('GitHub Publisher', () => {
clone_url: 'mockclone',
},
} as OctokitResponse<ReposCreateInOrgResponseData>);
mockGithubClient.users.getByUsername.mockResolvedValue({
data: {
type: 'Organization',
},
} as OctokitResponse<UsersGetByUsernameResponseData>);
await publisher.publish({
values: {
isOrg: true,
storePath: 'blam/test',
owner: 'bob',
},
@@ -81,6 +92,11 @@ describe('GitHub Publisher', () => {
clone_url: 'mockclone',
},
} as OctokitResponse<ReposCreateInOrgResponseData>);
mockGithubClient.users.getByUsername.mockResolvedValue({
data: {
type: 'User',
},
} as OctokitResponse<UsersGetByUsernameResponseData>);
await publisher.publish({
values: {
@@ -112,6 +128,12 @@ describe('GitHub Publisher', () => {
clone_url: 'mockclone',
},
} as OctokitResponse<ReposCreateInOrgResponseData>);
mockGithubClient.users.getByUsername.mockResolvedValue({
data: {
type: 'Organization',
},
} as OctokitResponse<UsersGetByUsernameResponseData>);
it('should call init on the repo with the directory', async () => {
await publisher.publish({
values,
@@ -45,9 +45,12 @@ export class GithubPublisher implements PublisherBase {
) {
const [owner, name] = values.storePath.split('/');
const repoCreationPromise = values.isOrg
? this.client.repos.createInOrg({ name, org: owner })
: this.client.repos.createForAuthenticatedUser({ name });
const user = await this.client.users.getByUsername({ username: owner });
const repoCreationPromise =
user.data.type === 'Organization'
? this.client.repos.createInOrg({ name, org: owner })
: this.client.repos.createForAuthenticatedUser({ name });
const { data } = await repoCreationPromise;
+1 -2
View File
@@ -46,8 +46,7 @@ export class ScaffolderApi {
headers: {
'Content-Type': 'application/json',
},
// TODO(shmidt-i): when repo picker is implemented, take isOrg from it
body: JSON.stringify({ template, values: { ...values, isOrg: true } }),
body: JSON.stringify({ template, values: { ...values } }),
});
if (response.status !== 201) {
@@ -72,7 +72,7 @@ export const JobStatusModal = ({
{entity && (
<DialogActions>
<Button
to={generatePath(entityRoute.path, {
to={generatePath(`/catalog/${entityRoute.path}`, {
kind: entity.kind,
optionalNamespaceAndName: [
entity.metadata.namespace,