Merge branch 'master' of github.com:spotify/backstage into scaffolder/new-templates
* 'master' of github.com:spotify/backstage: Add AA to adopters (#1684) docs: Add link to Figma library (#1674) docs: add SDA SE to adopters (#1678) fix: get package name from package.json fix(build-imgae): get package name from env fix linting feat(scaffolder): add color bg to template cards, use correct header colors auth-backend: tweak error messages cli: pin esbuild to 0.6.3 fix: use gitgub token from UI fix: code review Update packages/app/src/apis.ts feat: connect UI and API docs(techdocs-cli): add docs on deploying / bumping up version
This commit is contained in:
@@ -5,4 +5,6 @@
|
||||
| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. |
|
||||
| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up |
|
||||
| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. |
|
||||
| [SDA SE](https://sda.se) | [@Fox32](https://github.com/Fox32) | Central place for developing and sharing services in our insurance ecosystem. |
|
||||
| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. |
|
||||
| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
We have a [Figma component library](https://www.figma.com/@backstage) that you can use to build your own plugins for Backstage.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"@backstage/theme": "^0.1.1-alpha.14",
|
||||
"@material-ui/core": "^4.9.1",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@octokit/rest": "^18.0.0",
|
||||
"history": "^5.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.12.0",
|
||||
|
||||
@@ -82,7 +82,9 @@ export const apis = (config: ConfigApi) => {
|
||||
circleCIApiRef,
|
||||
new CircleCIApi(`${backendUrl}/proxy/circleci/api`),
|
||||
);
|
||||
|
||||
builder.add(githubActionsApiRef, new GithubActionsClient());
|
||||
|
||||
builder.add(featureFlagsApiRef, new FeatureFlags());
|
||||
|
||||
builder.add(lighthouseApiRef, new LighthouseRestApi('http://localhost:3003'));
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"css-loader": "^3.5.3",
|
||||
"dashify": "^2.0.0",
|
||||
"diff": "^4.0.2",
|
||||
"esbuild": "0.6.3",
|
||||
"eslint": "^7.1.0",
|
||||
"eslint-formatter-friendly": "^7.0.0",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
|
||||
@@ -19,8 +19,12 @@ import { createDistWorkspace } from '../../lib/packager';
|
||||
import { paths } from '../../lib/paths';
|
||||
import { run } from '../../lib/run';
|
||||
|
||||
const PKG_PATH = 'package.json';
|
||||
|
||||
export default async (imageTag: string) => {
|
||||
const tempDistWorkspace = await createDistWorkspace(['example-backend'], {
|
||||
const pkgPath = paths.resolveTarget(PKG_PATH);
|
||||
const pkg = await fs.readJson(pkgPath);
|
||||
const tempDistWorkspace = await createDistWorkspace([pkg.name], {
|
||||
files: [
|
||||
'package.json',
|
||||
'yarn.lock',
|
||||
@@ -28,7 +32,6 @@ export default async (imageTag: string) => {
|
||||
{ src: paths.resolveTarget('Dockerfile'), dest: 'Dockerfile' },
|
||||
],
|
||||
});
|
||||
|
||||
console.log(`Dist workspace ready at ${tempDistWorkspace}`);
|
||||
|
||||
await run('docker', ['build', '.', '-t', imageTag], {
|
||||
|
||||
@@ -26,7 +26,7 @@ export type PageTheme = {
|
||||
|
||||
export const gradients: Record<string, Gradient> = {
|
||||
darkGrey: {
|
||||
colors: ['#181818', '#404040'],
|
||||
colors: ['#171717', '#383838'],
|
||||
waveColor: '#757575',
|
||||
opacity: ['1.0', '0.0'],
|
||||
},
|
||||
|
||||
@@ -45,3 +45,18 @@ npx techdocs serve
|
||||
You should have a `localhost:3000` serving TechDocs in Backstage, as well as `localhost:8000` serving Mkdocs (which won't open up and be exposed to the user).
|
||||
|
||||
Happy hacking!
|
||||
|
||||
## Deploying a new version
|
||||
|
||||
Deploying the Node packages to NPM happens automatically on merge to `master` through GitHub Actions. The deployment happens through Lerna which determines which packages throughout the Backstage project have changed. In our case, the package is called `techdocs-cli` in the repository but `@techdocs/cli` in the NPM registry.
|
||||
|
||||
> Note: Once a package is published under a version, any subsequent changes will not override that version. You will need to bump up the version across the entire Backstage repository, which can be done through Lerna (see the command below).
|
||||
|
||||
In order to bump up all packages, go to the root of the Backstage repository. To see the current version see the `lerna.json` under the `version` key. To then update all the versions (locally on your machine), run the following:
|
||||
|
||||
```bash
|
||||
git checkout -b bump-up-version
|
||||
yarn lerna version --no-push --allow-branch --yes
|
||||
```
|
||||
|
||||
Upon being merged to master, Lerna will then automatically publish these packages as configured by the Backstage core team.
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('OAuthProvider Utils', () => {
|
||||
} as unknown) as express.Request;
|
||||
expect(() => {
|
||||
verifyNonce(mockRequest, 'providera');
|
||||
}).toThrowError('Missing nonce');
|
||||
}).toThrowError('Auth response is missing cookie nonce');
|
||||
});
|
||||
|
||||
it('should throw error if state nonce missing', () => {
|
||||
@@ -63,7 +63,7 @@ describe('OAuthProvider Utils', () => {
|
||||
} as unknown) as express.Request;
|
||||
expect(() => {
|
||||
verifyNonce(mockRequest, 'providera');
|
||||
}).toThrowError('Missing nonce');
|
||||
}).toThrowError('Auth response is missing state nonce');
|
||||
});
|
||||
|
||||
it('should throw error if nonce mismatch', () => {
|
||||
|
||||
@@ -43,10 +43,12 @@ export const verifyNonce = (req: express.Request, providerId: string) => {
|
||||
const cookieNonce = req.cookies[`${providerId}-nonce`];
|
||||
const stateNonce = req.query.state;
|
||||
|
||||
if (!cookieNonce || !stateNonce) {
|
||||
throw new Error('Missing nonce');
|
||||
if (!cookieNonce) {
|
||||
throw new Error('Auth response is missing cookie nonce');
|
||||
}
|
||||
if (!stateNonce) {
|
||||
throw new Error('Auth response is missing state nonce');
|
||||
}
|
||||
|
||||
if (cookieNonce !== stateNonce) {
|
||||
throw new Error('Invalid nonce');
|
||||
}
|
||||
@@ -151,9 +153,8 @@ export class OAuthProvider implements AuthProviderRouteHandlers {
|
||||
}
|
||||
|
||||
if (!this.options.disableRefresh) {
|
||||
// throw error if missing refresh token
|
||||
if (!refreshToken) {
|
||||
throw new Error('Missing refresh token');
|
||||
throw new InputError('Missing refresh token');
|
||||
}
|
||||
|
||||
// set new refresh token
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
"@material-ui/core": "^4.9.1",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@octokit/rest": "^18.0.0",
|
||||
"@octokit/types": "^5.0.1",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
|
||||
import { createApiRef } from '@backstage/core';
|
||||
import { Build, BuildDetails } from './types';
|
||||
import {
|
||||
ActionsListWorkflowRunsForRepoResponseData,
|
||||
ActionsGetWorkflowResponseData,
|
||||
ActionsGetWorkflowRunResponseData,
|
||||
} from '@octokit/types';
|
||||
|
||||
export const githubActionsApiRef = createApiRef<GithubActionsApi>({
|
||||
id: 'plugin.githubactions.service',
|
||||
@@ -23,14 +27,50 @@ export const githubActionsApiRef = createApiRef<GithubActionsApi>({
|
||||
});
|
||||
|
||||
export type GithubActionsApi = {
|
||||
listBuilds: ({
|
||||
listWorkflowRuns: ({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
token,
|
||||
pageSize,
|
||||
page,
|
||||
}: {
|
||||
token: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
pageSize?: number;
|
||||
page?: number;
|
||||
}) => Promise<ActionsListWorkflowRunsForRepoResponseData>;
|
||||
getWorkflow: ({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
id,
|
||||
}: {
|
||||
token: string;
|
||||
}) => Promise<Build[]>;
|
||||
getBuild: (buildUri: string, token: Promise<string>) => Promise<BuildDetails>;
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}) => Promise<ActionsGetWorkflowResponseData>;
|
||||
getWorkflowRun: ({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
id,
|
||||
}: {
|
||||
token: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}) => Promise<ActionsGetWorkflowRunResponseData>;
|
||||
reRunWorkflow: ({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
runId,
|
||||
}: {
|
||||
token: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
runId: number;
|
||||
}) => void;
|
||||
};
|
||||
|
||||
@@ -15,117 +15,88 @@
|
||||
*/
|
||||
|
||||
import { GithubActionsApi } from './GithubActionsApi';
|
||||
import { Build, BuildDetails, BuildStatus, WorkflowRun } from './types';
|
||||
|
||||
const statusToBuildStatus: { [status: string]: BuildStatus } = {
|
||||
success: BuildStatus.Success,
|
||||
failure: BuildStatus.Failure,
|
||||
pending: BuildStatus.Pending,
|
||||
running: BuildStatus.Running,
|
||||
in_progress: BuildStatus.Running,
|
||||
completed: BuildStatus.Success,
|
||||
};
|
||||
|
||||
const conclusionToStatus = (conslusion: string): BuildStatus =>
|
||||
statusToBuildStatus[conslusion] ?? BuildStatus.Null;
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import {
|
||||
ActionsListWorkflowRunsForRepoResponseData,
|
||||
ActionsGetWorkflowResponseData,
|
||||
ActionsGetWorkflowRunResponseData,
|
||||
} from '@octokit/types';
|
||||
|
||||
export class GithubActionsClient implements GithubActionsApi {
|
||||
async listBuilds({
|
||||
reRunWorkflow({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
token,
|
||||
runId,
|
||||
}: {
|
||||
token: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
token: string;
|
||||
}): Promise<Build[]> {
|
||||
const url = `https://api.github.com/repos/${owner}/${repo}/actions/runs`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
headers: new Headers({
|
||||
Authorization: `Bearer ${token}`,
|
||||
}),
|
||||
runId: number;
|
||||
}) {
|
||||
new Octokit({ auth: token }).actions.reRunWorkflow({
|
||||
owner,
|
||||
repo,
|
||||
run_id: runId,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return [
|
||||
{
|
||||
commitId: 'Error',
|
||||
message: 'Response status is not OK',
|
||||
branch: 'Error',
|
||||
status: BuildStatus.Failure,
|
||||
uri: 'Error',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
const newData: WorkflowRun[] = data.workflow_runs;
|
||||
|
||||
const endData: Build[] = [];
|
||||
|
||||
newData.forEach((element, index) => {
|
||||
const transData: Build = {
|
||||
commitId: '',
|
||||
message: '',
|
||||
branch: '',
|
||||
status: BuildStatus.Null,
|
||||
uri: '',
|
||||
};
|
||||
transData.commitId = String(element.head_commit.id);
|
||||
transData.branch = element.head_branch;
|
||||
transData.status = conclusionToStatus(element.conclusion);
|
||||
transData.message = element.head_commit.message;
|
||||
transData.uri = element.url;
|
||||
endData[index] = transData;
|
||||
});
|
||||
|
||||
return endData;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async getBuild(
|
||||
buildUri: string,
|
||||
token: Promise<string>,
|
||||
): Promise<BuildDetails> {
|
||||
const response = await fetch(buildUri, {
|
||||
headers: new Headers({
|
||||
Authorization: `Bearer ${await token}`,
|
||||
}),
|
||||
async listWorkflowRuns({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
pageSize = 100,
|
||||
page = 0,
|
||||
}: {
|
||||
token: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
pageSize?: number;
|
||||
page?: number;
|
||||
}): Promise<ActionsListWorkflowRunsForRepoResponseData> {
|
||||
const workflowRuns = await new Octokit({
|
||||
auth: token,
|
||||
}).actions.listWorkflowRunsForRepo({
|
||||
owner,
|
||||
repo,
|
||||
per_page: pageSize,
|
||||
page,
|
||||
});
|
||||
const buildBlank: Build = {
|
||||
commitId: '',
|
||||
message: '',
|
||||
branch: '',
|
||||
status: BuildStatus.Null,
|
||||
uri: '',
|
||||
};
|
||||
|
||||
const dataBlank: BuildDetails = {
|
||||
build: buildBlank,
|
||||
author: '',
|
||||
logUrl: '',
|
||||
overviewUrl: '',
|
||||
};
|
||||
|
||||
if (!response.ok) {
|
||||
return dataBlank;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
const newData: WorkflowRun = data;
|
||||
|
||||
dataBlank.author = newData.head_commit.author.name;
|
||||
dataBlank.build.branch = newData.head_branch;
|
||||
dataBlank.build.commitId = newData.head_commit.id;
|
||||
dataBlank.build.message = newData.head_commit.message;
|
||||
dataBlank.build.status = conclusionToStatus(newData.status);
|
||||
dataBlank.build.uri = newData.url;
|
||||
dataBlank.logUrl = newData.logs_url;
|
||||
dataBlank.overviewUrl = newData.html_url;
|
||||
|
||||
return dataBlank;
|
||||
return workflowRuns.data;
|
||||
}
|
||||
async getWorkflow({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
id,
|
||||
}: {
|
||||
token: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}): Promise<ActionsGetWorkflowResponseData> {
|
||||
const workflow = await new Octokit({ auth: token }).actions.getWorkflow({
|
||||
owner,
|
||||
repo,
|
||||
workflow_id: id,
|
||||
});
|
||||
return workflow.data;
|
||||
}
|
||||
async getWorkflowRun({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
id,
|
||||
}: {
|
||||
token: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}): Promise<ActionsGetWorkflowRunResponseData> {
|
||||
const run = await new Octokit({ auth: token }).actions.getWorkflowRun({
|
||||
owner,
|
||||
repo,
|
||||
run_id: id,
|
||||
});
|
||||
return run.data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
LinearProgress,
|
||||
makeStyles,
|
||||
Paper,
|
||||
@@ -29,9 +28,8 @@ import {
|
||||
Typography,
|
||||
} from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useAsync } from 'react-use';
|
||||
import { BuildStatusIndicator } from '../BuildStatusIndicator';
|
||||
import { Link, useApi, githubAuthApiRef } from '@backstage/core';
|
||||
import { githubActionsApiRef } from '../../api';
|
||||
|
||||
@@ -49,17 +47,26 @@ const useStyles = makeStyles<Theme>(theme => ({
|
||||
}));
|
||||
|
||||
export const BuildDetailsPage = () => {
|
||||
const repo = 'try-ssr';
|
||||
const owner = 'CircleCITest3';
|
||||
const api = useApi(githubActionsApiRef);
|
||||
const githubApi = useApi(githubAuthApiRef);
|
||||
const token = githubApi.getAccessToken('repo');
|
||||
const auth = useApi(githubAuthApiRef);
|
||||
|
||||
const classes = useStyles();
|
||||
const location = useLocation();
|
||||
const status = useAsync(
|
||||
() =>
|
||||
api.getBuild(decodeURIComponent(location.search.split('uri=')[1]), token),
|
||||
[location.search],
|
||||
);
|
||||
const { id } = useParams();
|
||||
const status = useAsync(async () => {
|
||||
const token = await auth.getAccessToken(['repo', 'user']);
|
||||
return api
|
||||
.getWorkflowRun({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
id: parseInt(id, 10),
|
||||
})
|
||||
.then(data => {
|
||||
return data;
|
||||
});
|
||||
}, [location.search]);
|
||||
|
||||
if (status.loading) {
|
||||
return <LinearProgress />;
|
||||
@@ -90,55 +97,42 @@ export const BuildDetailsPage = () => {
|
||||
<TableCell>
|
||||
<Typography noWrap>Branch</Typography>
|
||||
</TableCell>
|
||||
<TableCell>{details?.build.branch}</TableCell>
|
||||
<TableCell>{details?.head_branch}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography noWrap>Message</Typography>
|
||||
</TableCell>
|
||||
<TableCell>{details?.build.message}</TableCell>
|
||||
<TableCell>{details?.head_commit.message}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography noWrap>Commit ID</Typography>
|
||||
</TableCell>
|
||||
<TableCell>{details?.build.commitId}</TableCell>
|
||||
<TableCell>{details?.head_commit.id}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography noWrap>Status</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<BuildStatusIndicator status={details?.build.status} />
|
||||
</TableCell>
|
||||
<TableCell>{details?.status}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography noWrap>Author</Typography>
|
||||
</TableCell>
|
||||
<TableCell>{details?.author}</TableCell>
|
||||
<TableCell>{`${details?.head_commit.author.name} (${details?.head_commit.author.email})`}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography noWrap>Links</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<ButtonGroup
|
||||
variant="text"
|
||||
color="primary"
|
||||
aria-label="text primary button group"
|
||||
>
|
||||
{details?.overviewUrl && (
|
||||
<Button>
|
||||
<a href={details.overviewUrl}>GitHub</a>
|
||||
</Button>
|
||||
)}
|
||||
{details?.logUrl && (
|
||||
<Button>
|
||||
<a href={details.logUrl}>Logs</a>
|
||||
</Button>
|
||||
)}
|
||||
</ButtonGroup>
|
||||
{details?.html_url && (
|
||||
<Button>
|
||||
<a href={details.html_url}>GitHub</a>
|
||||
</Button>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import React from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import { BuildStatusIndicator } from '../BuildStatusIndicator';
|
||||
import { githubActionsApiRef } from '../../api';
|
||||
import { githubActionsApiRef, BuildStatus } from '../../api';
|
||||
import { Link, useApi, githubAuthApiRef } from '@backstage/core';
|
||||
|
||||
const useStyles = makeStyles<Theme>(theme => ({
|
||||
@@ -41,11 +41,11 @@ const useStyles = makeStyles<Theme>(theme => ({
|
||||
|
||||
const BuildInfoCardContent = () => {
|
||||
const api = useApi(githubActionsApiRef);
|
||||
const githubApi = useApi(githubAuthApiRef);
|
||||
const auth = useApi(githubAuthApiRef);
|
||||
|
||||
const status = useAsync(async () => {
|
||||
const token = await githubApi.getAccessToken('repo');
|
||||
return api.listBuilds({ owner: 'spotify', repo: 'backstage', token });
|
||||
const token = await auth.getAccessToken(['repo', 'user']);
|
||||
return api.listWorkflowRuns({ token, owner: 'spotify', repo: 'backstage' });
|
||||
});
|
||||
|
||||
if (status.loading) {
|
||||
@@ -58,8 +58,8 @@ const BuildInfoCardContent = () => {
|
||||
);
|
||||
}
|
||||
|
||||
const [build] =
|
||||
status.value?.filter(({ branch }) => branch === 'master') ?? [];
|
||||
// const [build] =
|
||||
// status.value?.filter(({ branch }) => branch === 'master') ?? [];
|
||||
|
||||
return (
|
||||
<Table>
|
||||
@@ -69,8 +69,8 @@ const BuildInfoCardContent = () => {
|
||||
<Typography noWrap>Message</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Link to={`builds/${encodeURIComponent(build?.uri || '')}`}>
|
||||
<Typography color="primary">{build?.message}</Typography>
|
||||
<Link to="builds/123">
|
||||
<Typography color="primary">build message</Typography>
|
||||
</Link>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -78,14 +78,14 @@ const BuildInfoCardContent = () => {
|
||||
<TableCell>
|
||||
<Typography noWrap>Commit ID</Typography>
|
||||
</TableCell>
|
||||
<TableCell>{build?.commitId}</TableCell>
|
||||
<TableCell>build commit id</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography noWrap>Status</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<BuildStatusIndicator status={build?.status} />
|
||||
<BuildStatusIndicator status={BuildStatus.Success} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
|
||||
@@ -47,7 +47,7 @@ export const BuildListPage = () => {
|
||||
</ContentHeader>
|
||||
<Grid container spacing={3} direction="column">
|
||||
<Grid item>
|
||||
<BuildListTable />
|
||||
<BuildListTable repo="try-ssr" owner="CircleCITest3" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Content>
|
||||
|
||||
@@ -74,7 +74,7 @@ const generatedColumns: TableColumn[] = [
|
||||
field: 'buildName',
|
||||
highlight: true,
|
||||
render: (row: Partial<Build>) => (
|
||||
<Link component={RouterLink} to={`/build/${row.id}`}>
|
||||
<Link component={RouterLink} to={`/github-actions/build/${row.id}`}>
|
||||
{row.buildName}
|
||||
</Link>
|
||||
),
|
||||
@@ -161,16 +161,23 @@ const BuildListTableView: FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
export const BuildListTable = () => {
|
||||
const [tableProps] = useBuilds();
|
||||
export const BuildListTable = ({
|
||||
repo,
|
||||
owner,
|
||||
}: {
|
||||
repo: string;
|
||||
owner: string;
|
||||
}) => {
|
||||
const [tableProps, { retry, setPage, setPageSize }] = useBuilds({
|
||||
repo,
|
||||
owner,
|
||||
});
|
||||
return (
|
||||
<BuildListTableView
|
||||
{...tableProps}
|
||||
retry={noop}
|
||||
onChangePageSize={noop}
|
||||
onChangePage={noop}
|
||||
retry={retry}
|
||||
onChangePageSize={setPageSize}
|
||||
onChangePage={setPage}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,301 +13,62 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useAsyncRetry } from 'react-use';
|
||||
import { Build } from './BuildListTable';
|
||||
import { githubActionsApiRef } from '../../api/GithubActionsApi';
|
||||
import { useApi, githubAuthApiRef } from '@backstage/core';
|
||||
import { ActionsListWorkflowRunsForRepoResponseData } from '@octokit/types';
|
||||
|
||||
// TODO(shmidt-i): use real APIs
|
||||
const useEntityGHSettings = () => ({ repo: 'test', owner: 'shmidt-i-test' });
|
||||
const buildsMock = {
|
||||
total_count: 1,
|
||||
workflow_runs: [
|
||||
{
|
||||
id: 30433642,
|
||||
node_id: 'MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ==',
|
||||
head_branch: 'master',
|
||||
head_sha: 'acb5820ced9479c074f688cc328bf03f341a511d',
|
||||
run_number: 562,
|
||||
event: 'push',
|
||||
status: 'queued',
|
||||
conclusion: null,
|
||||
workflow_id: 159038,
|
||||
url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642',
|
||||
html_url: 'https://github.com/octo-org/octo-repo/actions/runs/30433642',
|
||||
pull_requests: [],
|
||||
created_at: '2020-01-22T19:33:08Z',
|
||||
updated_at: '2020-01-22T19:33:08Z',
|
||||
jobs_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs',
|
||||
logs_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs',
|
||||
check_suite_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/check-suites/414944374',
|
||||
artifacts_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts',
|
||||
cancel_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel',
|
||||
rerun_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun',
|
||||
workflow_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038',
|
||||
head_commit: {
|
||||
id: 'acb5820ced9479c074f688cc328bf03f341a511d',
|
||||
tree_id: 'd23f6eedb1e1b9610bbc754ddb5197bfe7271223',
|
||||
message: 'Create linter.yml',
|
||||
timestamp: '2020-01-22T19:33:05Z',
|
||||
author: {
|
||||
name: 'Octo Cat',
|
||||
email: 'octocat@github.com',
|
||||
},
|
||||
committer: {
|
||||
name: 'GitHub',
|
||||
email: 'noreply@github.com',
|
||||
},
|
||||
},
|
||||
repository: {
|
||||
id: 1296269,
|
||||
node_id: 'MDEwOlJlcG9zaXRvcnkxMjk2MjY5',
|
||||
name: 'Hello-World',
|
||||
full_name: 'octocat/Hello-World',
|
||||
owner: {
|
||||
login: 'octocat',
|
||||
id: 1,
|
||||
node_id: 'MDQ6VXNlcjE=',
|
||||
avatar_url: 'https://github.com/images/error/octocat_happy.gif',
|
||||
gravatar_id: '',
|
||||
url: 'https://api.github.com/users/octocat',
|
||||
html_url: 'https://github.com/octocat',
|
||||
followers_url: 'https://api.github.com/users/octocat/followers',
|
||||
following_url:
|
||||
'https://api.github.com/users/octocat/following{/other_user}',
|
||||
gists_url: 'https://api.github.com/users/octocat/gists{/gist_id}',
|
||||
starred_url:
|
||||
'https://api.github.com/users/octocat/starred{/owner}{/repo}',
|
||||
subscriptions_url:
|
||||
'https://api.github.com/users/octocat/subscriptions',
|
||||
organizations_url: 'https://api.github.com/users/octocat/orgs',
|
||||
repos_url: 'https://api.github.com/users/octocat/repos',
|
||||
events_url: 'https://api.github.com/users/octocat/events{/privacy}',
|
||||
received_events_url:
|
||||
'https://api.github.com/users/octocat/received_events',
|
||||
type: 'User',
|
||||
site_admin: false,
|
||||
},
|
||||
private: false,
|
||||
html_url: 'https://github.com/octocat/Hello-World',
|
||||
description: 'This your first repo!',
|
||||
fork: false,
|
||||
url: 'https://api.github.com/repos/octocat/Hello-World',
|
||||
archive_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}',
|
||||
assignees_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/assignees{/user}',
|
||||
blobs_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}',
|
||||
branches_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/branches{/branch}',
|
||||
collaborators_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}',
|
||||
comments_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/comments{/number}',
|
||||
commits_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/commits{/sha}',
|
||||
compare_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}',
|
||||
contents_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/contents/{+path}',
|
||||
contributors_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/contributors',
|
||||
deployments_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/deployments',
|
||||
downloads_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/downloads',
|
||||
events_url: 'http://api.github.com/repos/octocat/Hello-World/events',
|
||||
forks_url: 'http://api.github.com/repos/octocat/Hello-World/forks',
|
||||
git_commits_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}',
|
||||
git_refs_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}',
|
||||
git_tags_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}',
|
||||
git_url: 'git:github.com/octocat/Hello-World.git',
|
||||
issue_comment_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}',
|
||||
issue_events_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/issues/events{/number}',
|
||||
issues_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/issues{/number}',
|
||||
keys_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/keys{/key_id}',
|
||||
labels_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/labels{/name}',
|
||||
languages_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/languages',
|
||||
merges_url: 'http://api.github.com/repos/octocat/Hello-World/merges',
|
||||
milestones_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/milestones{/number}',
|
||||
notifications_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}',
|
||||
pulls_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/pulls{/number}',
|
||||
releases_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/releases{/id}',
|
||||
ssh_url: 'git@github.com:octocat/Hello-World.git',
|
||||
stargazers_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/stargazers',
|
||||
statuses_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/statuses/{sha}',
|
||||
subscribers_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/subscribers',
|
||||
subscription_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/subscription',
|
||||
tags_url: 'http://api.github.com/repos/octocat/Hello-World/tags',
|
||||
teams_url: 'http://api.github.com/repos/octocat/Hello-World/teams',
|
||||
trees_url:
|
||||
'http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}',
|
||||
},
|
||||
head_repository: {
|
||||
id: 217723378,
|
||||
node_id: 'MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg=',
|
||||
name: 'octo-repo',
|
||||
full_name: 'octo-org/octo-repo',
|
||||
private: true,
|
||||
owner: {
|
||||
login: 'octocat',
|
||||
id: 1,
|
||||
node_id: 'MDQ6VXNlcjE=',
|
||||
avatar_url: 'https://github.com/images/error/octocat_happy.gif',
|
||||
gravatar_id: '',
|
||||
url: 'https://api.github.com/users/octocat',
|
||||
html_url: 'https://github.com/octocat',
|
||||
followers_url: 'https://api.github.com/users/octocat/followers',
|
||||
following_url:
|
||||
'https://api.github.com/users/octocat/following{/other_user}',
|
||||
gists_url: 'https://api.github.com/users/octocat/gists{/gist_id}',
|
||||
starred_url:
|
||||
'https://api.github.com/users/octocat/starred{/owner}{/repo}',
|
||||
subscriptions_url:
|
||||
'https://api.github.com/users/octocat/subscriptions',
|
||||
organizations_url: 'https://api.github.com/users/octocat/orgs',
|
||||
repos_url: 'https://api.github.com/users/octocat/repos',
|
||||
events_url: 'https://api.github.com/users/octocat/events{/privacy}',
|
||||
received_events_url:
|
||||
'https://api.github.com/users/octocat/received_events',
|
||||
type: 'User',
|
||||
site_admin: false,
|
||||
},
|
||||
html_url: 'https://github.com/octo-org/octo-repo',
|
||||
description: null,
|
||||
fork: false,
|
||||
url: 'https://api.github.com/repos/octo-org/octo-repo',
|
||||
forks_url: 'https://api.github.com/repos/octo-org/octo-repo/forks',
|
||||
keys_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}',
|
||||
collaborators_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}',
|
||||
teams_url: 'https://api.github.com/repos/octo-org/octo-repo/teams',
|
||||
hooks_url: 'https://api.github.com/repos/octo-org/octo-repo/hooks',
|
||||
issue_events_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}',
|
||||
events_url: 'https://api.github.com/repos/octo-org/octo-repo/events',
|
||||
assignees_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/assignees{/user}',
|
||||
branches_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/branches{/branch}',
|
||||
tags_url: 'https://api.github.com/repos/octo-org/octo-repo/tags',
|
||||
blobs_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}',
|
||||
git_tags_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}',
|
||||
git_refs_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}',
|
||||
trees_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}',
|
||||
statuses_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}',
|
||||
languages_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/languages',
|
||||
stargazers_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/stargazers',
|
||||
contributors_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/contributors',
|
||||
subscribers_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/subscribers',
|
||||
subscription_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/subscription',
|
||||
commits_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/commits{/sha}',
|
||||
git_commits_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}',
|
||||
comments_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/comments{/number}',
|
||||
issue_comment_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}',
|
||||
contents_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/contents/{+path}',
|
||||
compare_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}',
|
||||
merges_url: 'https://api.github.com/repos/octo-org/octo-repo/merges',
|
||||
archive_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}',
|
||||
downloads_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/downloads',
|
||||
issues_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/issues{/number}',
|
||||
pulls_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/pulls{/number}',
|
||||
milestones_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/milestones{/number}',
|
||||
notifications_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}',
|
||||
labels_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/labels{/name}',
|
||||
releases_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/releases{/id}',
|
||||
deployments_url:
|
||||
'https://api.github.com/repos/octo-org/octo-repo/deployments',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function useBuilds() {
|
||||
const { repo, owner } = useEntityGHSettings();
|
||||
export function useBuilds({ repo, owner }: { repo: string; owner: string }) {
|
||||
const api = useApi(githubActionsApiRef);
|
||||
const auth = useApi(githubAuthApiRef);
|
||||
|
||||
const [total, setTotal] = useState(0);
|
||||
const [page, setPage] = useState(0);
|
||||
const [pageSize, setPageSize] = useState(5);
|
||||
const getBuilds = useCallback(async () => buildsMock, []);
|
||||
|
||||
const restartBuild = async () => {};
|
||||
|
||||
const { loading, value: builds, retry } = useAsyncRetry(
|
||||
() =>
|
||||
getBuilds().then((allBuilds): Build[] => {
|
||||
setTotal(allBuilds.total_count);
|
||||
// Transformation here
|
||||
return allBuilds.workflow_runs.map(run => ({
|
||||
buildName: run.head_commit.message,
|
||||
id: `${run.id}`,
|
||||
onRestartClick: () => {},
|
||||
source: {
|
||||
branchName: run.head_branch,
|
||||
commit: {
|
||||
hash: run.head_commit.id,
|
||||
url: run.head_repository.branches_url.replace(
|
||||
'{/branch}',
|
||||
run.head_branch,
|
||||
),
|
||||
},
|
||||
const { loading, value: builds, retry } = useAsyncRetry<Build[]>(async () => {
|
||||
const token = await auth.getAccessToken(['repo', 'user']);
|
||||
|
||||
return (
|
||||
api
|
||||
// GitHub API pagination count starts from 1
|
||||
.listWorkflowRuns({ token, owner, repo, pageSize, page: page + 1 })
|
||||
.then(
|
||||
(allBuilds: ActionsListWorkflowRunsForRepoResponseData): Build[] => {
|
||||
setTotal(allBuilds.total_count);
|
||||
// Transformation here
|
||||
return allBuilds.workflow_runs.map(run => ({
|
||||
buildName: run.head_commit.message,
|
||||
id: `${run.id}`,
|
||||
onRestartClick: () => {
|
||||
api.reRunWorkflow({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
runId: run.id,
|
||||
});
|
||||
},
|
||||
source: {
|
||||
branchName: run.head_branch,
|
||||
commit: {
|
||||
hash: run.head_commit.id,
|
||||
url: run.head_repository.branches_url.replace(
|
||||
'{/branch}',
|
||||
run.head_branch,
|
||||
),
|
||||
},
|
||||
},
|
||||
status: run.status,
|
||||
buildUrl: run.url,
|
||||
}));
|
||||
},
|
||||
status: run.status,
|
||||
buildUrl: run.url,
|
||||
}));
|
||||
}),
|
||||
[page, pageSize, getBuilds],
|
||||
);
|
||||
)
|
||||
);
|
||||
}, [page, pageSize]);
|
||||
|
||||
const projectName = `${owner}/${repo}`;
|
||||
return [
|
||||
@@ -320,7 +81,7 @@ export function useBuilds() {
|
||||
total,
|
||||
},
|
||||
{
|
||||
getBuilds,
|
||||
builds,
|
||||
setPage,
|
||||
setPageSize,
|
||||
restartBuild,
|
||||
|
||||
@@ -24,7 +24,7 @@ export const rootRouteRef = createRouteRef({
|
||||
title: 'GitHub Actions',
|
||||
});
|
||||
export const buildRouteRef = createRouteRef({
|
||||
path: '/github-actions/builds',
|
||||
path: '/github-actions/build/:id',
|
||||
title: 'GitHub Actions Build',
|
||||
});
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ export const ScaffolderPage: React.FC<{}> = () => {
|
||||
}, [error, errorApi]);
|
||||
|
||||
return (
|
||||
<Page theme={pageTheme.home}>
|
||||
<Page theme={pageTheme.other}>
|
||||
<Header
|
||||
pageTitleOverride="Create a new component"
|
||||
title={
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Button } from '@backstage/core';
|
||||
import { Button, pageTheme } from '@backstage/core';
|
||||
import { Card, Chip, makeStyles, Typography } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
@@ -23,8 +23,8 @@ const useStyles = makeStyles(theme => ({
|
||||
header: {
|
||||
color: theme.palette.common.white,
|
||||
padding: theme.spacing(2, 2, 6),
|
||||
backgroundImage:
|
||||
'linear-gradient(-137deg, rgb(25, 230, 140) 0%, rgb(29, 127, 110) 100%)',
|
||||
backgroundImage: (props: { gradientStart: string; gradientStop: string }) =>
|
||||
`linear-gradient(-137deg, ${props.gradientStart} 0%, ${props.gradientStop} 100%)`,
|
||||
},
|
||||
content: {
|
||||
padding: theme.spacing(2),
|
||||
@@ -55,7 +55,9 @@ export const TemplateCard = ({
|
||||
type,
|
||||
name,
|
||||
}: TemplateCardProps) => {
|
||||
const classes = useStyles();
|
||||
const theme = pageTheme[type] ?? pageTheme.other;
|
||||
const [gradientStart, gradientStop] = theme.gradient.colors;
|
||||
const classes = useStyles({ gradientStart, gradientStop });
|
||||
const href = generatePath(templateRoute.path, { templateName: name });
|
||||
|
||||
return (
|
||||
@@ -72,7 +74,7 @@ export const TemplateCard = ({
|
||||
{description}
|
||||
</Typography>
|
||||
<div className={classes.footer}>
|
||||
<Button color="primary" variant="contained" to={href}>
|
||||
<Button color="primary" to={href}>
|
||||
Choose
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
Lifecycle,
|
||||
Page,
|
||||
useApi,
|
||||
pageTheme,
|
||||
} from '@backstage/core';
|
||||
import { catalogApiRef } from '@backstage/plugin-catalog';
|
||||
import { LinearProgress } from '@material-ui/core';
|
||||
@@ -135,7 +136,7 @@ export const TemplatePage = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Page theme={pageTheme.other}>
|
||||
<Header
|
||||
pageTitleOverride="Create a new component"
|
||||
title={
|
||||
|
||||
@@ -8077,10 +8077,10 @@ es6-shim@^0.35.5:
|
||||
resolved "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.5.tgz#46f59dc0a84a1c5029e8ff1166ca0a902077a9ab"
|
||||
integrity sha512-E9kK/bjtCQRpN1K28Xh4BlmP8egvZBGJJ+9GtnzOwt7mdqtrjHFuVGr7QJfdjBIKqrlU5duPf3pCBoDrkjVYFg==
|
||||
|
||||
esbuild@^0.5.3:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.5.3.tgz#18f5bdb618220c6f14bcb1cf5af528d02d4734c9"
|
||||
integrity sha512-RVzTK62svYjnh+agJRh+NWfZX74iKwFNUX52cF7Mo4QPS6bKxP1o+8GacPUMND2QnodVp2D3nKJs8gLspSfZzA==
|
||||
esbuild@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.6.3.tgz#a957e22f2503c745793514388110f9b55b3a6f83"
|
||||
integrity sha512-4lHgz/EvGLRQnDYzzrvW+eilaPHim5pCLz4mP0k0QIalD/n8Ji2NwQwoIa1uX+yKkbn9R/FAZvaEbodjx55rDg==
|
||||
|
||||
escape-goat@^2.0.0:
|
||||
version "2.1.1"
|
||||
@@ -16480,12 +16480,11 @@ rollup-plugin-dts@^1.4.6:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
|
||||
rollup-plugin-esbuild@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.1.0.tgz#8e12337c63a5b1144e0c5e8adf2f1568ad4d7d69"
|
||||
integrity sha512-XYqmwk4X0SPEExgilARbre/PplhLtE3q6wiZtfgIbwxJOVGXWec1Bkcux7TFTHGX3TQozzqEASTsRJCt7py/5Q==
|
||||
version "2.3.0"
|
||||
resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.3.0.tgz#7c107d4508af80d30966a148b306cb7d5b36b258"
|
||||
integrity sha512-lNbWDRaClwXauaIybuaiOBRWgxcp3GkZu0UUix9yH/OHFgVohKmzlU0NtNbvfbxAcfEooyuBRAv6YCaJl1Mbpw==
|
||||
dependencies:
|
||||
"@rollup/pluginutils" "^3.1.0"
|
||||
esbuild "^0.5.3"
|
||||
|
||||
rollup-plugin-image-files@^1.4.2:
|
||||
version "1.4.2"
|
||||
|
||||
Reference in New Issue
Block a user